"use client";

import { useRouter } from "next/navigation";
import { useMemo, useState } from "react";
import { UpgradeProButton } from "@/components/UpgradeProButton";
import {
  CREDIT_PRICE_CENTS,
  FREE_EXTRA_CREDITS_MAX,
  FREE_TOP_UP_MAX,
  FREE_TOP_UP_MIN,
  formatCreditPrice,
  formatEuroFromCents,
} from "@/lib/credits";

type Purchase = {
  id: string;
  credits: number;
  amountCents: number;
  completedAt: string | null;
};

type Props = {
  initialCredits: number;
  stripeConfigured: boolean;
  recentPurchases?: Purchase[];
};

export function CreditPurchasePanel({
  initialCredits,
  stripeConfigured,
  recentPurchases = [],
}: Props) {
  const router = useRouter();
  const [creditsBalance, setCreditsBalance] = useState(initialCredits);
  const [amount, setAmount] = useState(FREE_TOP_UP_MIN);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);

  const room = Math.max(0, FREE_EXTRA_CREDITS_MAX - creditsBalance);
  const maxBuyable = Math.min(FREE_TOP_UP_MAX, room);
  const minBuyable = room < FREE_TOP_UP_MIN ? 0 : FREE_TOP_UP_MIN;
  const atCap = room === 0;

  const totalLabel = useMemo(() => formatCreditPrice(amount), [amount]);
  const unitLabel = formatCreditPrice(1);

  async function handleBuy() {
    setLoading(true);
    setError(null);
    setMessage(null);
    try {
      const res = await fetch("/api/account/credits", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ credits: amount }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Checkout failed");

      if (data.mocked) {
        setCreditsBalance((c) => c + (data.granted ?? amount));
        setMessage(
          `Granted +${data.granted ?? amount} credits for ${formatEuroFromCents(data.amountCents ?? amount * CREDIT_PRICE_CENTS)} (dev mock).`,
        );
        setLoading(false);
        router.refresh();
        return;
      }

      if (!data.url) throw new Error("No checkout URL returned");
      window.location.href = data.url;
    } catch (err) {
      setError(err instanceof Error ? err.message : "Checkout failed");
      setLoading(false);
    }
  }

  function clampAmount(value: number) {
    if (maxBuyable < FREE_TOP_UP_MIN) return FREE_TOP_UP_MIN;
    return Math.min(maxBuyable, Math.max(FREE_TOP_UP_MIN, value));
  }

  return (
    <div className="mt-6 border-t border-gray-800 pt-6">
      <h3 className="mb-1 text-sm font-semibold uppercase tracking-wider text-gray-500">
        Extra credits
      </h3>
      <p className="mb-4 text-sm text-gray-400">
        Free plan: 10 monthly videos + up to {FREE_EXTRA_CREDITS_MAX} paid extras (
        {unitLabel} each). After both are used, Pro is required.
      </p>

      <div className="mb-4 rounded border border-gray-800 bg-surface p-4">
        <p className="text-xs font-semibold uppercase tracking-wider text-gray-500">
          Extra credit balance
        </p>
        <p className="mt-1 text-2xl font-semibold text-white">
          {Math.min(creditsBalance, FREE_EXTRA_CREDITS_MAX)}
          <span className="text-base font-normal text-gray-400">
            {" "}
            / {FREE_EXTRA_CREDITS_MAX} credits
          </span>
        </p>
        {creditsBalance > FREE_EXTRA_CREDITS_MAX && (
          <p className="mt-1 text-xs text-amber-400">
            You have {creditsBalance} extras from earlier purchases; no further top-ups until
            under {FREE_EXTRA_CREDITS_MAX}.
          </p>
        )}
      </div>

      {atCap ? (
        <div className="space-y-2 rounded border border-amber-500/30 bg-amber-500/5 px-4 py-3 text-sm text-amber-100">
          <p>
            Free extras are capped at {FREE_EXTRA_CREDITS_MAX}. When your monthly 10 and these
            extras are gone, continue with Pro (€5/mo · 50 videos).
          </p>
          <UpgradeProButton className="font-medium text-accent underline hover:text-white" />
        </div>
      ) : !stripeConfigured ? (
        <p className="text-sm text-amber-400">
          Card checkout is not configured yet (missing Stripe keys). In development you can also
          use{" "}
          <code className="text-gray-300">POST /api/dev/grant-credits</code>.
        </p>
      ) : (
        <div className="space-y-4">
          <label className="block text-sm text-gray-300">
            Credits to buy ({FREE_TOP_UP_MIN}–{maxBuyable})
            <div className="mt-2 flex items-center gap-3">
              <input
                type="range"
                min={minBuyable || FREE_TOP_UP_MIN}
                max={maxBuyable}
                value={clampAmount(amount)}
                onChange={(e) => setAmount(clampAmount(Number(e.target.value)))}
                className="w-full accent-[var(--accent,#3b82f6)]"
              />
              <input
                type="number"
                min={FREE_TOP_UP_MIN}
                max={maxBuyable}
                value={clampAmount(amount)}
                onChange={(e) =>
                  setAmount(
                    clampAmount(Math.floor(Number(e.target.value)) || FREE_TOP_UP_MIN),
                  )
                }
                className="w-16 rounded border border-gray-700 bg-surface px-2 py-1 text-center text-white"
              />
            </div>
          </label>

          <p className="text-sm text-gray-300">
            Total:{" "}
            <span className="font-semibold text-white">{totalLabel}</span>
            <span className="text-gray-500">
              {" "}
              ({unitLabel} × {clampAmount(amount)})
            </span>
          </p>

          <button
            type="button"
            disabled={loading}
            onClick={handleBuy}
            className="rounded bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50"
          >
            {loading
              ? "Starting checkout…"
              : `Buy ${clampAmount(amount)} credits (${totalLabel})`}
          </button>
        </div>
      )}

      {message && <p className="mt-3 text-sm text-emerald-400">{message}</p>}
      {error && <p className="mt-3 text-sm text-red-400">{error}</p>}

      {recentPurchases.length > 0 && (
        <div className="mt-6">
          <h4 className="mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500">
            Recent purchases
          </h4>
          <ul className="space-y-1 text-sm text-gray-400">
            {recentPurchases.map((p) => (
              <li key={p.id}>
                +{p.credits} credits · {formatEuroFromCents(p.amountCents)}
                {p.completedAt
                  ? ` · ${new Date(p.completedAt).toLocaleDateString()}`
                  : ""}
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}
