import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'
import {
  fetchOpenClawModelAuthStatus,
  refreshOpenClawModelAuthStatus,
  type OpenClawModelAuthCollectionDto,
} from '../src/api/openClawModels'
import { queryClient, queryKeys } from '../src/api/queryClient'
import { useAuthStore } from '../src/stores/auth'

function collection(status: string): OpenClawModelAuthCollectionDto {
  return {
    state: 'ready',
    items: [{
      provider: 'openai',
      displayName: 'OpenAI',
      status,
      expiry: null,
      profiles: [{ type: 'oauth', status: 'ok', count: 1 }],
      apiKey: null,
      usage: { summary: 'Ready', plan: 'team' },
    }],
    nextCursor: null,
    message: null,
    recovery: null,
    checkedAt: '2026-07-31T10:00:00.000Z',
  }
}

function requestUrl(input: RequestInfo | URL): URL {
  const raw = input instanceof Request ? input.url : String(input)
  return new URL(raw, 'http://localhost')
}

beforeEach(() => {
  setActivePinia(createPinia())
  const auth = useAuthStore()
  auth.initialized = true
  auth.applySession({
    accessToken: 'models-access-token',
    expiresAt: '2026-07-31T12:00:00.000Z',
    user: {
      id: 'bao',
      email: 'bao@nexus.local',
      displayName: 'Bao',
      role: 'owner',
    },
  })
  queryClient.clear()
})

afterEach(() => {
  queryClient.clear()
  vi.unstubAllGlobals()
})

describe('OpenClaw model authentication query', () => {
  it('loads the generated sanitized contract without forcing a gateway refresh', async () => {
    const fetchMock = vi.fn(async () => new Response(JSON.stringify(collection('ok')), {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    }))
    vi.stubGlobal('fetch', fetchMock)

    await expect(fetchOpenClawModelAuthStatus()).resolves.toEqual(collection('ok'))

    const [input, init] = fetchMock.mock.calls[0]!
    const url = requestUrl(input)
    expect(url.pathname).toBe('/api/v1/openclaw/models/auth-status')
    expect(url.searchParams.get('refresh')).toBe('false')
    expect(new Headers(init?.headers).get('Authorization')).toBe('Bearer models-access-token')
  })

  it('forces a refresh through the same canonical query cache', async () => {
    queryClient.setQueryData(queryKeys.openClawModelAuth(), collection('stale'))
    const fetchMock = vi.fn(async () => new Response(JSON.stringify(collection('ok')), {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    }))
    vi.stubGlobal('fetch', fetchMock)

    await expect(refreshOpenClawModelAuthStatus()).resolves.toEqual(collection('ok'))

    const url = requestUrl(fetchMock.mock.calls[0]![0])
    expect(url.searchParams.get('refresh')).toBe('true')
    expect(queryClient.getQueryData(queryKeys.openClawModelAuth())).toEqual(collection('ok'))
  })
})
