import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { MessageBatch } from '@cloudflare/workers-types'

const { sendMail } = vi.hoisted(() => ({ sendMail: vi.fn() }))

vi.mock('../src/integrations/platform/mail', () => ({
  sendMail,
}))

import { handleAuthEmailMessages } from '../src/queues/auth-email'

function message(body: unknown, overrides: Partial<{ id: string; attempts: number }> = {}) {
  return {
    id: overrides.id ?? 'message-1',
    attempts: overrides.attempts ?? 1,
    body,
    ack: vi.fn(),
    retry: vi.fn(),
  }
}

const env = {
  APP_BASE_URL: 'https://app.dev.zync.is',
  RESEND_API_KEY: 'resend-key',
} as never

describe('auth email queue consumer', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    sendMail.mockResolvedValue({ id: 'mail-1', provider: 'resend' })
  })

  it('renders verification mail through platform mail and acknowledges only after delivery', async () => {
    const current = message({
      type: 'auth.email',
      kind: 'verify_email',
      to: 'new@example.test',
      token: 'signed-token',
      userId: 'user-1',
    })

    await handleAuthEmailMessages({ messages: [current] } as unknown as MessageBatch<unknown>, env)

    expect(sendMail).toHaveBeenCalledWith(
      env,
      expect.objectContaining({
        to: 'new@example.test',
        subject: expect.any(String),
        idempotencyKey: 'auth-email:message-1',
        html: expect.stringContaining('/api/auth/verify-email?token=signed-token'),
      }),
    )
    expect(current.ack).toHaveBeenCalledOnce()
    expect(current.retry).not.toHaveBeenCalled()
  })

  it('retries provider failures without acknowledging the message', async () => {
    const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined)
    sendMail.mockRejectedValue(new Error('Resend unavailable'))
    const current = message({
      type: 'auth.email',
      kind: 'password_reset',
      to: 'user@example.test',
      token: 'reset-token',
      userId: 'user-1',
    }, { attempts: 2 })

    await handleAuthEmailMessages({ messages: [current] } as unknown as MessageBatch<unknown>, env)

    expect(current.ack).not.toHaveBeenCalled()
    expect(current.retry).toHaveBeenCalledWith({ delaySeconds: 60 })
    expect(consoleError).toHaveBeenCalledOnce()
    consoleError.mockRestore()
  })

  it('acknowledges malformed auth email jobs as terminal input', async () => {
    const current = message({ type: 'auth.email', kind: 'verify_email', to: 'bad' })

    await handleAuthEmailMessages({ messages: [current] } as unknown as MessageBatch<unknown>, env)

    expect(current.ack).toHaveBeenCalledOnce()
    expect(current.retry).not.toHaveBeenCalled()
    expect(sendMail).not.toHaveBeenCalled()
  })
})
