import { createJob } from "@shared/testing/factories.js";
import type { Job } from "@shared/types.js";
import { fireEvent, screen, waitFor } from "@testing-library/react";
import type React from "react";
import { MemoryRouter } from "react-router-dom";
import { toast } from "sonner";
import { beforeEach, describe, expect, it, vi } from "vitest";
import * as api from "../api";
import { renderWithQueryClient } from "../test/renderWithQueryClient";
import { ReadyPanel } from "./ReadyPanel";

const render = (ui: Parameters<typeof renderWithQueryClient>[0]) =>
  renderWithQueryClient(ui);

vi.mock("@/components/ui/dropdown-menu", () => {
  return {
    DropdownMenu: ({ children }: { children: React.ReactNode }) => (
      <div>{children}</div>
    ),
    DropdownMenuTrigger: ({ children }: { children: React.ReactNode }) => (
      <>{children}</>
    ),
    DropdownMenuContent: ({ children }: { children: React.ReactNode }) => (
      <div role="menu">{children}</div>
    ),
    DropdownMenuItem: ({
      children,
      onSelect,
      ...props
    }: {
      children: React.ReactNode;
      onSelect?: () => void;
    }) => (
      <button
        type="button"
        role="menuitem"
        onClick={() => onSelect?.()}
        {...props}
      >
        {children}
      </button>
    ),
    DropdownMenuSeparator: () => <hr />,
  };
});

vi.mock("../hooks/useProfile", () => ({
  useProfile: () => ({ personName: "Test" }),
}));

vi.mock("../hooks/useSettings", () => ({
  useSettings: () => ({ showSponsorInfo: false }),
}));

vi.mock("../api", () => ({
  rescoreJob: vi.fn(),
  getResumeProjectsCatalog: vi.fn().mockResolvedValue([]),
  markAsApplied: vi.fn(),
  generateJobPdf: vi.fn(),
  checkSponsor: vi.fn(),
  skipJob: vi.fn(),
  updateJob: vi.fn(),
}));

vi.mock("./JobDetailsEditDrawer", () => ({
  JobDetailsEditDrawer: ({
    open,
    onOpenChange,
    onJobUpdated,
  }: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    onJobUpdated: () => void | Promise<void>;
  }) =>
    open ? (
      <div data-testid="job-details-edit-drawer">
        <button
          type="button"
          onClick={() => {
            void onJobUpdated();
            onOpenChange(false);
          }}
        >
          Save details
        </button>
      </div>
    ) : null,
}));

vi.mock("sonner", () => ({
  toast: {
    success: vi.fn(),
    error: vi.fn(),
    message: vi.fn(),
  },
}));

describe("ReadyPanel", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("re-runs the fit assessment from the menu", async () => {
    const onJobUpdated = vi.fn().mockResolvedValue(undefined);
    const job = createJob();
    vi.mocked(api.rescoreJob).mockResolvedValue(job as Job);

    render(
      <MemoryRouter>
        <ReadyPanel
          job={job}
          onJobUpdated={onJobUpdated}
          onJobMoved={vi.fn()}
        />
      </MemoryRouter>,
    );

    fireEvent.click(
      screen.getByRole("menuitem", { name: /recalculate match/i }),
    );

    await waitFor(() => expect(api.rescoreJob).toHaveBeenCalledWith("job-1"));
    expect(onJobUpdated).toHaveBeenCalled();
    expect(toast.success).toHaveBeenCalledWith("Match recalculated");
  });

  it("opens edit details drawer from more actions", async () => {
    const onJobUpdated = vi.fn().mockResolvedValue(undefined);
    const job = createJob();

    render(
      <MemoryRouter>
        <ReadyPanel
          job={job}
          onJobUpdated={onJobUpdated}
          onJobMoved={vi.fn()}
        />
      </MemoryRouter>,
    );

    fireEvent.click(screen.getByRole("menuitem", { name: /edit details/i }));
    expect(screen.getByTestId("job-details-edit-drawer")).toBeInTheDocument();

    fireEvent.click(screen.getByRole("button", { name: /save details/i }));
    await waitFor(() => expect(onJobUpdated).toHaveBeenCalled());
    expect(
      screen.queryByTestId("job-details-edit-drawer"),
    ).not.toBeInTheDocument();
  });

  it("renders descriptive google dork links in the ready summary", async () => {
    render(
      <MemoryRouter>
        <ReadyPanel
          job={createJob({
            employer: "HP",
            title: "Frontend Engineer",
            skills: "Wolf Security, React, TypeScript",
          })}
          onJobUpdated={vi.fn()}
          onJobMoved={vi.fn()}
        />
      </MemoryRouter>,
    );

    await waitFor(() =>
      expect(api.getResumeProjectsCatalog).toHaveBeenCalled(),
    );

    fireEvent.click(
      screen.getByRole("button", {
        name: /3 search links/i,
      }),
    );

    const linkedInLink = screen.getByRole("link", {
      name: "LinkedIn profiles with HP, Wolf Security, and React in them",
    });
    expect(linkedInLink).toHaveAttribute(
      "href",
      `https://www.google.com/search?q=${encodeURIComponent('site:linkedin.com/in "HP" "Wolf Security" "React"')}`,
    );
    expect(linkedInLink).toHaveAttribute("target", "_blank");
    expect(linkedInLink).toHaveAttribute("rel", "noopener noreferrer");
    expect(linkedInLink).toHaveAttribute(
      "title",
      'site:linkedin.com/in "HP" "Wolf Security" "React"',
    );
  });
});
