"use client";

import { useEffect, useId, useMemo, useRef, useState } from "react";
import Link from "next/link";
import { CreditCard, LockKeyhole, PackageCheck } from "lucide-react";
import { ProductVisual } from "@/components/ProductVisual";
import { readCartItems, writeCartItems, type StoredCartItem } from "@/lib/cart-storage";
import { currency, displayPrice } from "@/lib/utils";

type Product = { id: string; name: string; customerPrice: string; totalSalePrice: string; manualPrice: string };
type SquareConfig = { applicationId: string; locationId: string; environment: "sandbox" | "production" };
type PayPalConfig = { clientId: string; serverConfigured: boolean };
type PaymentMethod = "STRIPE" | "PAYPAL" | "SQUARE";
type SquareTokenizeResult = { status: string; token?: string; errors?: Array<{ message?: string }> };
type SquareCard = {
  attach: (selector: string) => Promise<void>;
  tokenize: () => Promise<SquareTokenizeResult>;
  destroy?: () => Promise<void> | void;
};

declare global {
  interface Window {
    Square?: {
      payments: (applicationId: string, locationId: string) => {
        card: () => Promise<SquareCard>;
      };
    };
  }
}

let squareScriptPromise: Promise<void> | null = null;

function fetchCartProducts(stored: StoredCartItem[]) {
  const controller = new AbortController();
  const timeout = window.setTimeout(() => controller.abort(), 4000);
  return fetch(`/api/cart?ids=${stored.map((item) => item.productId).join(",")}`, { signal: controller.signal })
    .then((res) => res.ok ? res.json() : [])
    .then((data) => Array.isArray(data) ? data : [])
    .catch(() => [])
    .finally(() => window.clearTimeout(timeout));
}

function loadSquareScript(environment: SquareConfig["environment"]) {
  if (typeof window === "undefined") return Promise.reject(new Error("Square can only load in the browser."));
  if (window.Square) return Promise.resolve();
  if (squareScriptPromise) return squareScriptPromise;

  const scriptId = "square-web-payments-sdk";
  const src = environment === "production" ? "https://web.squarecdn.com/v1/square.js" : "https://sandbox.web.squarecdn.com/v1/square.js";

  squareScriptPromise = new Promise((resolve, reject) => {
    const existing = document.getElementById(scriptId) as HTMLScriptElement | null;
    if (existing) {
      if (existing.dataset.loaded === "true" || window.Square) {
        resolve();
        return;
      }
      existing.addEventListener("load", () => resolve(), { once: true });
      existing.addEventListener("error", () => reject(new Error("Square SDK failed to load.")), { once: true });
      return;
    }

    const script = document.createElement("script");
    script.id = scriptId;
    script.src = src;
    script.async = true;
    script.onload = () => {
      script.dataset.loaded = "true";
      resolve();
    };
    script.onerror = () => reject(new Error("Square SDK failed to load."));
    document.head.appendChild(script);
  });

  return squareScriptPromise;
}

function squareTokenMessage(result: SquareTokenizeResult) {
  return result.errors?.map((error) => error.message).filter(Boolean).join(" ") || "Square could not tokenize the payment details.";
}

export function CheckoutClient({ squareConfig, paypalConfig }: { squareConfig: SquareConfig; paypalConfig: PayPalConfig }) {
  const publicSquareApplicationId = process.env.NEXT_PUBLIC_SQUARE_APPLICATION_ID?.trim() || "";
  const publicSquareLocationId = process.env.NEXT_PUBLIC_SQUARE_LOCATION_ID?.trim() || "";
  const publicPayPalClientId = process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID?.trim() || "";
  const squareApplicationId = squareConfig.applicationId.trim() || publicSquareApplicationId;
  const squareLocationId = squareConfig.locationId.trim() || publicSquareLocationId;
  const squareEnabled = Boolean(squareApplicationId && squareLocationId);
  const paypalEnabled = Boolean((paypalConfig.clientId.trim() || publicPayPalClientId) && paypalConfig.serverConfigured);
  const [items, setItems] = useState<StoredCartItem[]>([]);
  const [products, setProducts] = useState<Product[]>([]);
  const [error, setError] = useState("");
  const [cartChecked, setCartChecked] = useState(false);
  const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>(squareEnabled ? "SQUARE" : paypalEnabled ? "PAYPAL" : "STRIPE");
  const [squareError, setSquareError] = useState("");
  const [squareLoading, setSquareLoading] = useState(false);
  const [squareReady, setSquareReady] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const squareCardRef = useRef<SquareCard | null>(null);
  const squareContainerId = useId().replace(/:/g, "");
  const rows = items.map((item) => ({ item, product: products.find((product) => product.id === item.productId) })).filter((row) => row.product);
  const subtotal = useMemo(() => rows.reduce((sum, row) => sum + displayPrice(row.product!) * row.item.quantity, 0), [rows]);

  useEffect(() => {
    let active = true;
    const failSafe = window.setTimeout(() => {
      if (!active) return;
      setProducts([]);
      setCartChecked(true);
    }, 4500);

    async function hydrateCheckoutCart() {
      try {
        const stored = readCartItems();
        if (!active) return;
        setItems(stored);

        if (!stored.length) {
          setProducts([]);
          return;
        }

        const data = await fetchCartProducts(stored);
        if (!active) return;

        const validIds = new Set(data.map((product: Product) => product.id));
        const validItems = stored.filter((item) => validIds.has(item.productId));
        setItems(validItems);
        setProducts(data.filter((product: Product) => validIds.has(product.id)));

      } catch {
        if (!active) return;
        setProducts([]);
      } finally {
        window.clearTimeout(failSafe);
        if (active) setCartChecked(true);
      }
    }

    hydrateCheckoutCart();

    return () => {
      active = false;
      window.clearTimeout(failSafe);
    };
  }, []);

  useEffect(() => {
    if (paymentMethod === "SQUARE") return;
    setSquareError("");
    setSquareLoading(false);
    setSquareReady(false);
    const currentCard = squareCardRef.current;
    squareCardRef.current = null;
    if (currentCard?.destroy) {
      void Promise.resolve(currentCard.destroy()).catch(() => undefined);
    }
  }, [paymentMethod]);

  useEffect(() => {
    if (paymentMethod !== "SQUARE") return;
    if (!squareEnabled) {
      setSquareReady(false);
      setSquareLoading(false);
      setSquareError("Square checkout is temporarily unavailable.");
      return;
    }

    let active = true;
    setSquareLoading(true);
    setSquareError("");
    setSquareReady(false);

    async function initializeSquareCard() {
      try {
        await loadSquareScript(squareConfig.environment);
        if (!active) return;
        if (!window.Square) throw new Error("Square payment form could not be loaded.");
        const payments = window.Square.payments(squareApplicationId, squareLocationId);
        const card = await payments.card();
        await card.attach(`#${squareContainerId}`);
        if (!active) {
          if (card.destroy) await Promise.resolve(card.destroy());
          return;
        }
        squareCardRef.current = card;
        setSquareReady(true);
      } catch (squareInitError) {
        if (!active) return;
        const message = squareInitError instanceof Error ? squareInitError.message : "Square payment form could not be initialized.";
        setSquareError(message);
      } finally {
        if (active) setSquareLoading(false);
      }
    }

    initializeSquareCard();

    return () => {
      active = false;
    };
  }, [paymentMethod, squareApplicationId, squareConfig.environment, squareLocationId, squareContainerId, squareEnabled]);

  async function submit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError("");
    setSubmitting(true);

    try {
      const form = new FormData(event.currentTarget);
      const payload = Object.fromEntries(form.entries());
      const checkoutItems = rows.map((row) => row.item);
      let squareSourceId: string | undefined;

      if (paymentMethod === "SQUARE") {
        if (!squareEnabled) {
          setError("Square checkout is temporarily unavailable.");
          return;
        }
        if (!squareCardRef.current || !squareReady) {
          setError(squareError || "Square payment form is still loading. Please wait a moment and try again.");
          return;
        }
        const tokenResult = await squareCardRef.current.tokenize();
        if (tokenResult.status !== "OK" || !tokenResult.token) {
          setError(squareTokenMessage(tokenResult));
          return;
        }
        squareSourceId = tokenResult.token;
      }

      const res = await fetch("/api/checkout", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          ...payload,
          paymentMethod,
          squareSourceId,
          agreementAccepted: form.get("agreementAccepted") === "on",
          simulateFailure: false,
          items: checkoutItems
        })
      });
      const data = await res.json();
      if (!res.ok) {
        setError(data.error || "Checkout failed.");
        return;
      }
      if (data.clearCart !== false) {
        writeCartItems([]);
      }
      const redirect = typeof data.redirect === "string" && data.redirect ? data.redirect : "/payment-success";
      if (redirect.startsWith("http://") || redirect.startsWith("https://")) {
        window.location.href = redirect;
        return;
      }
      const separator = redirect.includes("?") ? "&" : "?";
      window.location.href = `${redirect}${separator}order=${encodeURIComponent(data.orderNumber || "")}`;
    } catch {
      setError("Checkout could not be completed. Please try again.");
    } finally {
      setSubmitting(false);
    }
  }

  if (!cartChecked) {
    return (
      <section className="container-grid py-12">
        <div className="grid gap-6 lg:grid-cols-[1fr_390px]">
          <div className="grid gap-5">
            <div className="panel h-40 p-5"><div className="h-5 w-48 rounded bg-[#E6DFD0]" /><div className="mt-5 h-20 rounded bg-[#F7F5EF]" /></div>
            <div className="panel h-52 p-5"><div className="h-5 w-44 rounded bg-[#E6DFD0]" /><div className="mt-5 h-28 rounded bg-[#F7F5EF]" /></div>
          </div>
          <div className="panel h-56 p-5"><div className="h-5 w-36 rounded bg-[#E6DFD0]" /><div className="mt-5 h-16 rounded bg-[#F7F5EF]" /></div>
        </div>
      </section>
    );
  }

  if (!items.length || rows.length === 0) {
    return (
      <section className="container-grid py-12">
        <div className="mx-auto max-w-xl rounded border border-[#E5E1D8] bg-white p-8 text-center shadow-sm">
          <div className="product-media mx-auto mb-5 h-32 w-32 overflow-hidden rounded-full border border-[#E5E1D8]">
            <ProductVisual product={{ name: "Silver Coin", metalType: "SILVER", productType: "COIN" }} compact />
          </div>
          <h1 className="text-3xl font-black">Your cart is empty</h1>
          <p className="mt-3 text-[#666]">Add bullion products to your cart before starting checkout.</p>
          <div className="mt-6 flex flex-wrap justify-center gap-3">
            <Link href="/gold" className="btn btn-primary">Shop Gold</Link>
            <Link href="/silver" className="btn btn-secondary">Shop Silver</Link>
            <Link href="/products" className="btn btn-secondary">View All Products</Link>
          </div>
        </div>
      </section>
    );
  }

  return (
    <section className="container-grid py-8">
      <div className="text-sm text-[#666]"><Link href="/">Home</Link> / <Link href="/cart">Cart</Link> / Checkout</div>
      <div className="mt-3 flex flex-wrap items-end justify-between gap-3 rounded border border-[#E6DFD0] bg-white p-5">
        <div>
          <h1 className="text-3xl font-black">Secure Checkout</h1>
          <p className="mt-2 text-sm text-[#666]">Enter contact, fulfillment, and payment details for this order.</p>
        </div>
        <div className="flex flex-wrap gap-2 text-xs font-black uppercase text-[#555]">
          <span className="inline-flex items-center gap-1 rounded border border-[#E6DFD0] bg-[#F7F5EF] px-3 py-2"><LockKeyhole size={14} /> Secure checkout</span>
          <span className="inline-flex items-center gap-1 rounded border border-[#E6DFD0] bg-[#F7F5EF] px-3 py-2"><PackageCheck size={14} /> Fulfillment review</span>
        </div>
      </div>
      <form onSubmit={submit} className="mt-6 grid gap-6 lg:grid-cols-[1fr_390px]">
        <div className="grid gap-5">
          <section className="panel p-5">
            <h2 className="text-xl font-black">Contact Information</h2>
            <div className="mt-4 grid gap-4 md:grid-cols-2">
              <label>Full name<input name="customerName" required /></label>
              <label>Email<input name="customerEmail" type="email" required /></label>
              <label>Phone<input name="customerPhone" required /></label>
            </div>
          </section>
          <section className="panel p-5">
            <h2 className="text-xl font-black">Shipping Address</h2>
            <div className="mt-4 grid gap-4">
              <label>Shipping address<textarea name="shippingAddress" required /></label>
            </div>
          </section>
          <section className="panel p-5">
            <h2 className="text-xl font-black">Billing Address</h2>
            <div className="mt-4 grid gap-4">
              <label>Billing address<textarea name="billingAddress" required /></label>
            </div>
          </section>
          <section className="panel p-5">
            <h2 className="flex items-center gap-2 text-xl font-black"><CreditCard size={20} /> Payment Method</h2>
            <div className="mt-4 grid gap-3 md:grid-cols-2">
              {[
                ["STRIPE", "Card Payment", "Secure card checkout for this order."],
                ["PAYPAL", "PayPal", "Pay with your PayPal account."],
                ["SQUARE", "Square", "Pay securely with Square card entry."]
              ].map(([value, title, text]) => {
                const disabled = (value === "SQUARE" && !squareEnabled) || (value === "PAYPAL" && !paypalEnabled);
                return (
                <label key={value} className="rounded border border-[#E5E1D8] p-3 font-normal">
                  <span className="flex items-center gap-2 font-black">
                    <input
                      className="h-4 min-h-0 w-4"
                      type="radio"
                      name="paymentMethod"
                      value={value}
                      checked={paymentMethod === value}
                      disabled={disabled}
                      onChange={() => {
                        setPaymentMethod(value as PaymentMethod);
                        setError("");
                      }}
                    />
                    {title}
                  </span>
                  <span className="mt-1 block text-xs text-[#666]">
                    {disabled && value === "SQUARE" ? "Square checkout is temporarily unavailable." : null}
                    {disabled && value === "PAYPAL" ? "PayPal checkout is temporarily unavailable." : null}
                    {!disabled ? text : null}
                  </span>
                </label>
              );
              })}
            </div>

            {paymentMethod === "SQUARE" ? (
              <div className="mt-4 rounded border border-[#E5E1D8] bg-[#F7F5EF] p-4">
                <div className="flex flex-wrap items-center gap-2">
                  <h3 className="font-black">Square Card Entry</h3>
                </div>
                <p className="mt-2 text-xs text-[#666]">Card details are tokenized by Square in your browser. Only the Square payment token is sent to our server.</p>
                {!squareEnabled ? <div className="mt-3 rounded border border-[#B91C1C] bg-red-50 p-3 text-sm text-[#B91C1C]">Square checkout is temporarily unavailable.</div> : null}
                {squareEnabled ? <div id={squareContainerId} className="mt-4 min-h-[96px] rounded border border-[#D8C98F] bg-white p-3" /> : null}
                {squareLoading ? <p className="mt-3 text-sm text-[#666]">Loading Square payment form...</p> : null}
                {squareReady ? <p className="mt-3 text-xs font-bold text-[#0F766E]">Square payment form ready.</p> : null}
                {squareError ? <div className="mt-3 rounded border border-[#B91C1C] bg-red-50 p-3 text-sm text-[#B91C1C]">{squareError}</div> : null}
              </div>
            ) : null}

            <label className="mt-3 flex-row items-center gap-2 font-normal"><input className="h-4 min-h-0 w-4" type="checkbox" name="agreementAccepted" required /> I accept the service agreement, risk disclosure, and manual fulfillment review terms.</label>
          </section>
          {error ? <div className="rounded border border-[#B91C1C] bg-red-50 p-4 text-[#B91C1C]">{error}</div> : null}
        </div>
        <aside className="h-fit rounded border border-[#D8C98F] bg-white p-5 shadow-lg lg:sticky lg:top-44">
          <h2 className="text-xl font-black">Order Summary</h2>
          <div className="mt-4 grid gap-3">
            {rows.map(({ item, product }) => <div key={item.productId} className="flex justify-between gap-3 text-sm"><span>{product!.name} x {item.quantity}</span><strong>{currency(displayPrice(product!) * item.quantity)}</strong></div>)}
          </div>
          <div className="mt-5 flex justify-between border-t border-[#E5E1D8] pt-4 text-lg"><span>Total</span><strong>{currency(subtotal)}</strong></div>
          <button className="btn btn-primary mt-5 w-full" disabled={!items.length || submitting || (paymentMethod === "SQUARE" && squareLoading)}>
            {submitting ? "Processing..." : paymentMethod === "SQUARE" ? "Pay with Square" : paymentMethod === "PAYPAL" ? "Continue to PayPal" : "Place Order"}
          </button>
          <p className="mt-3 text-xs text-[#666]">Orders are reviewed by our fulfillment team before coordination.</p>
        </aside>
      </form>
    </section>
  );
}
