"use client";

import { useState, useEffect } from "react";
import { useSearchParams } from "next/navigation";
import { useRouter } from "@/i18n/navigation";
import { useTranslations } from "next-intl";
import { Card, CardHeader } from "@/components/ui/card";
import type { OrgBillingConfig } from "@/types";

interface Props {
  config: OrgBillingConfig | null;
  /**
   * True when this org has been flipped to pay-by-invoice by admin.
   * The card UI still renders (admin-set customers might also have
   * a saved card as backup), but with an info note that auto-charge
   * is disabled by their billing mode.
   */
  isPayByInvoice: boolean;
  /**
   * Personal-account flag from the session. Personal accounts are
   * single-user B2C tenants and don't have the bank-transfer
   * affordance — they pay by card or not at all. We hide the
   * "Bank transfer is available on request" hint for these accounts
   * to keep the messaging unambiguous.
   */
  isPersonal: boolean;
}

const BRAND_LABELS: Record<string, string> = {
  visa: "Visa",
  mastercard: "Mastercard",
  amex: "American Express",
  discover: "Discover",
  jcb: "JCB",
  diners: "Diners Club",
  unionpay: "UnionPay",
};

/**
 * Saved-card management — Phase 9.
 *
 * State derives entirely from the OrgBillingConfig the server
 * sends down. Actions are: set up (no card → Checkout setup
 * mode), update (existing card → same Checkout flow, replaces),
 * remove (DELETE the PM in Stripe + clear local fields), toggle
 * auto-charge.
 *
 * The component watches for ?card_setup=success on mount and
 * fires a router.refresh() — the success redirect from Stripe
 * lands here and the new card info needs to load. We also strip
 * the query param so a page reload doesn't re-trigger.
 */
export function SavedCardSection({
  config,
  isPayByInvoice,
  isPersonal,
}: Props) {
  const t = useTranslations("settingsBilling");
  const router = useRouter();
  const searchParams = useSearchParams();
  const [busy, setBusy] = useState<null | "setup" | "remove">(null);
  const [error, setError] = useState("");

  // Refresh + clean the URL when Stripe redirects back. Stripe's
  // webhook is what actually persists the card; the refresh just
  // re-fetches the server-side config so the new fields appear.
  useEffect(() => {
    const status = searchParams.get("card_setup");
    if (status === "success") {
      router.replace("/settings/billing");
      router.refresh();
    } else if (status === "cancelled") {
      // Just clean the URL. No-op otherwise.
      router.replace("/settings/billing");
    }
  }, [searchParams, router]);

  const hasCard = !!config?.stripeDefaultPaymentMethodId;
  const autoChargeOn = config?.autoChargeEnabled !== false;

  const startSetup = async () => {
    setError("");
    setBusy("setup");
    try {
      const res = await fetch("/api/billing/setup-card", { method: "POST" });
      const j = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(j.error || `HTTP ${res.status}`);
      if (!j.url) throw new Error("No redirect URL returned");
      // Hard-redirect — Stripe Checkout doesn't run inside the SPA.
      window.location.href = j.url;
    } catch (e: any) {
      setError(e.message);
      setBusy(null);
    }
  };

  const removeCard = async () => {
    if (!confirm(t("savedCardRemoveConfirm"))) return;
    setError("");
    setBusy("remove");
    try {
      const res = await fetch("/api/billing/saved-card", { method: "DELETE" });
      const j = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(j.error || `HTTP ${res.status}`);
      router.refresh();
    } catch (e: any) {
      setError(e.message);
    } finally {
      setBusy(null);
    }
  };

  // Empty state — no card on file.
  if (!hasCard) {
    return (
      <Card>
        <CardHeader>{t("savedCardHeading")}</CardHeader>
        <div className="p-5">
          <p className="text-sm text-text-secondary mb-4">
            {t("savedCardEmptyBody")}
          </p>
          {/* Phase 9: prominent policy notice. Auto-pay is the
              expected default — emphasise that failure to keep a
              chargeable card on file may result in tenant suspension.
              Sits above the CTA so it's seen before the click. */}
          <div className="text-sm rounded-md border border-warning/40 bg-warning/10 text-warning px-4 py-3 mb-4">
            <strong className="block mb-1">
              {t("savedCardAutoPayRequiredHeading")}
            </strong>
            <span className="text-text-secondary">
              {t("savedCardAutoPayRequiredBody")}
            </span>
          </div>
          {error && (
            <div className="text-sm text-error mb-3">{error}</div>
          )}
          <button
            onClick={startSetup}
            disabled={busy !== null}
            className="px-4 py-2 rounded-md bg-accent text-surface-0 text-sm disabled:opacity-50"
          >
            {busy === "setup" ? t("savedCardRedirecting") : t("savedCardSetupBtn")}
          </button>
          {/* Bank-transfer hint shown only for company accounts.
              Personal (B2C) accounts pay by card only — surfacing
              the alternative would only confuse. */}
          {!isPersonal && (
            <p className="text-xs text-text-muted mt-4">
              {t("savedCardBankTransferHint")}{" "}
              <a
                href="/support"
                className="text-accent hover:underline"
              >
                {t("savedCardBankTransferLink")}
              </a>
            </p>
          )}
        </div>
      </Card>
    );
  }

  // Card on file.
  const brandLabel =
    config?.stripePmBrand
      ? BRAND_LABELS[config.stripePmBrand] ?? config.stripePmBrand
      : t("savedCardBrandUnknown");
  const last4 = config?.stripePmLast4 ?? "????";
  const expMonth = config?.stripePmExpMonth;
  const expYear = config?.stripePmExpYear;
  const expLabel =
    expMonth && expYear
      ? `${String(expMonth).padStart(2, "0")}/${String(expYear).slice(-2)}`
      : "";
  // Heuristic for "expiring soon" — if the card expires this calendar
  // month or next. Stripe's pre-expiration emails handle the real
  // notification, but a portal hint is friendly too.
  const now = new Date();
  const expiringSoon =
    expMonth &&
    expYear &&
    (expYear < now.getFullYear() ||
      (expYear === now.getFullYear() && expMonth <= now.getMonth() + 2));

  return (
    <Card>
      <CardHeader>{t("savedCardHeading")}</CardHeader>
      <div className="p-5">
        <div className="flex items-center justify-between mb-4 flex-wrap gap-3">
          <div className="flex items-center gap-3">
            <span className="font-mono text-sm">
              {brandLabel} •••• {last4}
            </span>
            {expLabel && (
              <span
                className={`text-xs ${
                  expiringSoon ? "text-warning" : "text-text-muted"
                }`}
              >
                {t("savedCardExpires", { date: expLabel })}
              </span>
            )}
          </div>
          <div className="flex items-center gap-3 text-xs">
            <span
              className={`px-2 py-0.5 rounded text-xs ${
                autoChargeOn
                  ? "bg-success/15 text-success"
                  : "bg-text-muted/15 text-text-muted"
              }`}
            >
              {autoChargeOn
                ? t("savedCardAutoChargeOn")
                : t("savedCardAutoChargeOff")}
            </span>
          </div>
        </div>

        {isPayByInvoice && (
          <div className="text-xs text-text-muted bg-surface-3 rounded-md px-3 py-2 mb-3">
            {t("savedCardPayByInvoiceNote")}
          </div>
        )}

        {/* If the card is on file but the customer has actively
            disabled auto-pay, surface the suspension-risk reminder.
            Not shown when admin has flipped them to pay-by-invoice —
            that's a different deal and the note above explains it. */}
        {!isPayByInvoice && !autoChargeOn && (
          <div className="text-xs rounded-md border border-warning/40 bg-warning/10 text-warning px-3 py-2 mb-3">
            {t("savedCardAutoPayDisabledNote")}
          </div>
        )}

        {error && <div className="text-sm text-error mb-3">{error}</div>}

        <div className="flex gap-2 flex-wrap">
          <button
            onClick={startSetup}
            disabled={busy !== null}
            className="px-3 py-1.5 rounded-md border border-border text-sm disabled:opacity-50 hover:bg-surface-3"
          >
            {busy === "setup"
              ? t("savedCardRedirecting")
              : t("savedCardUpdateBtn")}
          </button>
          <button
            onClick={removeCard}
            disabled={busy !== null}
            className="px-3 py-1.5 rounded-md border border-error text-error text-sm disabled:opacity-50 hover:bg-error/10 ml-auto"
          >
            {busy === "remove"
              ? t("savedCardRemoving")
              : t("savedCardRemoveBtn")}
          </button>
        </div>

        {/* Bank-transfer hint shown only for company accounts. */}
        {!isPersonal && (
          <p className="text-xs text-text-muted mt-4">
            {t("savedCardBankTransferHint")}{" "}
            <a
              href="/support"
              className="text-accent hover:underline"
            >
              {t("savedCardBankTransferLink")}
            </a>
          </p>
        )}
      </div>
    </Card>
  );
}
