import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { UpgradeBlockProvider } from "../contexts/UpgradeBlockContext";
import { TestUserStoreProvider, type User } from "../providers/UserStoreProvider";
import { UpgradePanel } from "./UpgradePanel";

vi.mock("../hooks/organization", () => ({
  useOrganization: vi.fn(),
}));

vi.mock("../hooks/stripe", async (importOriginal) => {
  const actual = await importOriginal<typeof import("../hooks/stripe")>();
  return {
    ...actual,
    useCreateCheckoutSession: () => ({ mutate: vi.fn(), isPending: false }),
  };
});

vi.mock("../hooks/auth", () => ({
  useLogout: () => ({ mutate: vi.fn() }),
  useAuthedApi: () => ({}),
}));

import { useOrganization } from "../hooks/organization";

const mockUseOrganization = vi.mocked(useOrganization);

const baseUser: User = {
  id: "user-1",
  short_user_id: "u1",
  name: "Test User",
  first_name: "Test",
  last_name: "User",
  email: "test@example.com",
  avatar_url: null,
  is_client: false,
  client_onboarded_at: null,
  last_signed_in: null,
  plan: "none",
  created_at: new Date().toISOString(),
};

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

function renderPanel(user: User, orgData: ReturnType<typeof useOrganization>["data"]) {
  mockUseOrganization.mockReturnValue({
    data: orgData,
    isLoading: false,
    error: null,
  } as ReturnType<typeof useOrganization>);

  return render(
    <QueryClientProvider client={queryClient}>
      <TestUserStoreProvider user={user}>
        <UpgradeBlockProvider>
          <UpgradePanel />
        </UpgradeBlockProvider>
      </TestUserStoreProvider>
    </QueryClientProvider>
  );
}

const noPlanOrg = {
  organization: {
    id: 1,
    name: "Org",
    plan: "none",
    member_count: 1,
    tablo_count: 0,
    logo_url: null,
  },
  members: [],
  invites_sent: [],
  trial_starts_at: "2026-01-01",
  trial_ends_at: "2026-02-01",
  is_trial_expired: false,
  required_plan: "solo" as const,
  required_team_quantity: 1,
  active_subscription_plan: null,
  active_subscription_quantity: 0,
  is_billing_owner: true,
};

const trialExpiredOrg = {
  ...noPlanOrg,
  is_trial_expired: true,
  required_plan: "team" as const,
  required_team_quantity: 3,
  active_subscription_plan: "team" as const,
  active_subscription_quantity: 1,
  is_billing_owner: true,
};

const compliantOrg = {
  ...noPlanOrg,
  active_subscription_plan: "team" as const,
  active_subscription_quantity: 2,
  is_billing_owner: true,
};

describe("UpgradePanel", () => {
  it("renders nothing when user has a compliant subscription", () => {
    const { container } = renderPanel(baseUser, compliantOrg);
    expect(container.innerHTML).toBe("");
  });

  it("renders the paywall for regular users with no plan", () => {
    renderPanel(baseUser, noPlanOrg);
    expect(screen.getByText("Choisissez un abonnement pour continuer")).toBeInTheDocument();
  });

  it("renders trial expired message when trial is expired", () => {
    renderPanel(baseUser, trialExpiredOrg);
    expect(screen.getByText("Votre période d'essai est terminée")).toBeInTheDocument();
  });

  it("shows checkout buttons for billing owner", () => {
    renderPanel(baseUser, noPlanOrg);
    expect(screen.getByText("Passer au plan Solo")).toBeInTheDocument();
    expect(screen.getByText(/Passer au plan Teams/)).toBeInTheDocument();
    expect(screen.getByText("Devenir Founder (99€/an)")).toBeInTheDocument();
  });

  it("disables buttons for non-billing-owner and shows warning", () => {
    const nonOwnerOrg = { ...noPlanOrg, is_billing_owner: false };
    renderPanel(baseUser, nonOwnerOrg);

    const soloButton = screen.getByText("Passer au plan Solo").closest("button");
    expect(soloButton).toBeDisabled();

    expect(screen.getByText(/Seul le propriétaire de facturation/)).toBeInTheDocument();
  });

  it("renders nothing when org data is not yet loaded", () => {
    const { container } = renderPanel(baseUser, undefined);
    expect(container.innerHTML).toBe("");
  });
});
