"use client";
import React, { Suspense, useEffect, useMemo, useState } from "react";
import { useSearchParams } from "next/navigation";
import { useAuth } from "@/hooks/useAuth";
import { apiFetch } from "@/lib/api";
import { useDismissingState } from "@/hooks/useDismissingState";

function MakePaymentContent() {
  const searchParams = useSearchParams();
  const registrationId = searchParams.get("registrationId");
  const { token } = useAuth();
  const [loading, setLoading] = useState(false);
  const [error, setError] = useDismissingState<string | null>(null);
  const [info, setInfo] = useDismissingState<string | null>(null);
  const [registration, setRegistration] = useState<any | null>(null);
  const [payments, setPayments] = useState<any[]>([]);
  const [amount, setAmount] = useState<string>("");
  const [priceUpdated, setPriceUpdated] = useState<{ newTotal: number; message: string } | null>(null);

  // Compute effective unit price for a registration option.
  // Uses priceSnapshot when available (authoritative backend price, variant-aware).
  // Falls back to deadline-only early-bird calculation for legacy rows without a snapshot.
  const optionUnitPrice = (opt: any, referenceTime: any, atTime: Date): number => {
    if (opt.priceSnapshot !== null && opt.priceSnapshot !== undefined) {
      return Number(opt.priceSnapshot);
    }
    const eo = opt.eventOption;
    const variantId: string | null = opt.variantId || null;
    const base = (opt.variant?.price !== null && opt.variant?.price !== undefined)
      ? Number(opt.variant.price)
      : Number(eo?.price || 0);
    const allTiers = Array.isArray(eo?.earlyBirdTiers) ? eo.earlyBirdTiers.slice() : [];
    const tiers = variantId
      ? allTiers.filter((t: any) => t.variantId === variantId)
      : allTiers.filter((t: any) => !t.variantId);
    if (tiers.length === 0) return base;
    const t = atTime ? new Date(atTime) : new Date();
    const ref = referenceTime ? new Date(referenceTime) : t;
    const applicable = tiers
      .map((x: any) => ({ ...x, deadline: new Date(x.deadline) }))
      .filter((x: any) => (ref < x.deadline) && (t < x.deadline))
      .sort((a: any, b: any) => a.deadline.getTime() - b.deadline.getTime() || (a.order||0) - (b.order||0) || a.price - b.price);
    if (applicable.length === 0) return base;
    const price = Number(applicable[0].price);
    return (price >= 0) ? price : base;
  };

  const totals = useMemo(() => {
    if (!registration) return { totalDue: 0, totalPaid: 0, outstanding: 0 };
    const now = new Date();
    // totalDue uses priceSnapshot — not time-dependent, consistent with what the backend charges
    const totalDue = (registration.registrationOptions || []).reduce((s: number, opt: any) => s + optionUnitPrice(opt, null, now) * (opt.quantity || 0), 0);
    const totalPaid = payments.reduce((s: number, p: any) => s + (p.amount || 0), 0);
    const outstanding = Math.max(0, totalDue - totalPaid);
    return { totalDue, totalPaid, outstanding };
  }, [registration, payments]);

  const minAllowed = useMemo(() => {
    if (totals.outstanding <= 0) return 0;
    return totals.outstanding >= 15 ? 15 : totals.outstanding;
  }, [totals.outstanding]);

  useEffect(() => {
    (async () => {
      if (!token || !registrationId) return;
      try {
        setError(null);
        setLoading(true);
        const reg = await apiFetch<any>(`/api/registrations/${encodeURIComponent(registrationId)}`, { authToken: token });
        setRegistration(reg);
        const pays = await apiFetch<any[]>(`/api/payments/registration/${encodeURIComponent(registrationId)}`, { authToken: token });
        setPayments(pays);
      } catch (e: any) {
        setError(e?.message || "Failed to load registration");
      } finally {
        setLoading(false);
      }
    })();
  }, [token, registrationId]);

  useEffect(() => {
    if (totals.outstanding <= 0) {
      setAmount("");
    }
  }, [totals.outstanding]);

  const submit = async () => {
    if (!token || !registrationId) return;
    const amt = parseFloat(amount);
    if (!(amt > 0)) { setError("Enter a valid amount"); return; }
    if (amt > totals.outstanding) { setError(`Amount cannot exceed outstanding (R ${totals.outstanding.toFixed(2)})`); return; }
    if (amt < minAllowed) {
      if (totals.outstanding >= 15) {
        setError("Minimum payment is R15");
      } else {
        setError(`Please pay the remaining outstanding amount (R ${totals.outstanding.toFixed(2)})`);
      }
      return;
    }
    try {
      setError(null);
      setInfo(null);
      setPriceUpdated(null);
      setLoading(true);
      const res = await apiFetch<{ redirectUrl?: string; priceUpdated?: boolean; newTotal?: number; message?: string }>("/api/payments/yoco-checkout", {
        method: "POST",
        body: {
          registrationId,
          amount: amt,
          successUrl: window.location.origin + "/payment/success",
          cancelUrl: window.location.origin + "/payment/cancel",
          failureUrl: window.location.origin + "/payment/failure",
        },
        authToken: token,
      });
      if (res.priceUpdated) {
        // Early-bird price changed — show warning and reload registration data
        setPriceUpdated({ newTotal: res.newTotal ?? 0, message: res.message ?? 'Prices have changed.' });
        // Reload registration so totals reflect updated priceSnapshot
        try {
          const reg = await apiFetch<any>(`/api/registrations/${encodeURIComponent(registrationId)}`, { authToken: token });
          setRegistration(reg);
          const pays = await apiFetch<any[]>(`/api/payments/registration/${encodeURIComponent(registrationId)}`, { authToken: token });
          setPayments(pays);
        } catch {}
        setAmount("");
        return;
      }
      setInfo("Redirecting to payment...");
      window.location.href = res.redirectUrl!;
    } catch (e: any) {
      setError(e?.message || "Failed to create checkout");
    } finally {
      setLoading(false);
    }
  };

  if (!registrationId) return <div className="p-6">Missing registrationId.</div>;

  return (
    <div className="max-w-xl mx-auto w-full p-6">
      <h1 className="text-2xl font-semibold mb-4">Make a payment</h1>
      {error && <p className="text-red-600 text-sm mb-3">{error}</p>}
      {info && <p className="text-green-700 text-sm mb-3">{info}</p>}
      {priceUpdated && (
        <div className="mb-4 p-3 border border-amber-300 bg-amber-50 rounded text-sm text-amber-800">
          <strong>Pricing has changed.</strong> {priceUpdated.message}
          <div className="mt-1">New outstanding: <strong>R {priceUpdated.newTotal.toFixed(2)}</strong></div>
          <button
            className="mt-2 text-xs underline text-amber-700 hover:text-amber-900"
            onClick={() => setPriceUpdated(null)}
          >OK, I understand — continue with new price</button>
        </div>
      )}

      {registration ? (
        <div className="border rounded p-3 mb-4">
          <div className="font-medium">{registration.event?.title || registration.eventId}</div>
          <div className="text-sm text-gray-600">Registration #{registration.id.slice(0,8)}</div>
          <div className="mt-2 text-sm">
            <div>Total: R {totals.totalDue.toFixed(2)}</div>
            <div>Paid: R {totals.totalPaid.toFixed(2)}</div>
            <div>Outstanding: <span className={totals.outstanding>0?"text-red-600":"text-green-700"}>R {totals.outstanding.toFixed(2)}</span></div>
          </div>
          {(() => {
            const tiers = (registration.registrationOptions || []).flatMap((ro: any) => Array.isArray(ro.eventOption?.earlyBirdTiers) ? ro.eventOption.earlyBirdTiers : []);
            const upcoming = tiers.map((t: any) => ({ ...t, deadline: new Date(t.deadline) })).filter((t: any) => new Date() < t.deadline).sort((a: any, b: any) => a.deadline.getTime() - b.deadline.getTime());
            if (upcoming.length === 0) return null;
            const d = upcoming[0].deadline as Date;
            const dateStr = d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: '2-digit' });
            return <div className="mt-2 text-xs text-amber-700">Early bird pricing applies if paid before {dateStr}.</div>;
          })()}
        </div>
      ) : (
        <p className="text-sm text-gray-600 mb-4">Loading registration...</p>
      )}

      <label className="block text-sm font-medium mb-1">Amount (R)</label>
      <input
        type="number"
        min={minAllowed.toFixed(2)}
        max={totals.outstanding > 0 ? totals.outstanding.toFixed(2) : "0"}
        step="1"
        placeholder={totals.outstanding >= 15 ? "Enter amount (min R15)" : `Enter amount (max R ${totals.outstanding.toFixed(2)})`}
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
        disabled={totals.outstanding <= 0}
        className="w-full border rounded px-3 py-2 mb-1 disabled:opacity-60"
      />
      {totals.outstanding > 0 && (
        <p className="text-xs text-gray-600 mb-3">Minimum payment {totals.outstanding >= 15 ? "is R15" : `is the remaining outstanding amount (R ${totals.outstanding.toFixed(2)})`}.</p>
      )}
      <button
        disabled={loading || totals.outstanding <= 0}
        onClick={submit}
        className="bg-green-600 text-white px-4 py-2 rounded disabled:opacity-60"
      >{loading?"Creating checkout...": totals.outstanding <= 0 ? "No outstanding amount" : "Pay now"}</button>
    </div>
  );
}

export default function MakePaymentPage() {
  return (
    <Suspense fallback={<div className="p-6">Loading...</div>}>
      <MakePaymentContent />
    </Suspense>
  );
}
