import { beforeEach, describe, expect, it, vi } from 'vitest'
import { Hono } from 'hono'
import type { AppEnv } from '../src/types'

const mockCreateDb = vi.fn(() => ({}))
const mockGetSignatoryByToken = vi.fn()
const mockGetTenantById = vi.fn()
const mockGetWhiteLabelConfig = vi.fn()
const mockListSignatories = vi.fn()
const mockRecordContractView = vi.fn()
const mockSignContractByToken = vi.fn()
const mockDeclineContract = vi.fn()
const mockRecordContractAuditEvent = vi.fn()
const mockSignKbUrl = vi.fn()

vi.mock('@zync/db/queries', () => ({
  createDb: (...args: unknown[]) => mockCreateDb(...args),
  getSignatoryByToken: (...args: unknown[]) => mockGetSignatoryByToken(...args),
  getTenantById: (...args: unknown[]) => mockGetTenantById(...args),
  getWhiteLabelConfig: (...args: unknown[]) => mockGetWhiteLabelConfig(...args),
  listSignatories: (...args: unknown[]) => mockListSignatories(...args),
  recordContractView: (...args: unknown[]) => mockRecordContractView(...args),
  signContractByToken: (...args: unknown[]) => mockSignContractByToken(...args),
  declineContract: (...args: unknown[]) => mockDeclineContract(...args),
  recordContractAuditEvent: (...args: unknown[]) => mockRecordContractAuditEvent(...args),
}))

vi.mock('../src/lib/kb-storage', () => ({
  signKbUrl: (...args: unknown[]) => mockSignKbUrl(...args),
}))

import { signRoute } from '../src/routes/sign'
function makeApp() {
  const app = new Hono<AppEnv>()
  app.route('/api/sign', signRoute)
  return app
}

const bindings = {
  RATE_LIMITER_SIGN: { limit: vi.fn().mockResolvedValue({ success: true }) },
} as unknown as AppEnv['Bindings']

describe('contract signing page route contracts', () => {
  beforeEach(() => {
    vi.clearAllMocks()

    mockGetSignatoryByToken.mockResolvedValue({
      signatoryId: 'sig-1',
      contractId: 'contract-1',
      tenantId: 'tenant-1',
      email: 'dana@example.com',
      name: 'Dana Recipient',
      order: 2,
      tokenExpiresAt: '2026-06-01T00:00:00.000Z',
      signedAt: null,
      declinedAt: null,
      declinedReason: null,
      contract: {
        title: 'Master Services Agreement',
        content: '<p>Contract body</p>',
        status: 'sent',
        signingDeadline: '2026-08-15T00:00:00.000Z',
        signedPdfR2Key: 'contracts/signed.pdf',
        customerId: null,
      },
    })
    mockGetTenantById.mockResolvedValue({
      id: 'tenant-1',
      name: 'Acme Studio',
      settings: { locale: 'en' },
    })
    mockGetWhiteLabelConfig.mockResolvedValue({
      logoUrl: 'logos/acme.png',
      primaryColor: '#123456',
      customDomain: null,
      portalDomain: null,
      sslStatus: 'pending',
    })
    mockListSignatories.mockResolvedValue([
      {
        id: 'sig-0',
        order: 1,
        signedAt: null,
        declinedAt: null,
        name: 'Avi Approver',
        email: 'avi@example.com',
      },
      {
        id: 'sig-1',
        order: 2,
        signedAt: null,
        declinedAt: null,
        name: 'Dana Recipient',
        email: 'dana@example.com',
      },
    ])
    mockRecordContractView.mockResolvedValue(undefined)
    mockSignKbUrl.mockResolvedValue('https://signed.example.test/contract.pdf')
  })

  it('returns expired and waiting payload context instead of treating the token as not-found', async () => {
    const app = makeApp()

    const response = await app.request('/api/sign/token-123', undefined, bindings)

    expect(response.status).toBe(200)
    await expect(response.json()).resolves.toMatchObject({
      contract: {
        title: 'Master Services Agreement',
        signingDeadline: '2026-06-01T00:00:00.000Z',
        status: 'SENT',
        signedPdfReady: true,
      },
      signatory: {
        order: 2,
      },
      waitingFor: { name: 'Avi Approver' },
      tenantBranding: {
        tenantName: 'Acme Studio',
        locale: 'en',
      },
    })
  })
})
