import { screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi, beforeEach } from "vitest";
import CallCenterReport from "./CallCenterReport";
import { renderWithQueryClient as render } from "./test-utils";
import { ReportsAPI } from "@/apis/ReportsAPI";
import { CallCenterAPI } from "@/apis/CallCenterAPI";

vi.mock("@/apis/ReportsAPI", () => ({
  ReportsAPI: {
    getCallCenterTicketsSummary: vi.fn(),
    getCallCenterDailyCalls: vi.fn(),
    getCallCenterTicketsHistory: vi.fn(),
    getCallCenterDailyCallsDetailed: vi.fn(),
    getCallCenterDailyCallsDetailedPaginated: vi.fn(),
  },
}));

vi.mock("@/apis/CallCenterAPI", () => ({
  CallCenterAPI: {
    getSupervisors: vi.fn(),
  },
}));

const dateRange = { startDate: "2026-08-01", endDate: "2026-08-31" };

const summary = (overrides = {}) => ({
  closed_count: 3,
  pending_count: 1,
  most_frequent_type: "reclamo",
  by_type: [{ type: "reclamo", total: 3 }],
  by_priority: [{ priority: "high", total: 2 }, { priority: "low", total: 1 }],
  avg_closure_minutes: 45.5,
  ...overrides,
});

describe("CallCenterReport", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    ReportsAPI.getCallCenterTicketsSummary.mockResolvedValue(summary());
    ReportsAPI.getCallCenterDailyCalls.mockResolvedValue([]);
    ReportsAPI.getCallCenterTicketsHistory.mockResolvedValue([]);
    ReportsAPI.getCallCenterDailyCallsDetailed.mockResolvedValue([]);
    ReportsAPI.getCallCenterDailyCallsDetailedPaginated.mockResolvedValue({ rows: [], total: 0 });
    CallCenterAPI.getSupervisors.mockResolvedValue([]);
  });

  it("muestra el loader mientras carga el resumen", () => {
    ReportsAPI.getCallCenterTicketsSummary.mockReturnValue(new Promise(() => {}));
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);
    expect(document.querySelector(".animate-spin")).toBeTruthy();
  });

  it("muestra los contadores de cerrados/pendientes y el tiempo promedio (C3)", async () => {
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText("3")).toBeInTheDocument();
    expect(screen.getAllByText("1").length).toBeGreaterThan(0);
    expect(screen.getByText("45.5 min")).toBeInTheDocument();
    expect(screen.getByText(/reclamo/i)).toBeInTheDocument();
    expect(screen.getAllByLabelText("Más información").length).toBeGreaterThan(0);
  });

  it("muestra el detalle de tickets por urgencia (C3)", async () => {
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText("high")).toBeInTheDocument();
    expect(screen.getByText("low")).toBeInTheDocument();
  });

  it("muestra mensaje cuando no hay tickets por urgencia", async () => {
    ReportsAPI.getCallCenterTicketsSummary.mockResolvedValue(summary({ by_priority: [] }));
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText(/Sin datos en este período/i)).toBeInTheDocument();
  });

  it("muestra '—' cuando no hay tiempo promedio de cierre", async () => {
    ReportsAPI.getCallCenterTicketsSummary.mockResolvedValue(summary({ avg_closure_minutes: null }));
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText("—")).toBeInTheDocument();
  });

  it("muestra la tabla de llamados diarios cuando hay datos (C2)", async () => {
    ReportsAPI.getCallCenterDailyCalls.mockResolvedValue([
      { period: "2026-08-10", calls_count: 5 },
      { period: "2026-08-11", calls_count: 2 },
    ]);

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText("10/08/2026")).toBeInTheDocument();
    expect(screen.getByText("5")).toBeInTheDocument();
  });

  it("muestra mensaje cuando no hay llamados en el período", async () => {
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText(/No hay llamados registrados en este período/i)).toBeInTheDocument();
  });

  it("llama onDataReady con el resumen exportable de llamados diarios", async () => {
    const onDataReady = vi.fn();
    ReportsAPI.getCallCenterDailyCalls.mockResolvedValue([{ period: "2026-08-10", calls_count: 5 }]);

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={onDataReady} />);

    await waitFor(() => expect(onDataReady).toHaveBeenCalled());
    expect(onDataReady.mock.calls[0][0].fileName).toBe("llamados_diarios");
  });

  it("pide historial de tickets al escribir un RUT y lo muestra (C1)", async () => {
    const user = userEvent.setup();
    ReportsAPI.getCallCenterTicketsHistory.mockResolvedValue([
      {
        id: 1,
        ticket_number: "TK-0001",
        customer_name: "Ana",
        customer_tax_id: "11.111.111-1",
        status: "abierto",
        opened_at: "2026-08-10 09:00:00",
      },
    ]);

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);
    expect(await screen.findByText(/Ingresa un RUT para ver el historial/i)).toBeInTheDocument();

    await user.type(await screen.findByLabelText(/Buscar por RUT/i), "11.111.111-1");

    expect(await screen.findByText("TK-0001")).toBeInTheDocument();
    expect(screen.getByText("Ana")).toBeInTheDocument();
    expect(ReportsAPI.getCallCenterTicketsHistory).toHaveBeenCalledWith(1, { rut: "11.111.111-1" });
  });

  it("muestra mensaje sin resultados cuando la búsqueda de RUT no encuentra tickets", async () => {
    const user = userEvent.setup();
    ReportsAPI.getCallCenterTicketsHistory.mockResolvedValue([]);

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);
    await user.type(await screen.findByLabelText(/Buscar por RUT/i), "99999999-9");

    expect(await screen.findByText(/Sin resultados para ese RUT/i)).toBeInTheDocument();
  });

  it("muestra mensaje vacío en la gestión de llamadas diarias con TMO (PDF-05)", async () => {
    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);
    expect(
      await screen.findByText(/No hay llamadas con estado registrado en este período/i),
    ).toBeInTheDocument();
  });

  it("renderiza las llamadas con TMO y estado (PDF-05)", async () => {
    ReportsAPI.getCallCenterDailyCallsDetailedPaginated.mockResolvedValue({
      rows: [
        {
          ticket_number: "TK-0002",
          customer_name: "Beto",
          executive_name: "Ejecutiva Uno",
          call_started_at: "2026-08-10 09:00:00",
          call_ended_at: "2026-08-10 09:03:00",
          tmo_minutes: 3,
          call_outcome_code: "llamada_exitosa",
        },
        {
          ticket_number: "TK-0003",
          customer_name: "Carla",
          executive_name: null,
          call_started_at: null,
          call_ended_at: null,
          tmo_minutes: null,
          call_outcome_code: "no_contesta",
        },
      ],
      total: 2,
    });

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText("TK-0002")).toBeInTheDocument();
    expect(screen.getByText("Ejecutiva Uno")).toBeInTheDocument();
    expect(screen.getAllByText("3").length).toBeGreaterThan(0);
    expect(screen.getByText("llamada exitosa")).toBeInTheDocument();
    expect(screen.getByText("no contesta")).toBeInTheDocument();
  });

  it("pagina server-side la gestión de llamadas diarias con TMO (PDF-05)", async () => {
    const user = userEvent.setup();
    const rowsPage1 = [
      {
        ticket_number: "TK-P1",
        customer_name: "Cliente Página 1",
        executive_name: "Ejecutiva Uno",
        tmo_minutes: 2,
        call_outcome_code: "llamada_exitosa",
      },
    ];
    const rowsPage2 = [
      {
        ticket_number: "TK-P2",
        customer_name: "Cliente Página 2",
        executive_name: "Ejecutiva Dos",
        tmo_minutes: 4,
        call_outcome_code: "no_contesta",
      },
    ];
    ReportsAPI.getCallCenterDailyCallsDetailedPaginated.mockImplementation((_id, _from, _to, page) =>
      Promise.resolve(page === 2 ? { rows: rowsPage2, total: 11 } : { rows: rowsPage1, total: 11 }),
    );

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    expect(await screen.findByText("TK-P1")).toBeInTheDocument();
    expect(screen.getByText(/Página 1 de 2/i)).toBeInTheDocument();

    await user.click(screen.getByRole("button", { name: "Siguiente" }));

    expect(await screen.findByText("TK-P2")).toBeInTheDocument();
    expect(screen.getByText(/Página 2 de 2/i)).toBeInTheDocument();
    expect(ReportsAPI.getCallCenterDailyCallsDetailedPaginated).toHaveBeenLastCalledWith(1, "2026-08-01", "2026-08-31", 2, 10, undefined);
  });

  it("muestra nombre y apellido en el filtro de ejecutiva y permite buscar", async () => {
    const user = userEvent.setup();
    CallCenterAPI.getSupervisors.mockResolvedValue([
      { id: 8, user_name: "karole.fasching.rojas", name: null, last_name: null },
      { id: 10, user_name: "juan.abuyeres.cabrera", name: "Juan", last_name: "Abuyeres Cabrera" },
    ]);

    render(<CallCenterReport companyId={1} dateRange={dateRange} onDataReady={vi.fn()} />);

    await user.click(await screen.findByLabelText(/Filtrar por ejecutiva/i));

    expect(await screen.findByPlaceholderText(/Buscar ejecutiva/i)).toBeInTheDocument();
    expect(screen.getByText("Karole Fasching Rojas")).toBeInTheDocument();
    expect(screen.getByText("Juan Abuyeres Cabrera")).toBeInTheDocument();
    expect(screen.queryByText("karole.fasching.rojas")).not.toBeInTheDocument();

    await user.type(screen.getByPlaceholderText(/Buscar ejecutiva/i), "juan");
    expect(screen.getByText("Juan Abuyeres Cabrera")).toBeInTheDocument();
    expect(screen.queryByText("Karole Fasching Rojas")).not.toBeInTheDocument();

    await user.click(screen.getByText("Juan Abuyeres Cabrera"));

    await waitFor(() => {
      expect(ReportsAPI.getCallCenterTicketsSummary).toHaveBeenCalledWith(1, "2026-08-01", "2026-08-31", 10);
    });
  });
});
