import { afterAll, beforeAll, describe, expect, it, vi } from "bun:test"

vi.mock("../convex/rbac", () => ({
  requireStaff: vi.fn(),
}))

import type { Doc, Id } from "../convex/_generated/dataModel"
import { backlogOverviewHandler, slaOverviewHandler } from "../convex/reports"
import { requireStaff } from "../convex/rbac"
import { createReportsCtx } from "./utils/report-test-helpers"

const TENANT_ID = "tenant-1"
const VIEWER_ID = "user-staff" as Id<"users">

function buildTicket(overrides: Partial<Doc<"tickets">>): Doc<"tickets"> {
  const base: Record<string, unknown> = {
    _id: "ticket_base" as Id<"tickets">,
    tenantId: TENANT_ID,
    reference: 50000,
    subject: "Chamado",
    summary: null,
    status: "PENDING",
    priority: "MEDIUM",
    channel: "EMAIL",
    queueId: undefined,
    requesterId: "user_req" as Id<"users">,
    requesterSnapshot: { name: "Alice", email: "alice@example.com", avatarUrl: undefined, teams: [] },
    assigneeId: "user_agent" as Id<"users">,
    assigneeSnapshot: { name: "Bob", email: "bob@example.com", avatarUrl: undefined, teams: [] },
    companyId: undefined,
    companySnapshot: undefined,
    machineId: undefined,
    machineSnapshot: undefined,
    working: false,
    dueAt: undefined,
    firstResponseAt: undefined,
    resolvedAt: undefined,
    closedAt: undefined,
    updatedAt: Date.now(),
    createdAt: Date.now(),
    tags: [],
    customFields: [],
    totalWorkedMs: 0,
    internalWorkedMs: 0,
    externalWorkedMs: 0,
    activeSessionId: undefined,
  }
  return { ...(base as Doc<"tickets">), ...overrides }
}

function buildQueue(overrides: Partial<Doc<"queues">>): Doc<"queues"> {
  const base: Record<string, unknown> = {
    _id: "queue_base" as Id<"queues">,
    tenantId: TENANT_ID,
    name: "Suporte",
    slug: "suporte",
    createdAt: Date.now(),
    updatedAt: Date.now(),
  }
  return { ...(base as Doc<"queues">), ...overrides }
}

function buildCategory(overrides: Partial<Doc<"ticketCategories">>): Doc<"ticketCategories"> {
  const base: Record<string, unknown> = {
    _id: "category_base" as Id<"ticketCategories">,
    tenantId: TENANT_ID,
    name: "Onboarding",
    slug: "onboarding",
    description: null,
    order: 0,
    createdAt: Date.now(),
    updatedAt: Date.now(),
  }
  return { ...(base as Doc<"ticketCategories">), ...overrides }
}

describe("convex.reports.slaOverview", () => {
  const requireStaffMock = vi.mocked(requireStaff)
  const FIXED_NOW = Date.UTC(2024, 4, 8, 12, 0, 0)

  beforeAll(() => {
    vi.useFakeTimers()
    vi.setSystemTime(FIXED_NOW)
  })

  afterAll(() => {
    vi.useRealTimers()
  })

  it("summarizes totals, averages and queue breakdown", async () => {
    requireStaffMock.mockResolvedValue({
      role: "ADMIN",
      user: { companyId: undefined },
    } as unknown as Awaited<ReturnType<typeof requireStaff>>)

    const queue = buildQueue({
      _id: "queue_1" as Id<"queues">,
      name: "Suporte Nível 1",
    })
    const category = buildCategory({
      _id: "category_1" as Id<"ticketCategories">,
      name: "Admissões",
    })

    const tickets = [
      buildTicket({
        _id: "ticket_open" as Id<"tickets">,
        status: "PENDING",
        queueId: queue._id,
        categoryId: category._id,
        createdAt: Date.UTC(2024, 4, 7, 9, 0, 0),
        dueAt: Date.UTC(2024, 4, 7, 11, 0, 0),
        slaSnapshot: { categoryId: category._id, categoryName: category.name, priority: "MEDIUM" },
        slaResponseStatus: "pending",
        slaSolutionStatus: "pending",
      }),
      buildTicket({
        _id: "ticket_resolved" as Id<"tickets">,
        status: "RESOLVED",
        queueId: queue._id,
        categoryId: category._id,
        createdAt: Date.UTC(2024, 4, 6, 8, 0, 0),
        firstResponseAt: Date.UTC(2024, 4, 6, 8, 30, 0),
        resolvedAt: Date.UTC(2024, 4, 6, 10, 0, 0),
        slaSnapshot: { categoryId: category._id, categoryName: category.name, priority: "MEDIUM" },
        slaResponseStatus: "met",
        slaSolutionStatus: "met",
      }),
    ]

    const ctx = createReportsCtx({ tickets, queues: [queue], categories: [category] }) as Parameters<typeof slaOverviewHandler>[0]

    const result = await slaOverviewHandler(ctx, {
      tenantId: TENANT_ID,
      viewerId: VIEWER_ID,
      range: "7d",
    })

    expect(result.rangeDays).toBe(7)
    expect(result.totals).toEqual({ total: 2, open: 1, resolved: 1, overdue: 1 })
    expect(result.response).toEqual({ averageFirstResponseMinutes: 30, responsesRegistered: 1 })
    expect(result.resolution).toEqual({ averageResolutionMinutes: 120, resolvedCount: 1 })
    expect(result.queueBreakdown).toEqual([{ id: queue._id, name: queue.name, open: 1 }])
    expect(result.categoryBreakdown).toEqual([
      {
        categoryId: String(category._id),
        categoryName: category.name,
        priority: "MEDIUM",
        total: 2,
        responseMet: 1,
        solutionMet: 1,
        responseRate: 0.5,
        solutionRate: 0.5,
      },
    ])
  })
})

describe("convex.reports.backlogOverview", () => {
  const requireStaffMock = vi.mocked(requireStaff)
  const FIXED_NOW = Date.UTC(2024, 6, 1, 12, 0, 0)

  beforeAll(() => {
    vi.useFakeTimers()
    vi.setSystemTime(FIXED_NOW)
  })

  afterAll(() => {
    vi.useRealTimers()
  })

  it("aggregates status, priority and queue counts for open tickets", async () => {
    requireStaffMock.mockResolvedValue({
      role: "ADMIN",
      user: { companyId: undefined },
    } as unknown as Awaited<ReturnType<typeof requireStaff>>)

    const queueA = buildQueue({ _id: "queue_a" as Id<"queues">, name: "Atendimento" })
    const queueB = buildQueue({ _id: "queue_b" as Id<"queues">, name: "Infraestrutura" })

    const tickets = [
      buildTicket({
        _id: "ticket_pending" as Id<"tickets">,
        status: "PENDING",
        priority: "HIGH",
        queueId: queueA._id,
        createdAt: Date.UTC(2024, 5, 28, 10, 0, 0),
      }),
      buildTicket({
        _id: "ticket_paused" as Id<"tickets">,
        status: "PAUSED",
        priority: "MEDIUM",
        queueId: queueB._id,
        createdAt: Date.UTC(2024, 5, 29, 15, 0, 0),
      }),
      buildTicket({
        _id: "ticket_resolved" as Id<"tickets">,
        status: "RESOLVED",
        priority: "URGENT",
        queueId: undefined,
        createdAt: Date.UTC(2024, 5, 27, 9, 0, 0),
      }),
    ]

    const ctx = createReportsCtx({
      tickets,
      createdRangeTickets: tickets,
      queues: [queueA, queueB],
    }) as Parameters<typeof backlogOverviewHandler>[0]

    const result = await backlogOverviewHandler(ctx, {
      tenantId: TENANT_ID,
      viewerId: VIEWER_ID,
      range: "7d",
    })

    expect(result.rangeDays).toBe(7)
    expect(result.statusCounts).toMatchObject({
      PENDING: 1,
      PAUSED: 1,
      RESOLVED: 1,
    })
    expect(result.priorityCounts).toEqual({
      HIGH: 1,
      MEDIUM: 1,
      URGENT: 1,
    })
    expect(result.totalOpen).toBe(2)
    expect(result.queueCounts).toHaveLength(2)
    expect(result.queueCounts).toEqual(
      expect.arrayContaining([
        { id: "queue_a", name: queueA.name, total: 1 },
        { id: "queue_b", name: queueB.name, total: 1 },
      ])
    )
  })
})
