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

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

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

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

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

const mockUseOrganization = vi.mocked(useOrganization);
const mockUseSubscription = vi.mocked(useSubscription);
type SubscriptionData = NonNullable<ReturnType<typeof useSubscription>["data"]>;

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 renderCard(
  user: User,
  orgData: ReturnType<typeof useOrganization>["data"],
  subscription: ReturnType<typeof useSubscription>["data"] = undefined
) {
  mockUseOrganization.mockReturnValue({
    data: orgData,
    isLoading: false,
    error: null,
  } as ReturnType<typeof useOrganization>);

  mockUseSubscription.mockReturnValue({
    data: subscription,
    isLoading: false,
    error: null,
  } as ReturnType<typeof useSubscription>);

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

const baseOrg = {
  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,
};

describe("SubscriptionCard", () => {
  it("shows 'Sans abonnement' badge when there is no subscription", () => {
    renderCard(baseUser, baseOrg);
    expect(screen.getByText("Sans abonnement")).toBeInTheDocument();
  });

  it("shows Founder badge and unlimited info for annual plan", () => {
    const founderOrg = { ...baseOrg, active_subscription_plan: "annual" as const };
    const founderUser = { ...baseUser, plan: "standard" as const };
    renderCard(founderUser, founderOrg);
    expect(screen.getByText("Founder")).toBeInTheDocument();
    expect(screen.getByText(/Plan Founder \(annuel\)/)).toBeInTheDocument();
  });

  it("shows recommended plan for non-paying billing owner", () => {
    renderCard(baseUser, baseOrg);
    expect(screen.getByText(/Plan recommandé: Solo/)).toBeInTheDocument();
    expect(screen.getByText(/Passer au plan Solo/)).toBeInTheDocument();
    expect(screen.getByText("Devenir Founder (99€/an)")).toBeInTheDocument();
  });

  it("shows team as recommended plan when required", () => {
    const teamOrg = {
      ...baseOrg,
      required_plan: "team" as const,
      required_team_quantity: 3,
    };
    renderCard(baseUser, teamOrg);
    expect(screen.getByText(/Plan recommandé: Teams/)).toBeInTheDocument();
    expect(screen.getByText(/3 sièges Teams/)).toBeInTheDocument();
  });

  it("shows billing owner restriction when user is not billing owner", () => {
    const nonOwnerOrg = { ...baseOrg, is_billing_owner: false };
    renderCard(baseUser, nonOwnerOrg);
    expect(screen.getByText(/Seul le propriétaire de facturation/)).toBeInTheDocument();
    expect(screen.queryByText(/Passer au plan/)).not.toBeInTheDocument();
  });

  it("shows active subscription details with manage and cancel buttons", () => {
    const teamOrg = {
      ...baseOrg,
      active_subscription_plan: "team" as const,
      active_subscription_quantity: 3,
    };
    const activeSubscription = {
      id: "sub_1",
      status: "active",
      current_period_end: Math.floor(Date.now() / 1000) + 86400 * 30,
      cancel_at_period_end: false,
    } satisfies SubscriptionData;
    renderCard(baseUser, teamOrg, activeSubscription);
    expect(screen.getByText("Actif")).toBeInTheDocument();
    expect(screen.getByText("Gérer l'abonnement")).toBeInTheDocument();
    expect(screen.getByText("Annuler")).toBeInTheDocument();
  });

  it("shows trialing badge for trialing subscription", () => {
    const teamOrg = {
      ...baseOrg,
      active_subscription_plan: "team" as const,
    };
    const trialingSubscription = {
      id: "sub_1",
      status: "trialing",
      current_period_end: Math.floor(Date.now() / 1000) + 86400 * 14,
      cancel_at_period_end: false,
    } satisfies SubscriptionData;
    renderCard(baseUser, teamOrg, trialingSubscription);
    expect(screen.getByText("Période d'essai")).toBeInTheDocument();
  });

  it("shows past_due badge for overdue subscription", () => {
    const teamOrg = {
      ...baseOrg,
      active_subscription_plan: "team" as const,
    };
    const pastDueSubscription = {
      id: "sub_1",
      status: "past_due",
      current_period_end: Math.floor(Date.now() / 1000) - 86400,
      cancel_at_period_end: false,
    } satisfies SubscriptionData;
    renderCard(baseUser, teamOrg, pastDueSubscription);
    expect(screen.getByText("Paiement en retard")).toBeInTheDocument();
  });

  it("shows reactivation UI for canceled subscription", () => {
    const teamOrg = {
      ...baseOrg,
      active_subscription_plan: "team" as const,
      active_subscription_quantity: 2,
    };
    const canceledSubscription = {
      id: "sub_1",
      status: "active",
      current_period_end: Math.floor(Date.now() / 1000) + 86400 * 15,
      cancel_at_period_end: true,
    } satisfies SubscriptionData;
    renderCard(baseUser, teamOrg, canceledSubscription);
    expect(screen.getByText(/Abonnement en cours d'annulation/)).toBeInTheDocument();
    expect(screen.getByText("Réactiver l'abonnement")).toBeInTheDocument();
  });
});
