"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it, vi } from "vitest";

let mockOrganization: Record<string, unknown> | null = null;
let mockApiKeys: Array<{
  id: string;
  name: string;
  provider: string;
  scope: string;
}> = [];
let mockAgents: Array<{ id: string; name: string; icon?: string | null }> = [];
const mockSearchableSelect = vi.fn((props: { value: string }) => (
  <div>{props.value}</div>
));

vi.mock("next/link", () => ({
  default: ({
    children,
    href,
  }: {
    children: React.ReactNode;
    href: string;
  }) => <a href={href}>{children}</a>,
}));

vi.mock("@/components/llm-provider-api-key-form", () => ({
  PROVIDER_CONFIG: {
    vertex_ai: {
      icon: "/vertex.svg",
      name: "Vertex AI",
    },
    openai: {
      icon: "/openai.svg",
      name: "OpenAI",
    },
  },
}));

vi.mock("@/components/llm-model-select", () => ({
  LlmModelSearchableSelect: ({
    value,
    placeholder,
  }: {
    value: string;
    placeholder: string;
  }) => <div>{value || placeholder}</div>,
}));

vi.mock("@/components/llm-provider-options", () => ({
  LlmProviderApiKeyOptionLabel: ({
    providerName,
    keyName,
  }: {
    providerName: string;
    keyName: string;
  }) => (
    <span>
      {providerName} {keyName}
    </span>
  ),
  LlmProviderApiKeySelectItems: () => null,
}));

vi.mock("@/components/roles/with-permissions", () => ({
  WithPermissions: ({
    children,
  }: {
    children: (args: { hasPermission: boolean }) => React.ReactNode;
  }) => children({ hasPermission: true }),
}));

vi.mock("@/components/settings/settings-block", () => ({
  SettingsBlock: ({
    title,
    description,
    control,
  }: {
    title: React.ReactNode;
    description?: React.ReactNode;
    control: React.ReactNode;
  }) => (
    <section>
      <h2>{title}</h2>
      {description ? <p>{description}</p> : null}
      <div>{control}</div>
    </section>
  ),
  SettingsSectionStack: ({ children }: { children: React.ReactNode }) => (
    <div>{children}</div>
  ),
  SettingsSaveBar: ({ hasChanges }: { hasChanges: boolean }) =>
    hasChanges ? <div>Unsaved changes</div> : null,
}));

vi.mock("@/components/ui/searchable-select", () => ({
  SearchableSelect: (props: Record<string, unknown>) =>
    mockSearchableSelect(props as { value: string }),
}));

vi.mock("@/components/log-filter-option", () => ({
  ProfileFilterOption: ({ profile }: { profile: { name: string } }) => (
    <span>profile:{profile.name}</span>
  ),
}));

vi.mock("@/components/ui/select", () => ({
  Select: ({ children }: { children: React.ReactNode }) => (
    <div>{children}</div>
  ),
  SelectTrigger: ({ children }: { children: React.ReactNode }) => (
    <div>{children}</div>
  ),
  SelectValue: ({
    children,
    placeholder,
  }: {
    children?: React.ReactNode;
    placeholder?: string;
  }) => <span>{children ?? placeholder}</span>,
  SelectContent: ({ children }: { children: React.ReactNode }) => (
    <div>{children}</div>
  ),
  SelectItem: ({ children }: { children: React.ReactNode }) => (
    <div>{children}</div>
  ),
}));

vi.mock("@/lib/agent.query", () => ({
  useOrgScopedAgents: () => ({
    data: mockAgents,
  }),
}));

vi.mock("@/lib/llm-models.query", () => ({
  useLlmModels: () => ({
    data: [
      {
        id: "gemini-2.5-pro",
        dbId: "gemini-2.5-pro",
        provider: "vertex_ai",
        displayName: "Gemini 2.5 Pro",
      },
    ],
    isPending: false,
  }),
}));

vi.mock("@/lib/llm-provider-api-keys.query", () => ({
  useAvailableLlmProviderApiKeys: () => ({
    data: mockApiKeys,
  }),
}));

const mutateAsync = vi.fn();

vi.mock("@/lib/organization.query", () => ({
  useOrganization: () => ({
    data: mockOrganization,
  }),
  useAppearanceSettings: () => ({
    data: {
      appName: "Spark",
    },
  }),
  useUpdateAgentSettings: () => ({
    mutateAsync,
    isPending: false,
  }),
  useUpdateSecuritySettings: () => ({
    mutateAsync,
    isPending: false,
  }),
}));

import AgentSettingsPage from "./page";

function renderPage() {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  return render(
    <QueryClientProvider client={queryClient}>
      <AgentSettingsPage />
    </QueryClientProvider>,
  );
}

beforeEach(() => {
  vi.clearAllMocks();
  mockOrganization = {
    defaultModelId: "gemini-2.5-pro",
    defaultLlmApiKeyId: "key-1",
    defaultAgentId: null,
    globalToolPolicy: "permissive",
    allowChatFileUploads: true,
  };
  mockApiKeys = [
    {
      id: "key-1",
      name: "gemini - org",
      provider: "vertex_ai",
      scope: "org",
    },
  ];
  mockAgents = [];
});

describe("AgentSettingsPage", () => {
  it("lets users reset the org default model selection", async () => {
    const user = userEvent.setup();

    renderPage();

    expect(screen.getByText("gemini-2.5-pro")).toBeInTheDocument();

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

    expect(screen.getByText("Select API key first...")).toBeInTheDocument();
    expect(screen.getByText("Unsaved changes")).toBeInTheDocument();
  });

  it("uses the shared profile filter renderer for org agent rows in the default agent dropdown", () => {
    mockAgents = [
      {
        id: "agent-1",
        name: "Agent Builder Agent",
        icon: "🧰",
      },
    ];

    renderPage();

    const searchableSelectCall = mockSearchableSelect.mock.calls.find(
      ([props]) =>
        (props as { searchPlaceholder?: string }).searchPlaceholder ===
        "Search agents...",
    );
    expect(searchableSelectCall).toBeDefined();

    const items = (
      searchableSelectCall?.[0] as unknown as {
        items: Array<{
          value: string;
          label: string;
          content?: React.ReactNode;
          selectedContent?: React.ReactNode;
        }>;
      }
    ).items;

    expect(items[0]).toMatchObject({
      value: "__personal__",
      label: "User's personal agent",
    });
    expect(items[1]).toMatchObject({
      value: "agent-1",
      label: "Agent Builder Agent",
    });
    expect(items[1].content).toBeTruthy();
    expect(items[1].selectedContent).toBeTruthy();
  });
});
