"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import type { CartItem } from "../../lib/cart";
import { useProducts } from "../../lib/products";
import { computeCartTotals, effectivePrice, effectiveTaxRate } from "../../lib/cartTotals";
import { computeTaxBreakdown } from "@einfach-produktiv/invoicing";
import { computeExemptTotals } from "../../lib/vatExemption";
import { formatPrice, formatDate } from "../../lib/format";
import { Reveal } from "../../components/Reveal";
import { CheckoutSteps } from "../../components/CheckoutSteps";
import { VatBreakdown } from "../../components/VatBreakdown";
import { ORDER_KEY, type OrderSnapshot } from "../../lib/order";

// Rejects (rather than silently patching with fallback values) anything
// that doesn't match the current OrderSnapshot shape — e.g. a snapshot
// left over from before shippingCost/paymentMethodTitle were added to it.
// Fabricating "Kostenlos"/"—" for missing fields would render a receipt
// that looks real but states things about an order that were never true;
// treating it as no-order-found and clearing it is the honest fallback.
function parseOrderSnapshot(raw: string): OrderSnapshot | null {
  try {
    const data = JSON.parse(raw);
    if (
      !data ||
      !Array.isArray(data.items) ||
      data.items.length === 0 ||
      typeof data.orderNumber !== "string" ||
      typeof data.orderDateIso !== "string" ||
      typeof data.shippingCost !== "number" ||
      typeof data.paymentMethodTitle !== "string" ||
      (data.discountCode !== null && typeof data.discountCode !== "string") ||
      typeof data.discountAmount !== "number" ||
      typeof data.vatExempt !== "boolean" ||
      typeof data.kleinunternehmer !== "boolean"
    ) {
      return null;
    }
    return data as OrderSnapshot;
  } catch {
    return null;
  }
}

export function BestellbestaetigungContent({ defaultTaxRate }: { defaultTaxRate: number }) {
  const products = useProducts();
  const [order, setOrder] = useState<OrderSnapshot | null>(null);
  const [checked, setChecked] = useState(false);

  // The snapshot was already written (and the cart already cleared) by
  // /checkout's "Jetzt kaufen" click, before it ever navigated here — see
  // CheckoutContent.tsx's handlePurchase(). This is a pure read of that
  // browser-only value, deferred to an effect (not a lazy useState
  // initializer) purely to avoid an SSR/hydration mismatch: the server
  // has no sessionStorage, so it must render the same "nothing yet" state
  // the client shows before this effect runs.
  useEffect(() => {
    try {
      const raw = window.sessionStorage.getItem(ORDER_KEY);
      const parsed = raw ? parseOrderSnapshot(raw) : null;
      if (parsed) {
        // eslint-disable-next-line react-hooks/set-state-in-effect -- reading a browser-only store on mount to avoid an SSR/hydration mismatch, see comment above
        setOrder(parsed);
      } else if (raw) {
        // Present but invalid/outdated — drop it so it doesn't keep
        // failing validation on every future visit either.
        window.sessionStorage.removeItem(ORDER_KEY);
      }
    } catch {
      // ignore — falls through to the "no order" state below
    }
    setChecked(true);
  }, []);

  if (!checked) return null;

  if (!order) {
    return (
      <Reveal className="flex flex-col gap-6 items-center text-center pt-20 pb-16 px-[var(--layout-padding-x)] w-full">
        <p
          className="font-semibold text-h-feature text-text-primary"
          style={{ fontFamily: "var(--font-lora)" }}
        >
          Keine Bestellung gefunden
        </p>
        <p className="text-body text-text-muted max-w-[28rem]">
          Hier gibt es gerade nichts zu bestätigen — vielleicht ist die Sitzung abgelaufen.
        </p>
        <Link
          href="/shop"
          className="flex items-center gap-2 px-7 py-4 rounded-sm bg-brand text-h4 font-bold text-text-primary hover:bg-brand-hover active:scale-[0.97] transition-all"
        >
          Zum Shop
        </Link>
      </Reveal>
    );
  }

  const productsLoading = products.length === 0;
  const items = order.items
    .map((entry) => ({ entry, product: products.find((p) => p.id === entry.id) }))
    .filter((row): row is { entry: CartItem; product: NonNullable<(typeof row)["product"]> } => Boolean(row.product));

  // Displays the *persisted* discount/shippingCost from the snapshot, not
  // a fresh re-derivation — the purchase already happened, this page is a
  // receipt, not a live cart, so it doesn't re-validate the code at all.
  // order.shippingCost is already the actual (possibly de-grossed, if
  // vatExempt) figure charged at checkout — see api/checkout/route.ts's
  // own response. `subtotal`/`taxBreakdown` below still need their own
  // exempt branch, though: computeCartTotals/computeTaxBreakdown build
  // `subtotal` from each item's *current catalog* gross price via
  // effectivePrice(), which for an exempt order was never what was
  // actually charged (the catalog price includes VAT; the exempt order
  // paid the de-grossed net price instead).
  const { subtotal: catalogSubtotal, totalSavings, total: catalogTotal } = computeCartTotals(items, order.shippingCost, {
    type: "fixed",
    value: order.discountAmount,
  });
  const exemptTotals = order.vatExempt
    ? computeExemptTotals(
        items.map(({ entry, product }) => ({
          quantity: entry.qty,
          grossUnitPrice: effectivePrice(entry, product),
          taxRatePercent: effectiveTaxRate(product, defaultTaxRate),
        })),
        order.shippingCost,
        defaultTaxRate,
        order.discountAmount,
      )
    : null;
  const subtotal = exemptTotals?.subtotal ?? catalogSubtotal;
  const total = exemptTotals?.total ?? catalogTotal;
  const taxBreakdown = computeTaxBreakdown(
    items.map(({ entry, product }) => ({
      quantity: entry.qty,
      unitPrice: effectivePrice(entry, product),
      taxRatePercent: effectiveTaxRate(product, defaultTaxRate),
    })),
    catalogSubtotal,
    order.discountAmount,
    order.shippingCost,
  );

  return (
    <>
      {/* items-start + same pt-8/px as /checkout's own header block — not
          centered, so the bar sits at the exact same left edge/position a
          shopper just saw on the previous step. */}
      <Reveal className="flex flex-col items-start pt-8 pb-2 px-[var(--layout-padding-x)] w-full">
        <CheckoutSteps current={5} />
      </Reveal>

      {/* Hero — headline, short recap. No separate big checkmark badge —
          all four steps in the bar right above already render as
          checkmarks (current={5}), a second one here would just repeat
          it; pt-24 (up from the badge-era pt-12) keeps real breathing
          room between the bar and the headline now that the badge isn't
          filling that space itself. */}
      <Reveal className="flex flex-col gap-4 items-center text-center pt-24 pb-10 px-[var(--layout-padding-x)] w-full">
        <p
          className="font-semibold text-display text-text-primary"
          style={{ fontFamily: "var(--font-playfair)" }}
        >
          Vielen Dank!
        </p>
        <p
          className="font-semibold text-h3 text-text-primary"
          style={{ fontFamily: "var(--font-lora)" }}
        >
          Deine Bestellung ist bei uns eingegangen.
        </p>
        <div className="h-[0.125rem] w-8 bg-brand" />

        {!productsLoading && (
          <div className="flex flex-col gap-1 max-w-[26rem]">
            <p className="text-body text-text-muted">
              Du erhältst in Kürze eine Bestellbestätigung per E-Mail mit allen Details.
            </p>
          </div>
        )}
      </Reveal>

      {!productsLoading && (
        // Outer card+sidebar split stays lg: (fixed 18rem delivery-status
        // sidebar, L297 below — same fixed-width-block category as Tier C
        // exceptions elsewhere), while the inner order-meta/items row
        // already switches at sm: — intentional, not an inconsistent
        // leftover: the inner row has no fixed-width sidebar to fight for
        // room against, just two flexible columns.
        //
        // max-w-[36rem] between sm and lg (same fix/value as
        // NewsletterModal.tsx's own dialog cap) — max-w-[56rem] (896px)
        // doesn't actually constrain anything below that viewport width,
        // so at real Tablet widths (640-1023px) this card stretched to
        // fill the full page width instead of reading as a compact,
        // centered card. Widens to the real 56rem cap only once lg:'s
        // sidebar split kicks in and needs the room.
        <Reveal
          delay={0.05}
          className="w-full max-w-[36rem] lg:max-w-[56rem] mx-auto bg-bg-base border border-border rounded-md overflow-hidden flex flex-col lg:flex-row mb-16"
        >
          <div className="flex-1 p-6 md:p-8 flex flex-col sm:flex-row gap-8">
            {/* Order meta */}
            <div className="flex flex-row flex-wrap sm:flex-col gap-6 sm:w-36 sm:shrink-0">
              <div className="flex flex-col gap-1">
                <p className="text-label text-text-muted">Bestellnummer</p>
                <p className="font-bold text-body-sm text-text-primary whitespace-nowrap">{order.orderNumber}</p>
              </div>
              <div className="flex flex-col gap-1">
                <p className="text-label text-text-muted">Bestelldatum</p>
                <p className="font-bold text-body-sm text-text-primary whitespace-nowrap">
                  {formatDate(order.orderDateIso)}
                </p>
              </div>
              <div className="flex flex-col gap-1">
                <p className="text-label text-text-muted">Zahlungsmethode</p>
                <p className="font-bold text-body-sm text-text-primary whitespace-nowrap">{order.paymentMethodTitle}</p>
              </div>
            </div>

            {/* Items + totals */}
            <div className="flex-1 flex flex-col gap-5 min-w-0">
              <p
                className="font-semibold text-h-small text-text-primary"
                style={{ fontFamily: "var(--font-lora)" }}
              >
                Bestellübersicht
              </p>

              {items.map(({ entry, product }) => {
                const unitPrice = effectivePrice(entry, product);
                const taxRate = effectiveTaxRate(product, defaultTaxRate);
                const lineKey = entry.variant ? `${product.id}::${entry.variant}` : product.id;
                return (
                <div key={lineKey} className="flex gap-4 items-center w-full">
                  <div className="relative size-16 shrink-0 rounded-sm overflow-hidden">
                    <Image src={product.image} alt={product.name} fill sizes="64px" className="object-cover" />
                  </div>
                  <div className="flex-1 min-w-0 flex flex-col gap-0.5">
                    <p className="text-body-sm text-text-primary">
                      {product.name}
                      {entry.variant ? ` (${entry.variant})` : ""}
                    </p>
                    <p className="text-label text-text-muted">
                      {entry.qty} × {formatPrice(unitPrice)} {!order.kleinunternehmer && <span>inkl. {taxRate}% MwSt.</span>}
                    </p>
                  </div>
                  <p className="text-body-sm text-text-primary whitespace-nowrap">
                    {formatPrice(entry.qty * unitPrice)}
                  </p>
                </div>
                );
              })}

              <div className="h-px bg-border w-full" />

              <div className="flex items-center w-full">
                <span className="text-body-sm text-text-primary">Zwischensumme</span>
                <span className="flex-1" />
                <span className="text-body-sm text-text-primary">{formatPrice(subtotal)}</span>
              </div>
              {totalSavings > 0 && (
                <div className="flex items-center w-full">
                  <span className="text-body-sm text-success">Du sparst</span>
                  <span className="flex-1" />
                  <span className="font-bold text-body-sm text-success">-{formatPrice(totalSavings)}</span>
                </div>
              )}
              {order.discountCode && (
                <div className="flex items-center w-full">
                  <span className="text-body-sm text-success">Rabattcode ({order.discountCode})</span>
                  <span className="flex-1" />
                  <span className="font-bold text-body-sm text-success">-{formatPrice(order.discountAmount)}</span>
                </div>
              )}
              <div className="flex items-center w-full">
                <span className="text-body-sm text-text-primary">Versand</span>
                <span className="flex-1" />
                <span className="text-body-sm text-text-primary">
                  {order.shippingCost === 0 ? "Kostenlos" : formatPrice(order.shippingCost)}
                </span>
              </div>

              <div className="h-px bg-border w-full" />

              <div className="flex flex-col gap-0.5 w-full">
                <div className="flex items-center w-full">
                  <span
                    className="font-semibold text-h4 text-text-primary"
                    style={{ fontFamily: "var(--font-lora)" }}
                  >
                    Gesamtbetrag
                  </span>
                  <span className="flex-1" />
                  <span className="font-bold text-h-small text-text-primary">{formatPrice(total)}</span>
                </div>
                {order.kleinunternehmer ? (
                  <p className="text-label text-text-muted">Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.</p>
                ) : order.vatExempt ? (
                  <p className="text-label text-text-muted">Steuerfreie innergemeinschaftliche Lieferung (§4 Nr. 1b UStG)</p>
                ) : (
                  <VatBreakdown groups={taxBreakdown} />
                )}
              </div>
            </div>
          </div>

          {/* Delivery status panel */}
          <div className="w-full lg:w-[18rem] lg:shrink-0 bg-bg-muted p-7 flex flex-col items-center text-center gap-3 justify-center">
            <div className="flex items-center justify-center size-14 rounded-full bg-brand/10 text-text-primary shrink-0">
              <svg viewBox="0 0 24 24" className="size-6" fill="none" aria-hidden="true">
                <path d="M2 6.5h11v10H2z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" />
                <path d="M13 10.5h4l3.5 3v3H13z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round" />
                <circle cx="6" cy="17.5" r="1.6" stroke="currentColor" strokeWidth="1.6" />
                <circle cx="17" cy="17.5" r="1.6" stroke="currentColor" strokeWidth="1.6" />
              </svg>
            </div>
            <p className="font-semibold text-body text-text-primary">Deine Bestellung wird bearbeitet.</p>
            <p className="text-body-sm text-text-muted">
              Wir versenden in der Regel innerhalb von 1–2 Werktagen.
            </p>
            <p className="text-body-sm text-text-muted">
              Du erhältst eine E-Mail, sobald dein Paket unterwegs ist.
            </p>
          </div>
        </Reveal>
      )}

      <Reveal delay={0.08} className="flex items-center justify-center pb-4 px-[var(--layout-padding-x)] w-full">
        <Link href="/konto/bestellungen" className="underline text-body-sm text-text-primary hover:text-brand transition-colors">
          Meine Bestellungen ansehen
        </Link>
      </Reveal>

      {/* Testimonial band — same proven structure as /not-found's version
          (see that page's own comment), not a new layout: w-[45%] image
          column, narrow 40px edge gradient into bg-muted, quote in the
          flex-1 remainder. Only real change from that version is a fixed
          h- instead of min-h-, so both columns are pinned to an
          identical height regardless of how many lines the quote wraps
          to (a min-height alone lets whichever column has more content
          stretch the row past what the other side visually fills). */}
      <Reveal className="relative w-full flex items-stretch h-[14rem] sm:h-[16rem] bg-bg-muted overflow-hidden">
        <div className="relative w-full sm:w-[45%] shrink-0">
          {/* -inset-1, not inset-0 — this section fades in via Reveal's
              y:28→0 transform; a plain inset-0 image can leave a
              hairline gap at the top edge while that's still settling
              (or from ordinary sub-pixel rounding). Overflowing the
              image 4px past the container on every side means any such
              gap shows the image itself, not whatever's behind it — the
              parent's overflow-hidden clips the small overflow back
              down to a clean box either way. */}
          <Image
            alt=""
            src="/bestellbestaetigung-testimonial-photo.jpg"
            width={366}
            height={126}
            sizes="(min-width: 640px) 45vw, 100vw"
            className="absolute -inset-1 w-[calc(100%+0.5rem)] h-[calc(100%+0.5rem)] object-cover"
          />
          <div className="hidden sm:block absolute inset-y-0 right-0 w-40 bg-gradient-to-l from-bg-muted to-transparent" />
        </div>
        <div className="flex-1 flex flex-col justify-center gap-3 px-8 md:px-16">
          <p
            className="font-semibold text-h-section text-text-primary leading-[1.3] max-w-[28rem]"
            style={{ fontFamily: "var(--font-lora)" }}
          >
            „Produktivität beginnt nicht mit mehr – sondern mit dem, was wirklich zählt.“
          </p>
          <div className="h-[0.125rem] w-8 bg-brand" />
          <p className="text-body text-text-muted">Björn</p>
        </div>
      </Reveal>
    </>
  );
}
