// getUserSession blocked-account-status tests — SEC-018 / Batch 6.
//
// Verifies that a profile with account_status in { locked, inactive, deleted,
// deactivated } causes getUserSession() to return null, which in turn causes
// any admin route to return 401.
//
// Strategy: mock @/lib/supabase/server so getClaims() returns a valid JWT
// but the user_profiles query returns a profile with a blocked account_status.
// We then call an admin route handler and assert it returns 401 — which proves
// getUserSession() returned null for that profile.
//
// This is the practical "feasible with Supabase mock" approach described in the
// Batch 6 brief: we mock getClaims + from().select().single() to simulate the
// blocked-status path.

import { describe, it, expect, vi, beforeEach } from 'vitest'

// Minimal Supabase mock — returns a valid JWT claim but a profile with a
// configurable account_status.
function makeBlockedSupabaseMock(account_status: string) {
  const profileRow = {
    id:                 'user-1',
    auth_user_id:       'auth-1',
    first_name:         'Test',
    last_name:          'User',
    display_name:       'Test User',
    email:              'test@example.com',
    avatar_url:         null,
    department_id:      null,
    must_change_password: false,
    account_status,
    role_id:            'role-1',
    roles:              { code: 'admin' },
  }

  // Chainable query builder that terminates with the profile row
  function makeProfileChain() {
    const chain: Record<string, unknown> = {}
    chain.select = vi.fn(() => chain)
    chain.eq     = vi.fn(() => chain)
    chain.is     = vi.fn(() => chain)
    chain.single = vi.fn(() => Promise.resolve({ data: profileRow, error: null }))
    return chain
  }

  // role_permissions query — returns empty (irrelevant for blocked path)
  function makeRolePermsChain() {
    const chain: Record<string, unknown> = {}
    chain.select = vi.fn(() => chain)
    chain.eq     = vi.fn(() => chain)
    chain.then   = (resolve: (v: unknown) => unknown) =>
      Promise.resolve({ data: [], error: null }).then(resolve)
    return chain
  }

  let callCount = 0
  const supabase = {
    auth: {
      getClaims: vi.fn(() =>
        Promise.resolve({ data: { claims: { sub: 'auth-1' } }, error: null })
      ),
    },
    from: vi.fn((table: string) => {
      if (table === 'user_profiles') {
        callCount++
        return makeProfileChain()
      }
      if (table === 'role_permissions') return makeRolePermsChain()
      // Fallback chain for other tables
      const c: Record<string, unknown> = {}
      c.select = vi.fn(() => c)
      c.eq     = vi.fn(() => c)
      c.is     = vi.fn(() => c)
      c.single = vi.fn(() => Promise.resolve({ data: null, error: null }))
      c.then   = (resolve: (v: unknown) => unknown) =>
        Promise.resolve({ data: null, error: null }).then(resolve)
      return c
    }),
    _callCount: () => callCount,
  }
  return supabase
}

// ─── Module mock wiring ───────────────────────────────────────────────────────

let currentMock = makeBlockedSupabaseMock('active')

vi.mock('@/lib/supabase/server', () => ({
  createClient: vi.fn(() => Promise.resolve(currentMock)),
}))

beforeEach(() => {
  vi.clearAllMocks()
  // Reset the permissions mock so getUserSession() is the real implementation
  // (it reads from createClient which is mocked above).
})

// ─── Tests ────────────────────────────────────────────────────────────────────

// For each blocked status, call GET /api/admin/audit and expect 401.
// That route calls getUserSession() internally; if getUserSession returns null
// (because of the blocked status), the route returns 401.

const BLOCKED_STATUSES = ['locked', 'inactive', 'deleted', 'deactivated'] as const

describe('getUserSession — blocked account_status yields null → route returns 401', () => {
  for (const status of BLOCKED_STATUSES) {
    it(`account_status="${status}" → GET /api/admin/audit returns 401`, async () => {
      currentMock = makeBlockedSupabaseMock(status)

      // Re-import the permissions module without the vi.mock override so
      // getUserSession runs its real logic against our mocked Supabase.
      // The route imports getUserSession from @/lib/auth/permissions — we
      // need that to be the real function using our mocked createClient.
      vi.doMock('@/lib/auth/permissions', async () => {
        // Return the real module; createClient is already mocked above.
        const real = await vi.importActual<typeof import('@/lib/auth/permissions')>('@/lib/auth/permissions')
        return real
      })
      vi.doMock('@/lib/supabase/server', () => ({
        createClient: vi.fn(() => Promise.resolve(currentMock)),
      }))

      // Dynamically import the audit route after mocks are updated.
      const { GET } = await import('@/app/api/admin/audit/route')
      const req = new Request('http://localhost/api/admin/audit')
      const res = await GET(req as Parameters<typeof GET>[0])

      expect(res.status).toBe(401)
    })
  }
})
