import { afterEach, describe, mock, test } from 'node:test';
import assert from 'node:assert/strict';

import db from '@/db/models';
import ZoneCheckinService from '@/services/zone-checkin';
import UserProgressService from '@/services/user_progress';
import ForbiddenError from '@/shared/errors/forbidden';
import { FEATURE_PERMISSIONS } from '@/shared/constants/product-permissions';
import { ROLE_NAMES } from '@/shared/constants/roles';
import { createGlobalAccessUser, createTestUser } from '@/test-utils';
import type { CurrentUser } from '@/db/api/types';

function user(roleName: string): CurrentUser {
  return createTestUser({
    campusId: 'campus-1',
    app_role: {
      name: roleName,
      globalAccess: false,
      permissions: [{ name: FEATURE_PERMISSIONS.ZONE_CHECKIN }],
    },
  });
}

afterEach(() => {
  mock.restoreAll();
});

describe('ZoneCheckinService role eligibility', () => {
  test('rejects global access without explicit ZONE_CHECKIN', async () => {
    const rejectedUsers = [
      createGlobalAccessUser(),
    ];

    for (const currentUser of rejectedUsers) {
      await assert.rejects(
        () => ZoneCheckinService.today(currentUser),
        ForbiddenError,
      );
    }
  });

  test('allows an explicit ZONE_CHECKIN permission regardless of role name', async () => {
    mock.method(db.campuses, 'findByPk', (async () => ({
      timezone: 'America/Phoenix',
    })) as typeof db.campuses.findByPk);
    mock.method(UserProgressService, 'list', (async () => ({
      rows: [],
      count: 0,
    })) as typeof UserProgressService.list);

    const result = await ZoneCheckinService.today(user(ROLE_NAMES.OWNER));

    assert.equal(result.zone, null);
    assert.equal(result.isCheckedInToday, false);
  });

  test('allows a campus workflow role to read today status', async () => {
    mock.method(db.campuses, 'findByPk', (async () => ({
      timezone: 'America/Phoenix',
    })) as typeof db.campuses.findByPk);
    mock.method(UserProgressService, 'list', (async () => ({
      rows: [],
      count: 0,
    })) as typeof UserProgressService.list);

    const result = await ZoneCheckinService.today(user(ROLE_NAMES.TEACHER));

    assert.equal(result.zone, null);
    assert.equal(result.isCheckedInToday, false);
    assert.match(result.date, /^\d{4}-\d{2}-\d{2}$/);
  });
});
