import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'
import {
  canApproveAgentProposal,
  canRejectAgentProposal,
  canRetryAgentProposal,
  getAgentProposalStatusMeta,
  type AgentProposalDto,
} from '../src/api/agentProposals'
import { apiFetch } from '../src/services/api'
import { useAuthStore } from '../src/stores/auth'

const baseProposal: AgentProposalDto = {
  id: '0d2d33d7-bafa-4510-b135-c6a96021957a',
  source: 'manual',
  requestedName: 'Release Coordinator',
  requestedAgentId: 'release-coordinator',
  role: 'Delivery Operations',
  description: 'Coordinates releases.',
  model: null,
  emoji: null,
  avatar: null,
  workspace: '/managed/workspace-release-coordinator',
  files: [],
  status: 'awaiting_approval',
  requestedBy: 'bao',
  approvedBy: null,
  rejectedBy: null,
  rejectionReason: null,
  openClawAgentId: null,
  openClawWorkspace: null,
  error: null,
  revision: 1,
  createdAt: '2026-07-31T08:00:00.000Z',
  updatedAt: '2026-07-31T08:00:00.000Z',
  approvedAt: null,
  rejectedAt: null,
  completedAt: null,
}

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

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

describe('agent proposal frontend contract', () => {
  it('maps lifecycle states to safe owner actions', () => {
    expect(getAgentProposalStatusMeta('awaiting_approval').label).toBe('Freigabe offen')
    expect(canApproveAgentProposal(baseProposal)).toBe(true)
    expect(canRejectAgentProposal(baseProposal)).toBe(true)
    expect(canRetryAgentProposal(baseProposal)).toBe(false)

    const failed = { ...baseProposal, status: 'failed' }
    expect(canApproveAgentProposal(failed)).toBe(false)
    expect(canRejectAgentProposal(failed)).toBe(false)
    expect(canRetryAgentProposal(failed)).toBe(true)
    expect(canRetryAgentProposal({ ...baseProposal, status: 'in_doubt' })).toBe(true)
  })

  it('preserves generated Request headers through the authenticated fetch boundary', async () => {
    const fetchMock = vi.fn(async () => new Response(JSON.stringify({ ok: true }), {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    }))
    vi.stubGlobal('fetch', fetchMock)

    const request = new Request('http://localhost/api/v1/openclaw/agent-proposals', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Idempotency-Key': 'agent-proposal-create:test',
        'X-Correlation-ID': 'd4f72d7d-6331-4bcc-87e8-e74480315073',
      },
      body: JSON.stringify({ name: 'Release Coordinator' }),
    })

    await apiFetch(request)

    const [, init] = fetchMock.mock.calls[0]
    const headers = new Headers(init?.headers)
    expect(headers.get('Authorization')).toBe('Bearer proposal-access-token')
    expect(headers.get('Content-Type')).toBe('application/json')
    expect(headers.get('Idempotency-Key')).toBe('agent-proposal-create:test')
    expect(headers.get('X-Correlation-ID')).toBe('d4f72d7d-6331-4bcc-87e8-e74480315073')
  })
})
