// src/components/billing/billing-settings.tsx — Settings → Billing client UI.
// Header card (current plan / trial countdown), the shared PlanGrid (toggle +
// 4 plans + Enterprise), and the manage-billing footer (Stripe customer
// portal, cancel, restore). All money is USD-first; prices come from
// src/lib/billing/plans.ts in cents. Only the org owner (`isManager`) may
// act — everyone else sees the grid read-only.
"use client";

import { ExternalLinkIcon, LockIcon, ZapIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { PLAN_LABELS, PlanGrid } from "@/components/billing/plan-grid";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { authClient } from "@/lib/auth-client";
import {
  createMcpPackCheckoutAction,
  createSerankingPackCheckoutAction,
} from "@/lib/billing/pack-actions";
import type { PlanDef, PlanName } from "@/lib/billing/plans";

export type BillingSettingsProps = {
  orgId: string;
  /** Better Auth subscription row id (NOT the Stripe id) — for plan changes. */
  subscriptionId: string | null;
  currentPlan: string | null;
  status: string | null;
  periodEnd: Date | null;
  cancelAtPeriodEnd: boolean;
  /** App-level 14-day trial stamp on the organization (no Stripe involved). */
  trialEndsAt: Date | null;
  isManager: boolean;
  /** Current-month MCP request usage (sum over the org's keys). */
  mcpUsage: number;
  /** Monthly MCP request limit from the plan (-1 = unlimited). */
  mcpLimit: number;
  /** Remaining one-off MCP credits (pack purchases). */
  mcpCreditBalance: number;
  /** True when redirected back from a successful pack checkout (?pack=success). */
  packSuccess: boolean;
  /** Remaining SE-Ranking syncs (metered mode — pack purchases). */
  serankingSyncBalance: number;
  /** True when redirected back from a successful SE-Ranking pack checkout
   *  (?pack=seranking-success). */
  serankingPackSuccess: boolean;
};

function formatDate(date: Date) {
  return new Intl.DateTimeFormat(undefined, { dateStyle: "medium" }).format(
    date,
  );
}

/** Whole days remaining (clamped at 0) until `date`. */
function daysLeft(date: Date) {
  return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 86_400_000));
}

export function BillingSettings({
  orgId,
  subscriptionId,
  currentPlan,
  status,
  periodEnd,
  cancelAtPeriodEnd,
  trialEndsAt,
  isManager,
  mcpUsage,
  mcpLimit,
  mcpCreditBalance,
  packSuccess,
  serankingSyncBalance,
  serankingPackSuccess,
}: BillingSettingsProps) {
  const t = useTranslations("Billing");
  // One pending flag for every Stripe action — they all leave the page.
  const [pendingAction, setPendingAction] = useState<string | null>(null);

  // Success toast after the pack checkout redirect — once (Strict Mode runs
  // effects twice in dev, so guard with a ref).
  const packToastShown = useRef(false);
  useEffect(() => {
    if (packSuccess && !packToastShown.current) {
      packToastShown.current = true;
      toast.success(t("packPurchased"));
    }
  }, [packSuccess, t]);

  // Same mechanic for the SE-Ranking sync pack (?pack=seranking-success).
  const serankingPackToastShown = useRef(false);
  useEffect(() => {
    if (serankingPackSuccess && !serankingPackToastShown.current) {
      serankingPackToastShown.current = true;
      toast.success(t("serankingPackPurchased"));
    }
  }, [serankingPackSuccess, t]);

  const hasSubscription =
    subscriptionId !== null &&
    (status === "active" || status === "trialing" || status === "past_due");

  // Display status: a real subscription wins; otherwise the app-level trial.
  const onAppTrial =
    !hasSubscription &&
    trialEndsAt !== null &&
    trialEndsAt.getTime() > Date.now();
  const trialExpired =
    !hasSubscription &&
    trialEndsAt !== null &&
    trialEndsAt.getTime() <= Date.now();

  async function choosePlan(plan: PlanDef, annual: boolean) {
    setPendingAction(`plan-${plan.name}`);
    try {
      const res = await authClient.subscription.upgrade({
        plan: plan.name,
        annual,
        referenceId: orgId,
        customerType: "organization",
        successUrl: "/settings/billing",
        cancelUrl: "/settings/billing",
        ...(subscriptionId ? { subscriptionId } : {}),
      });
      if (res.error) {
        toast.error(t("checkoutError"));
      }
    } catch {
      toast.error(t("checkoutError"));
    } finally {
      setPendingAction(null);
    }
  }

  async function buyPack() {
    setPendingAction("pack");
    try {
      const res = await createMcpPackCheckoutAction();
      if ("url" in res) {
        window.location.href = res.url;
      } else {
        toast.error(t("checkoutError"));
        setPendingAction(null);
      }
    } catch {
      toast.error(t("checkoutError"));
      setPendingAction(null);
    }
  }

  async function buySerankingPack() {
    setPendingAction("seranking-pack");
    try {
      const res = await createSerankingPackCheckoutAction();
      if ("url" in res) {
        window.location.href = res.url;
      } else {
        toast.error(t("checkoutError"));
        setPendingAction(null);
      }
    } catch {
      toast.error(t("checkoutError"));
      setPendingAction(null);
    }
  }

  async function openPortal() {
    setPendingAction("portal");
    try {
      const res = await authClient.subscription.billingPortal({
        referenceId: orgId,
        returnUrl: "/settings/billing",
      });
      if (res.error) {
        toast.error(t("portalError"));
      } else if (res.data?.url) {
        // Unlike upgrade(), billingPortal() does not auto-redirect — navigate
        // to the hosted Customer Portal ourselves.
        window.location.href = res.data.url;
      }
    } catch {
      toast.error(t("portalError"));
    } finally {
      setPendingAction(null);
    }
  }

  async function cancelPlan() {
    setPendingAction("cancel");
    try {
      const res = await authClient.subscription.cancel({
        referenceId: orgId,
        returnUrl: "/settings/billing",
      });
      if (res.error) {
        toast.error(t("portalError"));
      } else if (
        res.data &&
        "url" in res.data &&
        typeof res.data.url === "string"
      ) {
        // cancel() routes through the Customer Portal's cancel flow — same
        // manual redirect as billingPortal().
        window.location.href = res.data.url;
      }
    } catch {
      toast.error(t("portalError"));
    } finally {
      setPendingAction(null);
    }
  }

  async function restorePlan() {
    setPendingAction("restore");
    try {
      const res = await authClient.subscription.restore({
        referenceId: orgId,
      });
      if (res.error) {
        toast.error(t("portalError"));
      } else {
        window.location.reload();
      }
    } catch {
      toast.error(t("portalError"));
    } finally {
      setPendingAction(null);
    }
  }

  const busy = pendingAction !== null;

  return (
    <>
      <div className="mb-1 flex flex-col gap-1.5">
        <h1 className="font-heading font-semibold text-2xl tracking-tight">
          {t("title")}
        </h1>
      </div>

      {/* ── Current plan ─────────────────────────────────────────────── */}
      <Card>
        <CardHeader>
          <CardDescription>{t("currentPlan")}</CardDescription>
          <div className="flex flex-wrap items-center gap-3">
            <CardTitle className="text-xl">
              {hasSubscription && currentPlan
                ? (PLAN_LABELS[currentPlan as PlanName] ?? currentPlan)
                : onAppTrial
                  ? t("statusTrialing")
                  : "—"}
            </CardTitle>
            <StatusBadge
              t={t}
              status={status}
              hasSubscription={hasSubscription}
              onAppTrial={onAppTrial}
              trialExpired={trialExpired}
              cancelAtPeriodEnd={cancelAtPeriodEnd}
            />
          </div>
        </CardHeader>
        <CardContent className="flex flex-col gap-1 text-muted-foreground text-sm">
          {onAppTrial && trialEndsAt ? (
            <p>{t("trialDaysLeft", { days: daysLeft(trialEndsAt) })}</p>
          ) : null}
          {trialExpired && trialEndsAt ? (
            <p>{t("trialEndedOn", { date: formatDate(trialEndsAt) })}</p>
          ) : null}
          {hasSubscription && status === "trialing" && periodEnd ? (
            <p>{t("trialDaysLeft", { days: daysLeft(periodEnd) })}</p>
          ) : null}
          {hasSubscription && status !== "trialing" && periodEnd ? (
            <p>
              {cancelAtPeriodEnd
                ? t("endsOn", { date: formatDate(periodEnd) })
                : t("renewsOn", { date: formatDate(periodEnd) })}
            </p>
          ) : null}
          {!isManager ? (
            <p className="flex items-center gap-1.5 text-amber-600 dark:text-amber-400">
              <LockIcon className="size-3.5 shrink-0" />
              {t("lockedMemberHint")}
            </p>
          ) : null}
        </CardContent>
      </Card>

      {/* ── MCP usage + credit packs ─────────────────────────────────── */}
      <Card>
        <CardHeader>
          <CardDescription>{t("mcpUsageTitle")}</CardDescription>
          <CardTitle className="text-xl">
            {mcpLimit === -1
              ? t("mcpUnlimited")
              : t("mcpUsage", { used: mcpUsage, limit: mcpLimit })}
          </CardTitle>
        </CardHeader>
        <CardContent className="text-muted-foreground text-sm">
          <p>{t("creditBalance", { count: mcpCreditBalance })}</p>
        </CardContent>
        {isManager ? (
          <CardFooter className="flex flex-wrap items-center gap-3">
            <Button variant="outline" onClick={buyPack} disabled={busy}>
              <ZapIcon className="size-4" />
              {pendingAction === "pack" ? "…" : t("buyPack")}
            </Button>
            <span className="text-muted-foreground text-sm">
              {t("packDesc")}
            </span>
          </CardFooter>
        ) : null}
      </Card>

      {/* ── SE-Ranking sync balance + pack ───────────────────────────── */}
      <Card>
        <CardHeader>
          <CardDescription>{t("serankingTitle")}</CardDescription>
          <CardTitle className="text-xl">
            {t("serankingBalance", { count: serankingSyncBalance })}
          </CardTitle>
        </CardHeader>
        {isManager ? (
          <CardFooter className="flex flex-wrap items-center gap-3">
            <Button
              variant="outline"
              onClick={buySerankingPack}
              disabled={busy}
            >
              <ZapIcon className="size-4" />
              {pendingAction === "seranking-pack" ? "…" : t("serankingBuyPack")}
            </Button>
            <span className="text-muted-foreground text-sm">
              {t("serankingDesc")}
            </span>
          </CardFooter>
        ) : null}
      </Card>

      {/* ── Plans (toggle + grid + Enterprise) ───────────────────────── */}
      <PlanGrid
        onChoosePlan={choosePlan}
        isManager={isManager}
        busy={busy}
        pendingPlan={
          pendingAction?.startsWith("plan-")
            ? (pendingAction.slice("plan-".length) as PlanName)
            : null
        }
        currentPlan={hasSubscription ? (currentPlan as PlanName | null) : null}
      />

      {/* ── Manage billing (subscribed managers only) ────────────────── */}
      {hasSubscription && isManager ? (
        <Card>
          <CardHeader>
            <CardTitle>{t("manageBilling")}</CardTitle>
          </CardHeader>
          <CardFooter className="flex flex-wrap gap-3">
            <Button variant="outline" onClick={openPortal} disabled={busy}>
              <ExternalLinkIcon className="size-4" />
              {pendingAction === "portal" ? "…" : t("openPortal")}
            </Button>
            {cancelAtPeriodEnd ? (
              <Button onClick={restorePlan} disabled={busy}>
                {pendingAction === "restore" ? "…" : t("restorePlan")}
              </Button>
            ) : (
              <Button
                variant="ghost"
                className="text-muted-foreground hover:text-destructive"
                onClick={cancelPlan}
                disabled={busy}
              >
                {pendingAction === "cancel" ? "…" : t("cancelPlan")}
              </Button>
            )}
          </CardFooter>
        </Card>
      ) : null}
    </>
  );
}

function StatusBadge({
  t,
  status,
  hasSubscription,
  onAppTrial,
  trialExpired,
  cancelAtPeriodEnd,
}: {
  t: ReturnType<typeof useTranslations<"Billing">>;
  status: string | null;
  hasSubscription: boolean;
  onAppTrial: boolean;
  trialExpired: boolean;
  cancelAtPeriodEnd: boolean;
}) {
  if (hasSubscription) {
    if (status === "trialing") {
      return (
        <Badge
          variant="secondary"
          className="border-primary/30 bg-primary/15 text-primary"
        >
          {t("statusTrialing")}
        </Badge>
      );
    }
    if (cancelAtPeriodEnd) {
      return (
        <Badge
          variant="secondary"
          className="border-amber-500/30 bg-amber-500/15 text-amber-600 dark:text-amber-400"
        >
          {t("statusCanceled")}
        </Badge>
      );
    }
    return (
      <Badge
        variant="secondary"
        className="border-emerald-500/30 bg-emerald-500/15 text-emerald-600 dark:text-emerald-400"
      >
        {t("statusActive")}
      </Badge>
    );
  }
  if (onAppTrial) {
    return (
      <Badge
        variant="secondary"
        className="border-primary/30 bg-primary/15 text-primary"
      >
        {t("statusTrialing")}
      </Badge>
    );
  }
  if (trialExpired || status === "canceled") {
    return <Badge variant="destructive">{t("statusExpired")}</Badge>;
  }
  return null;
}
