import {
  CLAUDE_CLIENT_ID,
  CLAUDE_CODE_CLIENT_ID,
  CLAUDE_DESKTOP_CLIENT_ID,
} from "@archestra/shared";
import { render, screen } from "@testing-library/react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
  useInteractionSessions,
  useInteractions,
} from "@/lib/interactions/interaction.query";
import SessionDetailPage from "./page.client";

vi.mock("next/navigation");

vi.mock("@/lib/interactions/interaction.query", () => ({
  useInteractions: vi.fn(),
  useInteractionSessions: vi.fn(),
}));

vi.mock("react", async (importOriginal) => {
  const actual = await importOriginal<typeof import("react")>();
  return {
    ...actual,
    use: () => ({ sessionId: "test-session" }),
  };
});

describe("SessionDetailPage", () => {
  beforeEach(() => {
    vi.mocked(useRouter).mockReturnValue({
      push: vi.fn(),
    } as unknown as ReturnType<typeof useRouter>);
    vi.mocked(useSearchParams).mockReturnValue(
      new URLSearchParams() as unknown as ReturnType<typeof useSearchParams>,
    );
    vi.mocked(usePathname).mockReturnValue("/llm/logs/session/test-session");
    vi.mocked(useInteractionSessions).mockReturnValue({
      data: undefined,
    } as unknown as ReturnType<typeof useInteractionSessions>);
  });

  it("shows a loading state while session interactions are loading", async () => {
    vi.mocked(useInteractions).mockReturnValue({
      data: undefined,
      isLoading: true,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    expect(await screen.findByText("Loading session logs...")).toBeVisible();
    expect(
      screen.queryByText("No interactions found for this session"),
    ).not.toBeInTheDocument();
  });

  it("shows the empty state after session interactions finish loading empty", async () => {
    vi.mocked(useInteractions).mockReturnValue({
      data: {
        data: [],
        pagination: {
          currentPage: 1,
          limit: 50,
          total: 0,
          totalPages: 0,
          hasNext: false,
          hasPrev: false,
        },
      },
      isLoading: false,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    expect(
      await screen.findByText("No interactions found for this session"),
    ).toBeVisible();
    expect(
      screen.queryByText("Loading session logs..."),
    ).not.toBeInTheDocument();
  });

  it("shows cache read/write totals when the session used prompt caching", async () => {
    vi.mocked(useInteractionSessions).mockReturnValue({
      data: {
        data: [
          {
            totalInputTokens: 1250,
            totalOutputTokens: 430,
            totalCacheReadTokens: 98000,
            totalCacheWriteTokens: 12000,
          },
        ],
      },
    } as unknown as ReturnType<typeof useInteractionSessions>);
    vi.mocked(useInteractions).mockReturnValue({
      data: { data: [], pagination: { total: 0 } },
      isLoading: false,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    expect(
      await screen.findByText(/98,000 cache read \/ 12,000 cache write/),
    ).toBeVisible();
  });

  // Every Claude client id (auto-discovered, header-set) renders one "Claude" badge.
  it.each([
    [CLAUDE_CLIENT_ID],
    [CLAUDE_CODE_CLIENT_ID],
    [CLAUDE_DESKTOP_CLIENT_ID],
  ])("renders the Claude badge for client id '%s'", async (externalAgentId) => {
    vi.mocked(useInteractionSessions).mockReturnValue({
      data: { data: [{ externalAgentIds: [externalAgentId] }] },
    } as unknown as ReturnType<typeof useInteractionSessions>);
    vi.mocked(useInteractions).mockReturnValue({
      data: { data: [], pagination: { total: 0 } },
      isLoading: false,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    expect(await screen.findByText("Claude")).toBeVisible();
  });

  it("shows no Claude badge for non-Claude clients", async () => {
    vi.mocked(useInteractionSessions).mockReturnValue({
      data: { data: [{ externalAgentIds: ["my-custom-agent"] }] },
    } as unknown as ReturnType<typeof useInteractionSessions>);
    vi.mocked(useInteractions).mockReturnValue({
      data: { data: [], pagination: { total: 0 } },
      isLoading: false,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    expect(
      await screen.findByText("No interactions found for this session"),
    ).toBeVisible();
    expect(screen.queryByText("Claude")).not.toBeInTheDocument();
  });

  it("renders the rows-per-page selector when the session has interactions", async () => {
    vi.mocked(useInteractions).mockReturnValue({
      data: {
        data: [],
        pagination: {
          currentPage: 1,
          limit: 50,
          total: 120,
          totalPages: 3,
          hasNext: true,
          hasPrev: false,
        },
      },
      isLoading: false,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    // Both the desktop and mobile pagination layouts render the selector.
    expect(
      (await screen.findAllByText("Rows per page")).length,
    ).toBeGreaterThan(0);
    expect(
      screen.getAllByText(/Showing 1 to 10 of 120 requests/).length,
    ).toBeGreaterThan(0);
  });

  it("hides the cache line when the session used no caching", async () => {
    vi.mocked(useInteractionSessions).mockReturnValue({
      data: {
        data: [
          {
            totalInputTokens: 1250,
            totalOutputTokens: 430,
            totalCacheReadTokens: 0,
            totalCacheWriteTokens: 0,
          },
        ],
      },
    } as unknown as ReturnType<typeof useInteractionSessions>);
    vi.mocked(useInteractions).mockReturnValue({
      data: { data: [], pagination: { total: 0 } },
      isLoading: false,
    } as unknown as ReturnType<typeof useInteractions>);

    renderSessionDetailPage();

    expect(await screen.findByText(/1,250 in/)).toBeVisible();
    expect(screen.queryByText(/cache read/)).not.toBeInTheDocument();
  });
});

function renderSessionDetailPage() {
  return render(
    <SessionDetailPage
      paramsPromise={Promise.resolve({ sessionId: "test-session" })}
    />,
  );
}
