"use client";

import { useEffect, useMemo, useState, type FormEvent } from "react";

type DesignPayload = {
  partnerOne: string;
  partnerTwo: string;
  weddingDate: string;
  heading: string;
  message: string;
  footer: string;
  font: "editorial" | "modern" | "romantic";
  fontSize: number;
  alignment: "left" | "center";
  palette: "ivory" | "blush" | "sage" | "stone" | "white";
};

type CurrencyCode = "ZAR" | "USD" | "EUR" | "GBP";
type PricingItem = { carat: number; prices: Record<CurrencyCode, number> };
type UploadedPdf = { id: string; fileName: string; sizeBytes: number; pageCount: number; widthMm: number; heightMm: number };

const currencyNames: Record<CurrencyCode, string> = {
  ZAR: "ZAR · R",
  USD: "USD · $",
  EUR: "EUR · €",
  GBP: "GBP · £",
};

const euroRegions = new Set(["AT", "BE", "HR", "CY", "EE", "FI", "FR", "DE", "GR", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PT", "SK", "SI", "ES"]);

const guestQuantityOptions = [
  ...Array.from({ length: 11 }, (_, index) => 100 + index * 10),
  ...Array.from({ length: 4 }, (_, index) => 225 + index * 25),
  ...Array.from({ length: 14 }, (_, index) => 350 + index * 50),
];

function formatMoney(amount: number, currency: CurrencyCode) {
  return new Intl.NumberFormat(currency === "ZAR" ? "en-ZA" : currency === "EUR" ? "en-IE" : currency === "GBP" ? "en-GB" : "en-US", {
    style: "currency",
    currency,
    maximumFractionDigits: 0,
  }).format(amount);
}

function formatWeddingDate(value: string) {
  if (!value) return "";
  return new Intl.DateTimeFormat("en-ZA", { day: "2-digit", month: "long", year: "numeric" }).format(new Date(`${value}T12:00:00`));
}

function diamondPixelSize(carat: number) {
  return Math.max(10, Math.round(28 * Math.cbrt(carat / 0.5)));
}

function detectCurrency(): CurrencyCode {
  const locale = navigator.languages?.[0] || navigator.language || "";
  const region = locale.match(/[-_]([a-z]{2})\b/i)?.[1]?.toUpperCase();
  const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || "";
  if (region === "ZA" || timeZone === "Africa/Johannesburg") return "ZAR";
  if (region === "GB" || timeZone === "Europe/London") return "GBP";
  if ((region && euroRegions.has(region)) || (timeZone.startsWith("Europe/") && timeZone !== "Europe/London")) return "EUR";
  return "USD";
}

function savedCurrency(): CurrencyCode | null {
  const value = document.cookie.split(";").map((part) => part.trim()).find((part) => part.startsWith("dv_currency="))?.split("=")[1];
  return value && ["ZAR", "USD", "EUR", "GBP"].includes(value) ? value as CurrencyCode : null;
}

export default function OrderPage() {
  const [pricing, setPricing] = useState<PricingItem[]>([]);
  const [currency, setCurrency] = useState<CurrencyCode>("ZAR");
  const [currencyNote, setCurrencyNote] = useState("Detected currency");
  const [carat, setCarat] = useState(0.02);
  const [guestCount, setGuestCount] = useState(100);
  const [design, setDesign] = useState<DesignPayload | null>(null);
  const [uploadedDesign, setUploadedDesign] = useState<UploadedPdf | null>(null);
  const [customerName, setCustomerName] = useState("");
  const [weddingDate, setWeddingDate] = useState("");
  const [email, setEmail] = useState("");
  const [phone, setPhone] = useState("");
  const [deliveryAddress, setDeliveryAddress] = useState("");
  const [deliveryRecipient, setDeliveryRecipient] = useState("");
  const [deliveryConfirmed, setDeliveryConfirmed] = useState(false);
  const [notes, setNotes] = useState("");
  const [submitStatus, setSubmitStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
  const [message, setMessage] = useState("");
  const [reference, setReference] = useState("");

  useEffect(() => {
    const rememberedCurrency = savedCurrency();
    setCurrency(rememberedCurrency || detectCurrency());
    setCurrencyNote(rememberedCurrency ? "Saved currency" : "Detected currency");
    const draft = sessionStorage.getItem("diamondVialDraft");
    if (draft) {
      try { setDesign(JSON.parse(draft) as DesignPayload); } catch { /* keep a design-free order */ }
    }
    const uploadedDraft = sessionStorage.getItem("diamondVialUploadedDesign");
    if (uploadedDraft) {
      try { setUploadedDesign(JSON.parse(uploadedDraft) as UploadedPdf); } catch { sessionStorage.removeItem("diamondVialUploadedDesign"); }
    }

    fetch("/api/pricing")
      .then(async (response) => {
        const result = await response.json() as { pricing?: PricingItem[]; error?: string };
        if (!response.ok || !result.pricing) throw new Error(result.error || "Unable to load prices.");
        setPricing(result.pricing);
        if (result.pricing[0]) setCarat(result.pricing[0].carat);
      })
      .catch((error: unknown) => setMessage(error instanceof Error ? error.message : "Unable to load prices."));
  }, []);

  const selectedPrice = useMemo(
    () => pricing.find((item) => item.carat === carat)?.prices[currency] || 0,
    [carat, currency, pricing],
  );
  const total = selectedPrice * guestCount;

  async function placeOrder(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSubmitStatus("submitting");
    setMessage("");

    try {
      const response = await fetch("/api/orders", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ customerName, weddingDate, email, phone, deliveryAddress, deliveryRecipient, notes, guestCount, carat, currency, design, uploadId: uploadedDesign?.id || null }),
      });
      const result = await response.json() as { order?: { reference: string }; error?: string };
      if (!response.ok || !result.order) throw new Error(result.error || "Unable to place the order.");
      setReference(result.order.reference);
      setSubmitStatus("success");
      sessionStorage.removeItem("diamondVialDraft");
      sessionStorage.removeItem("diamondVialUploadedDesign");
      window.scrollTo({ top: 0, behavior: "smooth" });
    } catch (error) {
      setSubmitStatus("error");
      setMessage(error instanceof Error ? error.message : "Unable to place the order.");
    }
  }

  function changeCurrency(value: CurrencyCode) {
    setCurrency(value);
    setCurrencyNote("Saved currency");
    document.cookie = `dv_currency=${value}; Path=/; Max-Age=31536000; SameSite=Lax`;
  }

  if (submitStatus === "success") {
    return (
      <main className="order-page order-success-page">
        <a className="brand" href="/"><img className="brand-mark" src="/logo.svg" width="24" height="38" alt="" aria-hidden="true" /><span>Gem Vial</span></a>
        <section className="order-success-card">
          <div className="success-diamond"><img src="/diamond-single-28.png" width="28" height="28" alt="" style={{ width: diamondPixelSize(carat), height: diamondPixelSize(carat) }} /></div>
          <p className="eyebrow"><span /> Order request received</p>
          <h1>Thank you.<br /><em>Your forever begins here.</em></h1>
          <p>Your design and order details have been saved. We’ll contact you to confirm the final artwork, diamond availability and payment.</p>
          <dl>
            <div><dt>Reference</dt><dd>{reference}</dd></div>
            <div><dt>Wedding date</dt><dd>{formatWeddingDate(weddingDate)}</dd></div>
            <div><dt>Delivery recipient</dt><dd>{deliveryRecipient}</dd></div>
            <div><dt>Diamond</dt><dd>{carat.toFixed(2)} ct</dd></div>
            <div><dt>Guests</dt><dd>{guestCount}</dd></div>
            <div><dt>Estimated total</dt><dd>{formatMoney(total, currency)}</dd></div>
          </dl>
          <a className="button button-dark" href="/">Return home</a>
        </section>
      </main>
    );
  }

  return (
    <main className="order-page">
      <header className="designer-header order-header">
        <a className="brand" href="/"><img className="brand-mark" src="/logo.svg" width="24" height="38" alt="" aria-hidden="true" /><span>Gem Vial</span></a>
        <div className="designer-progress order-progress">
          <span>01 Personalise</span><i /><span className="active">02 Your order</span><i /><span>03 Confirm</span>
        </div>
        <div className="order-header-actions">
          <label className="currency-switcher"><span>{currencyNote}</span><select value={currency} onChange={(event) => changeCurrency(event.target.value as CurrencyCode)}>{Object.entries(currencyNames).map(([code, label]) => <option key={code} value={code}>{label}</option>)}</select></label>
          <a className="designer-back" href="/personalise">← Edit card</a>
        </div>
      </header>

      <section className="order-intro">
        <p className="eyebrow"><span /> The diamond</p>
        <h1>Choose their piece<br />of <em>your forever.</em></h1>
        <p>Select your diamond size and guest count. Your estimated total updates instantly in {currency}.</p>
      </section>

      <form className="order-layout" onSubmit={placeOrder}>
        <div className="order-main">
          <section className="order-section diamond-choice-section">
            <div className="order-section-heading"><span>01</span><div><h2>Diamond size</h2><p>One real lab-grown diamond per guest</p></div></div>
            <div className="diamond-size-grid">
              {pricing.map((item) => (
                <button type="button" key={item.carat} className={carat === item.carat ? "diamond-size active" : "diamond-size"} onClick={() => setCarat(item.carat)} aria-pressed={carat === item.carat}>
                  <span className="diamond-size-visual"><img src="/diamond-single-28.png" width="28" height="28" alt="" style={{ width: diamondPixelSize(item.carat), height: diamondPixelSize(item.carat) }} /></span>
                  <strong>{item.carat.toFixed(2)} <small>ct</small></strong>
                  <span>{formatMoney(item.prices[currency], currency)} / guest</span>
                </button>
              ))}
            </div>
            <p className="price-disclaimer">Prices shown are editable catalogue prices and are confirmed with availability before payment.</p>
          </section>

          <section className="order-section">
            <div className="order-section-heading"><span>02</span><div><h2>Guest quantity</h2><p>How many individual favours do you need?</p></div></div>
            <div className="quantity-control">
              <button type="button" onClick={() => setGuestCount((count) => Math.max(1, count - 10))} aria-label="Remove ten guests">−</button>
              <label><input type="number" min="1" max="2000" value={guestCount} onChange={(event) => setGuestCount(Math.min(2000, Math.max(1, Number(event.target.value) || 1)))} /><span>guests</span></label>
              <button type="button" onClick={() => setGuestCount((count) => Math.min(2000, count + 10))} aria-label="Add ten guests">+</button>
            </div>
            <label className="guest-quantity-select">
              <span>Select a guest quantity</span>
              <select value={guestQuantityOptions.includes(guestCount) ? guestCount : ""} onChange={(event) => setGuestCount(Number(event.target.value))}>
                <option value="" disabled>Choose from 100 to 1,000 guests</option>
                {guestQuantityOptions.map((amount) => <option key={amount} value={amount}>{amount.toLocaleString("en-US")} guests</option>)}
              </select>
            </label>
            <div className="quick-quantities">
              {[50, 100, 150, 200, 300].map((amount) => <button type="button" key={amount} className={guestCount === amount ? "active" : ""} onClick={() => setGuestCount(amount)}>{amount}</button>)}
            </div>
          </section>

          <section className="order-section">
            <div className="order-section-heading"><span>03</span><div><h2>Your details</h2><p>So we can confirm your order</p></div></div>
            <div className="order-form-grid">
              <label><span>Full name</span><input value={customerName} onChange={(event) => setCustomerName(event.target.value)} required maxLength={100} /></label>
              <label><span>Email address</span><input type="email" value={email} onChange={(event) => setEmail(event.target.value)} required maxLength={254} /></label>
              <label><span>Contact number</span><input type="tel" value={phone} onChange={(event) => setPhone(event.target.value)} required maxLength={40} /></label>
              <label><span>Wedding date</span><input type="date" value={weddingDate} onChange={(event) => setWeddingDate(event.target.value)} required /></label>
              <label className="order-wide"><span>Delivery address</span><textarea value={deliveryAddress} onChange={(event) => setDeliveryAddress(event.target.value)} rows={3} required minLength={10} maxLength={500} autoComplete="street-address" placeholder="Street address, suburb, city, province and postal code" /></label>
              <label className="order-wide"><span>Person authorised to sign for delivery</span><input value={deliveryRecipient} onChange={(event) => setDeliveryRecipient(event.target.value)} required minLength={2} maxLength={100} autoComplete="name" placeholder="Full name exactly as shown on their ID or passport" /></label>
              <div className="delivery-notice" role="note">
                <strong>Secure courier handover</strong>
                <p>The authorised recipient named above must be available in person to receive and sign for the order. The courier will require their original valid ID document or passport to confirm their identity.</p>
                <label className="delivery-confirmation">
                  <input type="checkbox" checked={deliveryConfirmed} onChange={(event) => setDeliveryConfirmed(event.target.checked)} required />
                  <span>I confirm the named recipient will be available with their ID document or passport for delivery.</span>
                </label>
              </div>
              <label className="order-notes"><span>Notes or special requests</span><textarea value={notes} onChange={(event) => setNotes(event.target.value)} rows={4} maxLength={600} placeholder="Colour notes, packaging requests, timing considerations…" /></label>
            </div>
          </section>
        </div>

        <aside className="order-summary">
          <div className="summary-product">
            <div className="summary-stone"><img src="/diamond-single-28.png" width="28" height="28" alt="" style={{ width: diamondPixelSize(carat), height: diamondPixelSize(carat) }} /></div>
            <div><span>Selected diamond</span><strong>{carat.toFixed(2)} ct</strong><small>Round brilliant · Lab-grown</small></div>
          </div>
          {uploadedDesign ? (
            <div className="summary-design uploaded">
              <span>Your supplied PDF</span>
              <strong>{uploadedDesign.fileName}</strong>
              <small>{uploadedDesign.pageCount} {uploadedDesign.pageCount === 1 ? "page" : "pages"} · {uploadedDesign.widthMm} × {uploadedDesign.heightMm} mm</small>
              <a href="/personalise">Replace artwork</a>
            </div>
          ) : design ? (
            <div className="summary-design">
              <span>Your personalised card</span>
              <strong>{design.partnerOne} & {design.partnerTwo}</strong>
              <small>{design.heading}</small>
              <a href="/personalise">Edit design</a>
            </div>
          ) : (
            <div className="summary-design empty"><span>No card attached</span><a href="/personalise">Create your card</a></div>
          )}
          <div className="summary-totals">
            <div><span>{formatMoney(selectedPrice, currency)} × {guestCount} guests</span><strong>{formatMoney(total, currency)}</strong></div>
            <div className="summary-total"><span>Estimated total · {currency}</span><strong>{formatMoney(total, currency)}</strong></div>
          </div>
          <button className="button button-dark order-submit" type="submit" disabled={!pricing.length || submitStatus === "submitting"}>
            {submitStatus === "submitting" ? "Saving order…" : "Place order request"}<span>→</span>
          </button>
          {message && <p className={`order-message ${submitStatus}`}>{message}</p>}
          <p className="summary-fineprint">No payment is taken now. Final pricing, artwork and availability are confirmed personally before production.</p>
        </aside>
      </form>
    </main>
  );
}
