"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import Link from "next/link";
import { formatPrice } from "@/lib/format";
import { MERCHANT } from "@/lib/merchant";
import MerchProductCard from "@/components/merch-product-card";
import PaystackMark from "@/components/paystack-mark";
import { MpesaMark } from "@/components/payment-marks";
import type { PublicProduct } from "@/lib/merch-public";

export type { PublicProduct } from "@/lib/merch-public";

interface PublicShop {
  id: string;
  pickupEnabled: boolean;
  deliveryEnabled: boolean;
  deliveryFeeCents: number;
  pickupInstructions: string | null;
}

// The organizer's upcoming events, shown on the same storefront (like
// HustleSasa's All / Events / Products tabs).
export interface StoreEvent {
  id: string;
  title: string;
  href: string;
  when: string;
  where: string | null;
  coverImageUrl: string | null;
  fromCents: number | null;
}

type Method = "mpesa" | "card";
type Fulfillment = "pickup" | "delivery";
type Tab = "all" | "events" | "merch";

export default function ShopClient({
  shop,
  products,
  events = [],
}: {
  shop: PublicShop;
  products: PublicProduct[];
  events?: StoreEvent[];
}) {
  // variantId -> quantity
  const [cart, setCart] = useState<Record<string, number>>({});
  // productId -> chosen variantId
  const [chosen, setChosen] = useState<Record<string, string>>(() =>
    Object.fromEntries(products.map((p) => [p.id, (p.variants.find((v) => v.available > 0) ?? p.variants[0])?.id ?? ""]))
  );
  const [tab, setTab] = useState<Tab>("all");
  const [fulfillment, setFulfillment] = useState<Fulfillment>(shop.pickupEnabled ? "pickup" : "delivery");
  const [method, setMethod] = useState<Method>("mpesa");
  const [buyer, setBuyer] = useState({ name: "", email: "", phone: "" });
  const [address, setAddress] = useState({ address: "", city: "" });
  const [couponCode, setCouponCode] = useState("");
  const [coupon, setCoupon] = useState<{ code: string; discountCents: number; subtotal: number } | null>(null);
  const [couponError, setCouponError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [pushed, setPushed] = useState(false);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const cartRef = useRef<HTMLElement | null>(null);

  useEffect(() => () => void (pollRef.current && clearInterval(pollRef.current)), []);

  const lines = useMemo(() => {
    const out: { product: PublicProduct; variant: PublicProduct["variants"][number]; quantity: number }[] = [];
    for (const p of products) {
      for (const v of p.variants) {
        const q = cart[v.id];
        if (q) out.push({ product: p, variant: v, quantity: q });
      }
    }
    return out;
  }, [cart, products]);

  const subtotal = lines.reduce((s, l) => s + l.variant.priceCents * l.quantity, 0);
  const deliveryFee = fulfillment === "delivery" ? shop.deliveryFeeCents : 0;
  // A coupon priced against a different subtotal is stale -- re-apply.
  const activeCoupon = coupon && coupon.subtotal === subtotal ? coupon : null;
  const discount = activeCoupon?.discountCents ?? 0;
  const total = subtotal - discount + deliveryFee;
  const itemCount = lines.reduce((s, l) => s + l.quantity, 0);

  function add(product: PublicProduct) {
    const vid = chosen[product.id];
    const v = product.variants.find((x) => x.id === vid);
    if (!v || v.available === 0) return;
    setCart((c) => ({ ...c, [vid]: Math.min((c[vid] ?? 0) + 1, v.available) }));
    setError(null);
  }
  function setQty(variantId: string, q: number, max: number) {
    setCart((c) => {
      const next = { ...c };
      if (q <= 0) delete next[variantId];
      else next[variantId] = Math.min(q, max);
      return next;
    });
  }

  async function applyCoupon() {
    if (!couponCode.trim()) return;
    setCouponError(null);
    const res = await fetch("/api/merch/coupon", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ shopId: shop.id, code: couponCode.trim(), buyerEmail: buyer.email || undefined, subtotalCents: subtotal }),
    }).catch(() => null);
    const data = res ? await res.json().catch(() => ({})) : {};
    if (!res?.ok || !data.valid) {
      setCoupon(null);
      setCouponError(data.error || "Code not accepted");
      return;
    }
    setCoupon({ code: couponCode.trim().toUpperCase(), discountCents: data.discountCents, subtotal });
  }

  async function checkout() {
    setLoading(true);
    setError(null);
    const res = await fetch("/api/merch/checkout", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        shopId: shop.id,
        items: lines.map((l) => ({ variantId: l.variant.id, quantity: l.quantity })),
        buyer,
        fulfillment,
        address: fulfillment === "delivery" ? address : null,
        method,
        couponCode: activeCoupon?.code,
      }),
    });
    const data = await res.json().catch(() => ({}));
    if (!res.ok) {
      setError(data.error || "Something went wrong");
      setLoading(false);
      return;
    }

    if (method === "card") {
      window.location.href = data.url;
      return;
    }

    setPushed(true);
    pollRef.current = setInterval(async () => {
      const s = await fetch(`/api/merch/status?orderId=${data.orderId}`).then((r) => r.json()).catch(() => null);
      if (s?.status === "paid") {
        clearInterval(pollRef.current!);
        window.location.href = `/shop/orders/${data.orderId}`;
      } else if (s?.status === "cancelled") {
        clearInterval(pollRef.current!);
        setPushed(false);
        setLoading(false);
        setError("Payment was not completed. You can try again.");
      }
    }, 3000);
  }

  const needsAddress = fulfillment === "delivery";
  const ready =
    itemCount > 0 &&
    buyer.name.trim() &&
    buyer.email.trim() &&
    buyer.phone.trim() &&
    (!needsAddress || (address.address.trim() && address.city.trim()));

  const showEvents = (tab === "all" || tab === "events") && events.length > 0;
  const showMerch = tab === "all" || tab === "merch";

  return (
    <div className="space-y-6">
      {/* Storefront tabs */}
      <div className="flex gap-2">
        {(
          [
            ["all", `All (${events.length + products.length})`],
            ["events", `Events (${events.length})`],
            ["merch", `Merch (${products.length})`],
          ] as [Tab, string][]
        ).map(([t, label]) => (
          <button
            key={t}
            type="button"
            onClick={() => setTab(t)}
            className={`rounded-full border px-4 py-1.5 text-sm font-semibold ${
              tab === t ? "border-brand-green bg-brand-green text-white" : "border-line text-muted hover:text-ink"
            }`}
          >
            {label}
          </button>
        ))}
      </div>

      {showEvents && (
        <section>
          {tab === "all" && <h2 className="mb-3 text-xl font-black">Events</h2>}
          <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
            {events.map((e) => (
              <Link
                key={e.id}
                href={e.href}
                className="group overflow-hidden rounded-2xl border border-line bg-panel transition-colors hover:border-brand-green"
              >
                <div className="aspect-[16/9] bg-bg">
                  {e.coverImageUrl && (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={e.coverImageUrl} alt="" className="h-full w-full object-cover" />
                  )}
                </div>
                <div className="p-4">
                  <p className="font-bold group-hover:text-brand-green-h">{e.title}</p>
                  <p className="mt-1 text-sm text-muted">{e.when}</p>
                  {e.where && <p className="text-sm text-muted">{e.where}</p>}
                  <p className="mt-2 text-sm font-semibold text-brand-green-h">
                    {e.fromCents === null ? "Tickets" : e.fromCents === 0 ? "Free" : `From ${formatPrice(e.fromCents, "kes")}`} · Buy
                    ticket →
                  </p>
                </div>
              </Link>
            ))}
          </div>
        </section>
      )}

      {showMerch && (
        <div className="grid gap-8 lg:grid-cols-[1fr_22rem]">
          <section>
            {tab === "all" && <h2 className="mb-3 text-xl font-black">Merch</h2>}
            {products.length === 0 ? (
              <p className="text-muted">Nothing on the shelf yet — check back soon.</p>
            ) : (
              <div className="grid gap-4 sm:grid-cols-2">
                {products.map((p) => (
                  <MerchProductCard
                    key={p.id}
                    product={p}
                    chosenVariantId={chosen[p.id]}
                    onChoose={(vid) => setChosen((c) => ({ ...c, [p.id]: vid }))}
                    onAdd={() => add(p)}
                    inCart={p.variants.reduce((s, v) => s + (cart[v.id] ?? 0), 0)}
                  />
                ))}
              </div>
            )}
          </section>

          {products.length > 0 && (
            <aside
              ref={cartRef}
              id="cart"
              className="h-fit scroll-mt-20 space-y-4 rounded-2xl border border-line bg-panel p-4 lg:sticky lg:top-6"
            >
              <h2 className="text-lg font-bold">Your cart{itemCount > 0 ? ` (${itemCount})` : ""}</h2>

              {lines.length === 0 ? (
                <p className="text-sm text-muted">Your cart is empty.</p>
              ) : (
                <>
                  <ul className="space-y-3">
                    {lines.map((l) => (
                      <li key={l.variant.id} className="flex items-start justify-between gap-2 text-sm">
                        <div>
                          <p className="font-medium">{l.product.name}</p>
                          {l.product.variants.length > 1 && <p className="text-xs text-muted">{l.variant.label}</p>}
                          <div className="mt-1 flex items-center gap-2">
                            <button
                              onClick={() => setQty(l.variant.id, l.quantity - 1, l.variant.available)}
                              className="h-6 w-6 rounded border border-line"
                              aria-label="Decrease quantity"
                            >
                              −
                            </button>
                            <span className="w-5 text-center tabular-nums">{l.quantity}</span>
                            <button
                              onClick={() => setQty(l.variant.id, l.quantity + 1, l.variant.available)}
                              disabled={l.quantity >= l.variant.available}
                              className="h-6 w-6 rounded border border-line disabled:opacity-40"
                              aria-label="Increase quantity"
                            >
                              +
                            </button>
                          </div>
                        </div>
                        <span className="tabular-nums">{formatPrice(l.variant.priceCents * l.quantity, "kes")}</span>
                      </li>
                    ))}
                  </ul>

                  <div className="space-y-3 border-t border-line pt-4">
                    {shop.pickupEnabled && shop.deliveryEnabled && (
                      <div className="flex gap-2">
                        {(["pickup", "delivery"] as const).map((f) => (
                          <button
                            key={f}
                            onClick={() => setFulfillment(f)}
                            className={`flex-1 rounded-md border py-2 text-sm font-medium ${
                              fulfillment === f ? "border-brand-green bg-brand-green/10 text-brand-green-h" : "border-line text-muted"
                            }`}
                          >
                            {f === "pickup" ? "Pickup" : "Delivery"}
                          </button>
                        ))}
                      </div>
                    )}
                    {fulfillment === "pickup" && shop.pickupInstructions && (
                      <p className="text-xs text-muted">{shop.pickupInstructions}</p>
                    )}

                    <Input label="Your name" value={buyer.name} onChange={(v) => setBuyer({ ...buyer, name: v })} />
                    <Input label="Email" type="email" value={buyer.email} onChange={(v) => setBuyer({ ...buyer, email: v })} />
                    <Input
                      label="Phone number"
                      type="tel"
                      placeholder="07XX XXX XXX"
                      value={buyer.phone}
                      onChange={(v) => setBuyer({ ...buyer, phone: v })}
                    />

                    {needsAddress && (
                      <>
                        <Input
                          label="Delivery address"
                          value={address.address}
                          onChange={(v) => setAddress({ ...address, address: v })}
                        />
                        <Input label="Town / city" value={address.city} onChange={(v) => setAddress({ ...address, city: v })} />
                      </>
                    )}

                    <div>
                      <label className="mb-1 block text-sm font-medium">Coupon code</label>
                      {activeCoupon ? (
                        <div className="flex items-center justify-between rounded-md border border-green-500 bg-green-500/10 px-3 py-2 text-sm text-green-400">
                          <span>
                            “{activeCoupon.code}” — {formatPrice(activeCoupon.discountCents, "kes")} off
                          </span>
                          <button
                            type="button"
                            onClick={() => {
                              setCoupon(null);
                              setCouponCode("");
                            }}
                            className="text-xs text-muted"
                          >
                            Remove
                          </button>
                        </div>
                      ) : (
                        <div className="flex gap-2">
                          <input
                            value={couponCode}
                            onChange={(e) => setCouponCode(e.target.value)}
                            placeholder="Enter code"
                            className="input flex-1"
                          />
                          <button
                            type="button"
                            onClick={applyCoupon}
                            disabled={!couponCode.trim()}
                            className="rounded-md border border-line px-3 text-sm disabled:opacity-50"
                          >
                            Apply
                          </button>
                        </div>
                      )}
                      {couponError && <p className="mt-1 text-xs text-red-500">{couponError}</p>}
                    </div>

                    <div className="flex gap-2">
                      {(["mpesa", "card"] as const).map((m) => (
                        <button
                          key={m}
                          onClick={() => setMethod(m)}
                          className={`flex flex-1 items-center justify-center gap-1.5 rounded-md border py-2 text-sm font-medium ${
                            method === m
                              ? m === "card"
                                ? "border-[#00C3F7] bg-[#00C3F7]/10 text-[#00C3F7]"
                                : "border-[#39B54A] bg-[#39B54A]/10 text-[#39B54A]"
                              : "border-line text-muted"
                          }`}
                        >
                          {m === "card" ? <PaystackMark className="h-3.5 w-3.5" /> : <MpesaMark className="h-4 w-auto" />}
                          {m === "mpesa" ? "M-Pesa" : "Paystack"}
                        </button>
                      ))}
                    </div>
                    {method === "mpesa" && (
                      <p className="text-xs text-muted">
                        You&apos;ll get an M-Pesa prompt on your phone (PayBill {MERCHANT.mpesa.paybill}).
                      </p>
                    )}
                    {method === "card" && (
                      <p className="text-xs text-muted">
                        Pay with Paystack: Visa or Mastercard, charged in KES on Paystack&apos;s secure page.
                      </p>
                    )}

                    <dl className="space-y-1 text-sm">
                      <div className="flex justify-between">
                        <dt className="text-muted">Subtotal</dt>
                        <dd className="tabular-nums">{formatPrice(subtotal, "kes")}</dd>
                      </div>
                      {discount > 0 && (
                        <div className="flex justify-between">
                          <dt className="text-muted">Discount</dt>
                          <dd className="tabular-nums">−{formatPrice(discount, "kes")}</dd>
                        </div>
                      )}
                      {deliveryFee > 0 && (
                        <div className="flex justify-between">
                          <dt className="text-muted">Delivery</dt>
                          <dd className="tabular-nums">{formatPrice(deliveryFee, "kes")}</dd>
                        </div>
                      )}
                      <div className="flex justify-between text-base font-bold">
                        <dt>Total</dt>
                        <dd className="tabular-nums">{formatPrice(total, "kes")}</dd>
                      </div>
                    </dl>

                    <button
                      onClick={checkout}
                      disabled={loading || pushed || !ready}
                      className={`inline-flex w-full items-center justify-center gap-2 rounded-full px-6 py-2.5 text-sm font-semibold text-white hover:brightness-110 disabled:opacity-50 ${
                        method === "card" ? "bg-[#011B33] ring-1 ring-[#00C3F7]/60" : "bg-[#39B54A]"
                      }`}
                    >
                      {!loading && !pushed && (method === "card" ? <PaystackMark /> : <MpesaMark className="h-5 w-auto" />)}
                      {pushed ? "Waiting for confirmation…" : loading ? "Redirecting…" : method === "mpesa" ? "Pay with M-Pesa" : "Pay with Paystack"}
                    </button>
                    {pushed && (
                      <p className="text-sm text-green-700">
                        Check your phone — enter your M-Pesa PIN to complete payment. This page updates automatically.
                      </p>
                    )}
                    {error && <p className="text-sm text-red-600">{error}</p>}
                    <p className="text-xs text-muted">All merchandise sales are final — no refunds.</p>
                  </div>
                </>
              )}
            </aside>
          )}
        </div>
      )}

      {/* Phones: the cart sits below a long product list, so float a button to it. */}
      {itemCount > 0 && showMerch && (
        <button
          type="button"
          onClick={() => cartRef.current?.scrollIntoView({ behavior: "smooth", block: "start" })}
          className="fixed bottom-5 left-1/2 z-40 -translate-x-1/2 rounded-full bg-brand-orange px-6 py-3 text-sm font-bold text-white shadow-lg lg:hidden"
        >
          View cart ({itemCount}) · {formatPrice(total, "kes")}
        </button>
      )}
    </div>
  );
}

function Input({
  label,
  value,
  onChange,
  type = "text",
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  type?: string;
  placeholder?: string;
}) {
  return (
    <div>
      <label className="mb-1 block text-sm font-medium">{label}</label>
      <input type={type} value={value} placeholder={placeholder} onChange={(e) => onChange(e.target.value)} className="input" />
    </div>
  );
}
