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

const mockCreateDb = vi.fn(() => ({}))
const mockFindAndMarkBreachedTickets = vi.fn()
const mockGetSlaPolicyByPriority = vi.fn()
const mockGetOwnerAdminUserIds = vi.fn()
const mockCreateNotification = vi.fn()
const mockSendEmail = vi.fn()
const mockTimingSafeEqual = vi.fn(() => true)

vi.mock('@zync/db/queries', () => ({
  createDb: (...args: unknown[]) => mockCreateDb(...args),
  findAndMarkBreachedTickets: (...args: unknown[]) => mockFindAndMarkBreachedTickets(...args),
  getSlaPolicyByPriority: (...args: unknown[]) => mockGetSlaPolicyByPriority(...args),
  getOwnerAdminUserIds: (...args: unknown[]) => mockGetOwnerAdminUserIds(...args),
  createNotification: (...args: unknown[]) => mockCreateNotification(...args),
}))

vi.mock('@zync/notifications', () => ({
  sendEmail: (...args: unknown[]) => mockSendEmail(...args),
}))

vi.mock('@zync/auth', async () => {
  const actual = await vi.importActual<typeof import('@zync/auth')>('@zync/auth')
  return {
    ...actual,
    timingSafeEqual: (...args: unknown[]) => mockTimingSafeEqual(...args),
  }
})

import { ticketSlaCheckCron } from '../src/routes/cron/ticket-sla-check'

function appWithRoute() {
  const app = new Hono<AppEnv>()
  app.route('/api/cron/ticket-sla-check', ticketSlaCheckCron)
  return app
}

describe('POST /api/cron/ticket-sla-check', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockFindAndMarkBreachedTickets.mockResolvedValue([
      {
        id: 'ticket-1',
        tenant_id: 'tenant-1',
        assignee_id: 'assignee-1',
        priority: 'urgent',
      },
    ])
    mockGetSlaPolicyByPriority.mockResolvedValue({
      priority: 'urgent',
      notify_in_app: true,
      notify_email: true,
      escalation_email: 'cto@example.com',
    })
    mockGetOwnerAdminUserIds.mockResolvedValue(['owner-1', 'admin-1'])
  })

  it('notifies assignee plus owner/admin users and sends escalation email', async () => {
    const res = await appWithRoute().request(
      '/api/cron/ticket-sla-check',
      {
        method: 'POST',
        headers: { 'x-cron-secret': '1234567890abcdef' },
      },
      { CRON_SECRET: '1234567890abcdef' } as AppEnv['Bindings'],
    )

    expect(res.status).toBe(200)
    expect(mockCreateNotification).toHaveBeenCalledTimes(3)
    expect(mockCreateNotification).toHaveBeenCalledWith(
      {},
      expect.objectContaining({
        userId: 'assignee-1',
        type: 'ticket_escalated',
        titleKey: 'notification.ticket_escalated.title',
        bodyKey: 'notification.ticket_escalated.body',
      }),
    )
    expect(mockCreateNotification).toHaveBeenCalledWith(
      {},
      expect.objectContaining({ userId: 'owner-1', type: 'ticket_escalated' }),
    )
    expect(mockCreateNotification).toHaveBeenCalledWith(
      {},
      expect.objectContaining({ userId: 'admin-1', type: 'ticket_escalated' }),
    )
    expect(mockSendEmail).toHaveBeenCalledWith(
      expect.objectContaining({ to: 'cto@example.com' }),
      expect.objectContaining({ CRON_SECRET: '1234567890abcdef' }),
    )
  })
})
