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

const mockGetDashboardData = vi.fn()
const mockDismissChecklist = vi.fn()

vi.mock('@zync/db/queries', () => ({
  getDashboardData: (...args: unknown[]) => mockGetDashboardData(...args),
  dismissChecklist: (...args: unknown[]) => mockDismissChecklist(...args),
}))

vi.mock('../src/middleware/auth', () => ({
  authMiddleware: async (
    c: {
      set: (key: string, value: unknown) => void
      req: { method: string; header: (name: string) => string | undefined }
    },
    next: () => Promise<void>,
  ) => {
    c.set('db', { tag: 'db' })
    c.set('session', {
      type: 'user',
      tid: 'tenant-1',
      sub: 'user-1',
      role: 'ADMIN',
      permissions: ['tasks:read'],
    })
    await next()
  },
}))

describe('dashboard routes', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('returns the unified dashboard payload from GET /api/dashboard', async () => {
    mockGetDashboardData.mockResolvedValue({
      kpis: {
        revenue_this_month: null,
        open_invoices: null,
        active_projects: { count: 2 },
        pending_tasks: { count: 3 },
        overdue: { tasks: 1, invoices: 0, total: 1 },
      },
      recent_activity: [],
      upcoming: { events: [], tasks_today: [], tasks_tomorrow: [] },
      setup_checklist: null,
      modules: {
        invoices: false,
        tasks: true,
        projects: true,
        customers: false,
        calendar: false,
        time: false,
      },
    })

    const { dashboardRoutes } = await import('../src/routes/dashboard')
    const app = new Hono<AppEnv>()
    app.route('/api/dashboard', dashboardRoutes)

    const res = await app.request('/api/dashboard', undefined, {} as AppEnv['Bindings'])

    expect(res.status).toBe(200)
    await expect(res.json()).resolves.toMatchObject({
      modules: {
        tasks: true,
        projects: true,
      },
      kpis: {
        pending_tasks: { count: 3 },
      },
    })
    expect(mockGetDashboardData).toHaveBeenCalledWith(
      { tag: 'db' },
      expect.objectContaining({
        tenantId: 'tenant-1',
        userId: 'user-1',
        role: 'ADMIN',
      }),
    )
  })

  it('allows ADMIN to dismiss the checklist and returns 204', async () => {
    const { dashboardRoutes } = await import('../src/routes/dashboard')
    const app = new Hono<AppEnv>()
    app.route('/api/dashboard', dashboardRoutes)

    const res = await app.request(
      '/api/dashboard/checklist/dismiss',
      {
        method: 'PATCH',
        headers: { Origin: 'https://app.zync.test' },
      },
      {} as AppEnv['Bindings'],
    )

    expect(res.status).toBe(204)
    expect(await res.text()).toBe('')
    expect(mockDismissChecklist).toHaveBeenCalledWith({ tag: 'db' }, 'tenant-1')
  })
})
