import { useState, useEffect, useMemo, useRef } from 'react';
import { createFileRoute, Link } from '@tanstack/react-router';
import {
  ArrowRight, ArrowLeft, Check, CreditCard, Truck, User, ShoppingBag,
  Lock, Loader2, AlertCircle, Tag, X, Star,
} from 'lucide-react';
import { useAuthStore } from '@/stores/authStore';
import { confluxCheckout as confluxCheckoutFn } from '@/lib/wc.functions';
import { savePendingPurchase, trackEcommerce } from '@/lib/analytics';
import { toAnalyticsItem } from '@/hooks/useGqlCart';
import { useGqlCart } from '@/hooks/useGqlCart';
import { gqlCheckout, type GqlAddressInput } from '@/lib/graphql/cart';
import { attachAffiliateToOrder as attachAffiliateFn } from '@/lib/affiliate.functions';
import { useLoyalty } from '@/hooks/useLoyalty';
import { useSearchParams } from '@/hooks/useSearchParams';
import { useShippingCountries } from '@/hooks/useShippingEstimate';
import { PhoneInput, validatePhone } from '@/components/PhoneInput';
import { ServicepointPicker, type SelectedServicepoint } from '@/components/ServicepointPicker';
import {
  validateBillingAddress,
  validateShippingAddress,
  normalizePostalCode,
  type AddressErrors,
} from '@/lib/addressValidation';
import { useCarriersForCountry } from '@/lib/carrierMapping';
import { useT, useLang, headLang, localizePath, SITE_URL, locale } from '@/lib/i18n';

export const Route = createFileRoute('/checkout')({
  head: (ctx) => {
    const lang = headLang(ctx);
    const url = `${SITE_URL}${localizePath('/checkout', lang)}`;
    return {
      meta: [
        { title: lang === 'en' ? 'Checkout | Peptidewinkel' : 'Afrekenen | Peptidewinkel' },
        { name: 'description', content: lang === 'en' ? 'Complete your order at Peptidewinkel.' : 'Rond je bestelling af bij Peptidewinkel.' },
        { name: 'robots', content: 'noindex, nofollow' },
      ],
      links: [{ rel: 'canonical', href: url }],
    };
  },
  component: CheckoutPage,
});

type Step = 1 | 2 | 3 | 4;

interface PaymentMethodOption {
  id: string;
  label: string;
  desc: string;
  requiresRole?: string;
  logos?: { src: string; alt: string }[];
}

import sepaLogo from '@/assets/payment-logos/sepa.svg.asset.json';
import mastercardLogo from '@/assets/payment-logos/mastercard.svg.asset.json';
import visaLogo from '@/assets/payment-logos/visa.svg.asset.json';
import amexLogo from '@/assets/payment-logos/amex.svg.asset.json';
import idealLogo from '@/assets/payment-logos/ideal-wero.png.asset.json';
import bancontactLogo from '@/assets/payment-logos/bancontact.svg.asset.json';
import klarnaLogo from '@/assets/payment-logos/klarna.svg.asset.json';

const SEPA_LOGO = sepaLogo.url;
const CARD_LOGOS = [
  { src: mastercardLogo.url, alt: 'Mastercard' },
  { src: visaLogo.url, alt: 'Visa' },
  { src: amexLogo.url, alt: 'American Express' },
  { src: idealLogo.url, alt: 'iDEAL' },
  { src: bancontactLogo.url, alt: 'Bancontact' },
];


type TFn = (nl: string, en?: string) => string;

const getAllPaymentMethods = (t: TFn): PaymentMethodOption[] => [
  {
    id: 'bacs',
    label: t('SEPA / SEPA Instant bankoverschrijving', 'SEPA / SEPA Instant bank transfer'),
    desc: t('Handmatige overboeking — bankgegevens worden na bestelling getoond', 'Manual transfer — bank details are shown after your order'),
    logos: [{ src: SEPA_LOGO, alt: 'SEPA' }],
  },
  {
    id: 'conflux_ideal',
    label: 'iDEAL',
    desc: t('Direct betalen via je eigen bank', 'Pay directly via your own bank'),
    logos: [{ src: idealLogo.url, alt: 'iDEAL' }],
  },
  {
    id: 'conflux_bancontact',
    label: 'Bancontact',
    desc: t('Direct betalen met je Belgische bankkaart', 'Pay directly with your Belgian bank card'),
    logos: [{ src: bancontactLogo.url, alt: 'Bancontact' }],
  },
  {
    id: 'conflux_klarna',
    label: 'Klarna',
    desc: t('Achteraf betalen of in termijnen', 'Pay later or in installments'),
    logos: [{ src: klarnaLogo.url, alt: 'Klarna' }],
  },
];

const CONFLUX_WAY_CODES: Record<string, string> = {
  conflux_ideal: 'IDEAL',
  conflux_bancontact: 'BANCONTACT',
  conflux_klarna: 'KLARNA',
};

const COUNTRIES_NL: { code: string; nl: string; en: string }[] = [
  { code: 'NL', nl: 'Nederland', en: 'Netherlands' }, { code: 'BE', nl: 'België', en: 'Belgium' }, { code: 'DE', nl: 'Duitsland', en: 'Germany' },
  { code: 'FR', nl: 'Frankrijk', en: 'France' }, { code: 'LU', nl: 'Luxemburg', en: 'Luxembourg' }, { code: 'AT', nl: 'Oostenrijk', en: 'Austria' },
  { code: 'ES', nl: 'Spanje', en: 'Spain' }, { code: 'IT', nl: 'Italië', en: 'Italy' }, { code: 'PT', nl: 'Portugal', en: 'Portugal' },
  { code: 'GB', nl: 'Verenigd Koninkrijk', en: 'United Kingdom' }, { code: 'IE', nl: 'Ierland', en: 'Ireland' }, { code: 'DK', nl: 'Denemarken', en: 'Denmark' },
  { code: 'SE', nl: 'Zweden', en: 'Sweden' }, { code: 'NO', nl: 'Noorwegen', en: 'Norway' }, { code: 'FI', nl: 'Finland', en: 'Finland' },
  { code: 'PL', nl: 'Polen', en: 'Poland' }, { code: 'CZ', nl: 'Tsjechië', en: 'Czechia' }, { code: 'CH', nl: 'Zwitserland', en: 'Switzerland' },
  { code: 'US', nl: 'Verenigde Staten', en: 'United States' },
];
const getCountries = (lang: 'nl' | 'en') => COUNTRIES_NL.map((c) => ({ code: c.code, name: lang === 'en' ? c.en : c.nl }));

const getSteps = (t: TFn) => [
  { num: 1, label: t('Gegevens', 'Details'), icon: User },
  { num: 2, label: t('Verzending', 'Shipping'), icon: Truck },
  { num: 3, label: t('Betaling', 'Payment'), icon: CreditCard },
  { num: 4, label: t('Bevestiging', 'Confirmation'), icon: Check },
];

function CarrierLine({ country }: { country: string }) {
  const t = useT();
  const carriers = useCarriersForCountry(country);
  if (carriers.length === 0) return null;
  return <p>{t('Bezorgd door', 'Delivered by')} {carriers.join(', ')}</p>;
}

function CheckoutPage() {
  const t = useT();
  const lang = useLang();
  const steps = useMemo(() => getSteps(t), [t]);
  const ALL_PAYMENT_METHODS = useMemo(() => getAllPaymentMethods(t), [t]);
  const COUNTRIES = useMemo(() => getCountries(lang), [lang]);
  const {
    items, totals, isReady, isFetching, cart,
    shippingRates, chosenShippingMethods,
    updateShippingMethod, updateShippingPending,
    updateCustomer, updateCustomerPending,
    applyCoupon, applyCouponPending, removeCoupon,
  } = useGqlCart();
  const { codes: allowedCountryCodes } = useShippingCountries();
  // Carriers worden hieronder per gekozen verzendland opgehaald (zie shippingCountry).
  const { customer, isLoggedIn, wcToken } = useAuthStore();
  const beganCheckout = useRef(false);
  useEffect(() => {
    if (beganCheckout.current || !isReady || !items.length) return;
    beganCheckout.current = true;
    trackEcommerce("begin_checkout", items.map((i) => toAnalyticsItem(i)));
  }, [isReady, items]);
  const [searchParams] = useSearchParams();
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [couponError, setCouponError] = useState<string | null>(null);
  const cancelled = searchParams.get('cancelled');

  const userRoles = (customer as { roles?: string[] } | null)?.roles || [];
  const paymentMethods = useMemo(
    () => ALL_PAYMENT_METHODS.filter((m) => !m.requiresRole || userRoles.includes(m.requiresRole)),
    [userRoles]
  );

  const defaultPaymentMethod = paymentMethods[0]?.id || 'bacs';

  // Filter het landenlijst op WooCommerce-shippingzones. `null` = wereldwijd.
  // Als WC geen zones teruggeeft (lege set) → toon volledige lijst zodat de
  // klant nooit met een lege dropdown achterblijft.
  const availableCountries = useMemo(() => {
    if (!allowedCountryCodes || allowedCountryCodes.size === 0) return COUNTRIES;
    const filtered = COUNTRIES.filter((c) => allowedCountryCodes.has(c.code));
    return filtered.length > 0 ? filtered : COUNTRIES;
  }, [allowedCountryCodes]);

  const [couponInput, setCouponInput] = useState('');
  const [pointsToRedeem, setPointsToRedeem] = useState(0);
  const [servicepoint, setServicepoint] = useState<SelectedServicepoint | null>(null);
  const [addressErrors, setAddressErrors] = useState<AddressErrors>({});
  const [addressTouched, setAddressTouched] = useState(false);
  const { loyalty } = useLoyalty();

  const [form, setForm] = useState({
    firstName: isLoggedIn ? customer?.first_name || '' : '',
    lastName: isLoggedIn ? customer?.last_name || '' : '',
    email: isLoggedIn ? customer?.email || '' : '',
    phone: isLoggedIn ? customer?.billing?.phone || '' : '',
    street: isLoggedIn ? customer?.billing?.address_1?.replace(/\s+\d+\S*$/, '') || '' : '',
    houseNumber: '',
    address2: isLoggedIn ? customer?.billing?.address_2 || '' : '',
    postalCode: isLoggedIn ? customer?.billing?.postcode || '' : '',
    city: isLoggedIn ? customer?.billing?.city || '' : '',
    country: isLoggedIn ? customer?.billing?.country || 'NL' : 'NL',
    sameShipping: true,
    shippingStreet: '', shippingHouseNumber: '', shippingAddress2: '',
    shippingPostalCode: '', shippingCity: '', shippingCountry: 'NL',
    paymentMethod: defaultPaymentMethod, orderNotes: '', acceptTerms: false, couponCode: '',
  });

  useEffect(() => {
    if (!paymentMethods.find((m) => m.id === form.paymentMethod)) {
      setForm((prev) => ({ ...prev, paymentMethod: defaultPaymentMethod }));
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [paymentMethods]);

  const updateField = (field: string, value: string | boolean) =>
    setForm((prev) => ({ ...prev, [field]: value }));

  // Push address to server-cart (debounced) so Woo can match the right
  // shipping zone and apply/recompute coupons against the correct totals.
  const lastSyncedAddr = useRef<string>('');
  useEffect(() => {
    if (!isReady) return;
    const billing: GqlAddressInput = {
      firstName: form.firstName, lastName: form.lastName, email: form.email, phone: form.phone,
      address1: `${form.street} ${form.houseNumber}`.trim(),
      address2: form.address2, city: form.city, postcode: form.postalCode, country: form.country,
    };
    const shipping: GqlAddressInput = form.sameShipping
      ? { ...billing }
      : {
          firstName: form.firstName, lastName: form.lastName,
          address1: `${form.shippingStreet} ${form.shippingHouseNumber}`.trim(),
          address2: form.shippingAddress2, city: form.shippingCity,
          postcode: form.shippingPostalCode, country: form.shippingCountry,
        };
    const key = JSON.stringify({ billing, shipping });
    if (key === lastSyncedAddr.current) return;
    // Only sync when at least country+postcode are present (avoid spamming Woo).
    const ready = billing.country && (billing.postcode || '').length >= 4;
    if (!ready) return;
    const t = setTimeout(() => {
      lastSyncedAddr.current = key;
      updateCustomer({ billing, shipping }).catch((e) =>
        console.warn('updateCustomer failed:', e)
      );
    }, 600);
    return () => clearTimeout(t);
  }, [
    isReady, form.firstName, form.lastName, form.email, form.phone,
    form.street, form.houseNumber, form.address2, form.postalCode, form.city, form.country,
    form.sameShipping, form.shippingStreet, form.shippingHouseNumber, form.shippingAddress2,
    form.shippingPostalCode, form.shippingCity, form.shippingCountry, updateCustomer,
  ]);

  // Reset pakketpunt zodra het verzendland verandert — codes zijn landgebonden.
  const spCountry = form.sameShipping ? form.country : form.shippingCountry;
  useEffect(() => {
    setServicepoint(null);
  }, [spCountry]);

  // Als het huidig geselecteerde land niet in de WC-shippingzones valt
  // (bv. doordat het opgeslagen klantadres een ander land had), schuif
  // door naar het eerste toegestane land zodat de klant niet vastzit.
  useEffect(() => {
    if (availableCountries.length === 0) return;
    const allowed = new Set(availableCountries.map((c) => c.code));
    setForm((prev) => {
      const next = { ...prev };
      let changed = false;
      if (!allowed.has(prev.country)) {
        next.country = availableCountries[0].code;
        changed = true;
      }
      if (!prev.sameShipping && !allowed.has(prev.shippingCountry)) {
        next.shippingCountry = availableCountries[0].code;
        changed = true;
      }
      return changed ? next : prev;
    });
  }, [availableCountries]);

  // Server-cart totals (authoritative — no local shipping estimation).
  const subtotal = totals.subtotal;
  const discount = totals.discount;
  const shippingCost = totals.shipping;
  const pointsDiscount = pointsToRedeem > 0 && loyalty ? pointsToRedeem * loyalty.pointsToEuro : 0;
  // Points are redeemed server-side; subtract them here for the display total.
  const total = Math.max(0, totals.total - pointsDiscount);

  const phoneError = validatePhone(form.phone, lang);

  // Live validatie zodra de klant ooit op Volgende heeft geklikt, zodat
  // fouten direct verdwijnen bij het corrigeren.
  useEffect(() => {
    if (!addressTouched) return;
    const errs: AddressErrors = {
      ...validateBillingAddress({
        firstName: form.firstName, lastName: form.lastName, email: form.email,
        street: form.street, houseNumber: form.houseNumber,
        postalCode: form.postalCode, city: form.city, country: form.country,
      }, lang),
    };
    if (!form.sameShipping) {
      Object.assign(errs, validateShippingAddress({
        shippingStreet: form.shippingStreet,
        shippingHouseNumber: form.shippingHouseNumber,
        shippingPostalCode: form.shippingPostalCode,
        shippingCity: form.shippingCity,
        shippingCountry: form.shippingCountry,
      }, lang));
    }
    setAddressErrors(errs);
  }, [
    addressTouched, form.firstName, form.lastName, form.email, form.street,
    form.houseNumber, form.postalCode, form.city, form.country, form.sameShipping,
    form.shippingStreet, form.shippingHouseNumber, form.shippingPostalCode,
    form.shippingCity, form.shippingCountry, lang,
  ]);

  const validateAndAdvance = () => {
    const errs: AddressErrors = {
      ...validateBillingAddress({
        firstName: form.firstName, lastName: form.lastName, email: form.email,
        street: form.street, houseNumber: form.houseNumber,
        postalCode: form.postalCode, city: form.city, country: form.country,
      }, lang),
    };
    if (!form.sameShipping) {
      Object.assign(errs, validateShippingAddress({
        shippingStreet: form.shippingStreet,
        shippingHouseNumber: form.shippingHouseNumber,
        shippingPostalCode: form.shippingPostalCode,
        shippingCity: form.shippingCity,
        shippingCountry: form.shippingCountry,
      }, lang));
    }
    if (phoneError) {
      // PhoneInput toont zijn eigen fout, maar zorg dat we niet doorgaan.
    }
    setAddressErrors(errs);
    setAddressTouched(true);
    if (Object.keys(errs).length === 0 && !phoneError) {
      // Normaliseer postcode voor net display + correcte server-cart match.
      setForm((prev) => ({
        ...prev,
        postalCode: normalizePostalCode(prev.country, prev.postalCode),
        shippingPostalCode: prev.sameShipping
          ? prev.shippingPostalCode
          : normalizePostalCode(prev.shippingCountry, prev.shippingPostalCode),
      }));
      return true;
    }
    return false;
  };




  const selectedRateId = chosenShippingMethods[0] || '';

  const handleCouponSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!couponInput.trim()) return;
    setCouponError(null);
    try {
      const next = await applyCoupon(couponInput.trim());
      const applied = next?.appliedCoupons?.some(
        (c) => c.code.toLowerCase() === couponInput.trim().toLowerCase()
      );
      if (!applied) {
        setCouponError(t('Kortingscode niet geldig.', 'Discount code is not valid.'));
      } else {
        setCouponInput('');
      }
    } catch (err) {
      setCouponError(err instanceof Error ? err.message : t('Kortingscode niet geldig.', 'Discount code is not valid.'));
    }
  };

  const handlePlaceOrder = async () => {
    if (!form.acceptTerms || isSubmitting) return;
    if (!paymentMethods.find((m) => m.id === form.paymentMethod)) {
      setSubmitError(t('Deze betaalmethode is niet beschikbaar voor uw account.', 'This payment method is not available for your account.'));
      return;
    }
    if (!selectedRateId) {
      setSubmitError(t('Selecteer een verzendmethode.', 'Please select a shipping method.'));
      return;
    }
    setIsSubmitting(true);
    setSubmitError(null);

    const billing: GqlAddressInput = {
      firstName: form.firstName, lastName: form.lastName, email: form.email, phone: form.phone,
      address1: `${form.street} ${form.houseNumber}`.trim(),
      address2: form.address2, city: form.city, postcode: form.postalCode, country: form.country,
    };
    const shipping: GqlAddressInput | undefined = form.sameShipping ? undefined : {
      firstName: form.firstName, lastName: form.lastName,
      address1: `${form.shippingStreet} ${form.shippingHouseNumber}`.trim(),
      address2: form.shippingAddress2, city: form.shippingCity,
      postcode: form.shippingPostalCode, country: form.shippingCountry,
    };

    try {
      // Ensure server-cart has the final address before placing the order.
      await updateCustomer({ billing, shipping: shipping ?? billing });

      // Pakketpunt-info — voorvoegen aan klantnotitie zodat WC/QLS-webhook
      // de code uit de order kan lezen (later vervangen door order meta).
      const spNote = servicepoint
        ? `[QLS_SERVICEPOINT] ${servicepoint.carrier ?? ''} ${servicepoint.code} — ${servicepoint.name}, ${servicepoint.address}`
        : '';
      const combinedNote = [spNote, form.orderNotes].filter(Boolean).join('\n\n');

      if (form.paymentMethod === 'bacs') {
        const result = await gqlCheckout({
          billing,
          shipping,
          shipToDifferentAddress: !form.sameShipping,
          paymentMethod: 'bacs',
          customerNote: combinedNote,
        });
        if (!result?.order?.databaseId) {
          throw new Error(t('Bestelling kon niet worden aangemaakt. Probeer het opnieuw.', 'Order could not be created. Please try again.'));
        }
        if (result.order.orderKey) {
          try {
            await attachAffiliateFn({ data: { order_id: result.order.databaseId, order_key: result.order.orderKey } });
          } catch { /* attribution must never block the order */ }
        }
        const qs = new URLSearchParams({
          order_id: String(result.order.databaseId),
          method: 'bacs',
          ...(result.order.orderKey ? { order_key: result.order.orderKey } : {}),
        }).toString();
        window.location.href = `/bestelling-bevestigd?${qs}`;
        return;
      }

      // The wallet path: the server function creates the WC order, reserves the
      // loyalty points and lets the Laravel backend start the payment. We pass the
      // server-cart items and the chosen shipping rate id ("flat_rate:5") so the
      // server can resolve the instance_id.
      const instanceId = (() => {
        const m = /^[^:]+:(\d+)$/.exec(selectedRateId);
        return m ? Number(m[1]) : undefined;
      })();
      const rate = shippingRates.find((r) => r.id === selectedRateId);

      const payload = {
        customer: { first_name: form.firstName, last_name: form.lastName, email: form.email, phone: form.phone },
        billing: { street: form.street, house_number: form.houseNumber, address_2: form.address2, postal_code: form.postalCode, city: form.city, country: form.country },
        shipping: form.sameShipping ? undefined : {
          street: form.shippingStreet, house_number: form.shippingHouseNumber, address_2: form.shippingAddress2,
          postal_code: form.shippingPostalCode, city: form.shippingCity, country: form.shippingCountry,
        },
        items: items.map((item) => ({
          name: item.name,
          quantity: item.quantity,
          unit_price: item.unitPrice.toFixed(2),
          sku: '',
          product_id: item.productId,
        })),
        shipping_method: rate?.methodId || 'flat_rate',
        shipping_method_instance_id: instanceId,
        shipping_cost: shippingCost,
        payment_method: form.paymentMethod,
        order_notes: combinedNote,
        qls_servicepoint_code: servicepoint?.code,
        qls_servicepoint_name: servicepoint?.name,
        qls_servicepoint_carrier: servicepoint?.carrier ?? undefined,
        qls_servicepoint_address: servicepoint?.address,
        customer_id: isLoggedIn ? customer?.id : undefined,
        wc_token: wcToken || undefined,
        coupon_code: totals.appliedCoupons[0]?.code,
        points_to_redeem: pointsToRedeem > 0 ? pointsToRedeem : undefined,
        client_user_agent: navigator.userAgent,
        site_origin: window.location.origin,
      };

      const wayCode = CONFLUX_WAY_CODES[form.paymentMethod];
      if (!wayCode) throw new Error(t('Kies een betaalmethode.', 'Choose a payment method.'));

      const data = (await confluxCheckoutFn({ data: { ...payload, way_code: wayCode } })) as {
        error?: string; payment_link?: string;
      };
      if (data?.error) throw new Error(data.error);
      if (data?.payment_link) {
        savePendingPurchase({
          items: items.map((i) => toAnalyticsItem(i)),
          value: totals.total,
          shipping: totals.shipping ?? 0,
          tax: totals.tax ?? 0,
          coupon: totals.appliedCoupons[0]?.code,
        });
        window.location.href = data.payment_link;
      }
      else throw new Error(t('Geen betaallink ontvangen. Neem contact op met de klantenservice.', 'No payment link received. Please contact customer service.'));
    } catch (err) {
      console.error('Checkout error:', err);
      const msg = err instanceof Error ? err.message : t('Er is een fout opgetreden. Probeer het opnieuw.', 'An error occurred. Please try again.');
      if (/punt/i.test(msg)) setPointsToRedeem(0);
      setSubmitError(msg);
    } finally { setIsSubmitting(false); }
  };

  if (!isReady) {
    return (
      <div className="container py-20 text-center">
        <Loader2 className="w-8 h-8 mx-auto text-muted-foreground animate-spin mb-4" />
        <p className="text-sm text-muted-foreground">{t('Winkelwagen laden...', 'Loading cart...')}</p>
      </div>
    );
  }

  if (items.length === 0) {
    return (
      <div className="container py-20 text-center">
        <div className="mx-auto w-24 h-24 rounded-full bg-muted flex items-center justify-center mb-6">
          <ShoppingBag className="w-11 h-11 text-muted-foreground/60" aria-hidden="true" />
        </div>
        <h1 className="text-2xl font-bold mb-2">{t('Uw winkelwagen is leeg', 'Your cart is empty')}</h1>
        <p className="text-muted-foreground mb-6 max-w-md mx-auto">{t('Ontdek onze producten en voeg ze toe aan uw wagen.', 'Discover our products and add them to your cart.')}</p>
        <Link to="/shop" className="inline-flex items-center gap-2 bg-primary text-primary-foreground font-semibold px-6 py-3 rounded-md hover:bg-primary-hover transition-colors">
          {t('Bekijk producten', 'View products')} <ArrowRight className="w-4 h-4" />
        </Link>
      </div>
    );
  }

  const inputCls = "w-full px-3 py-2.5 border border-border rounded-md bg-background text-sm focus:ring-2 focus:ring-ring outline-none";
  const selectCls = "w-full px-3 py-2.5 border border-border rounded-md bg-background text-sm focus:ring-2 focus:ring-ring outline-none";

  const appliedCoupon = totals.appliedCoupons[0];
  const shippingCountry = form.sameShipping ? form.country : form.shippingCountry;
  const shippingPostalCode = form.sameShipping ? form.postalCode : form.shippingPostalCode;
  const cartBusy = isFetching || updateCustomerPending || updateShippingPending;

  return (
    <div className="container py-8 max-w-4xl">
      {cancelled && (
        <div className="mb-6 p-4 bg-destructive/10 border border-destructive/20 rounded-lg flex items-center gap-3">
          <AlertCircle className="w-5 h-5 text-destructive shrink-0" />
          <p className="text-sm">{t('Uw betaling is geannuleerd. U kunt het opnieuw proberen.', 'Your payment was cancelled. You can try again.')}</p>
        </div>
      )}

      <div className="grid md:grid-cols-3 gap-8">
        <div className="md:col-span-2 space-y-10">
          {(() => {
            const err = (key: keyof AddressErrors) =>
              addressErrors[key] ? (
                <p className="text-xs text-destructive mt-1">{addressErrors[key]}</p>
              ) : null;
            const ring = (key: keyof AddressErrors) =>
              addressErrors[key] ? 'border-destructive focus:ring-destructive' : '';
            return (
            <div className="space-y-6">
              <h2 className="text-xl font-bold">{t('Uw Gegevens', 'Your Details')}</h2>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium mb-1">{t('Voornaam', 'First name')} *</label>
                  <input value={form.firstName} onChange={(e) => updateField('firstName', e.target.value)} className={`${inputCls} ${ring('firstName')}`} />
                  {err('firstName')}
                </div>
                <div>
                  <label className="block text-sm font-medium mb-1">{t('Achternaam', 'Last name')} *</label>
                  <input value={form.lastName} onChange={(e) => updateField('lastName', e.target.value)} className={`${inputCls} ${ring('lastName')}`} />
                  {err('lastName')}
                </div>
              </div>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium mb-1">{t('E-mail', 'Email')} *</label>
                  <input type="email" value={form.email} onChange={(e) => updateField('email', e.target.value)} className={`${inputCls} ${ring('email')}`} />
                  {err('email')}
                </div>
                <div>
                  <label className="block text-sm font-medium mb-1">{t('Telefoonnummer', 'Phone number')}</label>
                  <PhoneInput value={form.phone} onChange={(val) => updateField('phone', val)} defaultCountry={form.country} error={form.phone.length > 3 ? phoneError : null} />
                </div>
              </div>
              <h3 className="font-semibold mt-4">{t('Factuuradres', 'Billing address')}</h3>
              <div>
                <label className="block text-sm font-medium mb-1">{t('Land', 'Country')} *</label>
                <select value={form.country} onChange={(e) => updateField('country', e.target.value)} className={selectCls}>
                  {availableCountries.map((c) => <option key={c.code} value={c.code}>{c.name}</option>)}
                </select>
              </div>
              <div className="grid grid-cols-3 gap-4">
                <div className="col-span-2">
                  <label className="block text-sm font-medium mb-1">{t('Straat', 'Street')} *</label>
                  <input value={form.street} onChange={(e) => updateField('street', e.target.value)} className={`${inputCls} ${ring('street')}`} />
                  {err('street')}
                </div>
                <div>
                  <label className="block text-sm font-medium mb-1">{t('Huisnr.', 'House no.')} *</label>
                  <input value={form.houseNumber} onChange={(e) => updateField('houseNumber', e.target.value)} placeholder={t('bv. 12a', 'e.g. 12a')} className={`${inputCls} ${ring('houseNumber')}`} />
                  {err('houseNumber')}
                </div>
              </div>
              <div>
                <label className="block text-sm font-medium mb-1">{t('Adresregel 2', 'Address line 2')} <span className="text-muted-foreground font-normal">({t('optioneel', 'optional')})</span></label>
                <input value={form.address2} onChange={(e) => updateField('address2', e.target.value)} placeholder={t('Appartement, suite, etc.', 'Apartment, suite, etc.')} className={inputCls} />
              </div>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium mb-1">{t('Postcode', 'Postal code')} *</label>
                  <input value={form.postalCode} onChange={(e) => updateField('postalCode', e.target.value)} className={`${inputCls} ${ring('postalCode')}`} />
                  {err('postalCode')}
                </div>
                <div>
                  <label className="block text-sm font-medium mb-1">{t('Plaats', 'City')} *</label>
                  <input value={form.city} onChange={(e) => updateField('city', e.target.value)} className={`${inputCls} ${ring('city')}`} />
                  {err('city')}
                </div>
              </div>
              <label className="flex items-center gap-2 cursor-pointer">
                <input type="checkbox" checked={form.sameShipping} onChange={(e) => updateField('sameShipping', e.target.checked)} className="rounded border-border text-primary" />
                <span className="text-sm">{t('Verzendadres is hetzelfde als factuuradres', 'Shipping address is the same as billing address')}</span>
              </label>
              {!form.sameShipping && (
                <div className="space-y-4 p-4 bg-muted/50 rounded-lg">
                  <h3 className="font-semibold">{t('Verzendadres', 'Shipping address')}</h3>
                  <select value={form.shippingCountry} onChange={(e) => updateField('shippingCountry', e.target.value)} className={selectCls}>
                    {availableCountries.map((c) => <option key={c.code} value={c.code}>{c.name}</option>)}
                  </select>
                  <div className="grid grid-cols-3 gap-4">
                    <div className="col-span-2">
                      <input value={form.shippingStreet} onChange={(e) => updateField('shippingStreet', e.target.value)} placeholder={t('Straat', 'Street')} className={`${inputCls} ${ring('shippingStreet')}`} />
                      {err('shippingStreet')}
                    </div>
                    <div>
                      <input value={form.shippingHouseNumber} onChange={(e) => updateField('shippingHouseNumber', e.target.value)} placeholder={t('Huisnr.', 'House no.')} className={`${inputCls} ${ring('shippingHouseNumber')}`} />
                      {err('shippingHouseNumber')}
                    </div>
                  </div>
                  <input value={form.shippingAddress2} onChange={(e) => updateField('shippingAddress2', e.target.value)} placeholder={t('Adresregel 2 (optioneel)', 'Address line 2 (optional)')} className={inputCls} />
                  <div className="grid grid-cols-2 gap-4">
                    <div>
                      <input value={form.shippingPostalCode} onChange={(e) => updateField('shippingPostalCode', e.target.value)} placeholder={t('Postcode', 'Postal code')} className={`${inputCls} ${ring('shippingPostalCode')}`} />
                      {err('shippingPostalCode')}
                    </div>
                    <div>
                      <input value={form.shippingCity} onChange={(e) => updateField('shippingCity', e.target.value)} placeholder={t('Plaats', 'City')} className={`${inputCls} ${ring('shippingCity')}`} />
                      {err('shippingCity')}
                    </div>
                  </div>
                </div>
              )}
              <div>
                <label className="block text-sm font-medium mb-1">{t('Opmerkingen bij bestelling', 'Order notes')} <span className="text-muted-foreground font-normal">({t('optioneel', 'optional')})</span></label>
                <textarea value={form.orderNotes} onChange={(e) => updateField('orderNotes', e.target.value)} rows={3} placeholder={t('Speciale instructies voor uw bestelling...', 'Special instructions for your order...')} className="w-full px-3 py-2.5 border border-border rounded-md bg-background text-sm focus:ring-2 focus:ring-ring outline-none resize-none" />
              </div>
            </div>
            );
          })()}

          {(
            <div className="space-y-6">
              <h2 className="text-xl font-bold">{t('Verzendmethode', 'Shipping method')}</h2>
              <div className="text-sm text-muted-foreground space-y-1">
                <p>
                  {t('Verzending naar', 'Shipping to')}: {COUNTRIES.find((c) => c.code === shippingCountry)?.name || shippingCountry}
                </p>
                <CarrierLine country={shippingCountry} />
              </div>
              {cartBusy && shippingRates.length === 0 ? (
                <div className="flex items-center gap-2 text-muted-foreground py-8 justify-center">
                  <Loader2 className="w-5 h-5 animate-spin" /><span className="text-sm">{t('Verzendmethoden laden...', 'Loading shipping methods...')}</span>
                </div>
              ) : shippingRates.length === 0 ? (
                <div className="p-4 bg-destructive/10 border border-destructive/20 rounded-lg text-sm">
                  {t('Geen verzendmethoden beschikbaar voor dit land. Controleer uw adres in stap 1.', 'No shipping methods available for this country. Please check your address above.')}
                </div>
              ) : shippingRates.map((rate) => {
                const checked = rate.id === selectedRateId;
                // For the selected rate, prefer the server-computed shipping total
                // (authoritative — includes shipping-class fees the flat rate alone doesn't).
                const rateCost = Number(rate.cost) || 0;
                const effectiveCost = checked ? shippingCost : rateCost;
                const displayPrice = effectiveCost === 0 ? t('Gratis', 'Free') : `€${effectiveCost.toFixed(2)}`;
                return (
                  <label key={rate.id} className={`flex items-center gap-4 p-4 rounded-lg border cursor-pointer transition-all ${checked ? 'border-primary bg-primary/5' : 'border-border hover:border-primary/50'}`}>
                    <input
                      type="radio" name="shipping" value={rate.id} checked={checked}
                      onChange={() => updateShippingMethod(rate.id).catch((e) => console.warn(e))}
                      disabled={updateShippingPending}
                      className="text-primary"
                    />
                    <div className="flex-1">
                      <p className="font-medium text-sm">{rate.label}</p>
                    </div>
                    <span className="font-semibold text-sm">{displayPrice}</span>
                  </label>
                );
              })}
              {/* QLS pakketpunt-optie tijdelijk uitgeschakeld — wordt later heractiveerd. */}
              {false && (
                <div className="pt-2">
                  <ServicepointPicker
                    country={shippingCountry}
                    postalCode={shippingPostalCode}
                    value={servicepoint}
                    onChange={setServicepoint}
                  />
                </div>
              )}

            </div>
          )}

          {(
            <div className="space-y-4">
              <div>
                <h2 className="text-xl font-bold">{t('Betaalmethode', 'Payment method')}</h2>
                <p className="text-sm text-muted-foreground mt-1">{t('Kies hoe u wilt betalen. Alle transacties zijn versleuteld en veilig.', 'Choose how you want to pay. All transactions are encrypted and secure.')}</p>
              </div>
              <div className="grid gap-3">
                {paymentMethods.map((method) => {
                  const selected = form.paymentMethod === method.id;
                  return (
                    <label
                      key={method.id}
                      className={`group relative flex flex-col sm:flex-row sm:items-center gap-4 p-5 rounded-xl border-2 cursor-pointer transition-all overflow-hidden ${
                        selected
                          ? 'border-primary bg-gradient-to-br from-primary/10 via-primary/5 to-transparent shadow-gold-soft'
                          : 'border-border hover:border-primary/40 hover:bg-surface'
                      }`}
                    >
                      {selected && (
                        <span className="absolute top-3 right-3 inline-flex items-center justify-center w-5 h-5 rounded-full bg-primary text-primary-foreground">
                          <Check className="w-3 h-3" strokeWidth={3} />
                        </span>
                      )}
                      <input
                        type="radio"
                        name="payment"
                        value={method.id}
                        checked={selected}
                        onChange={(e) => updateField('paymentMethod', e.target.value)}
                        className="sr-only"
                      />
                      <div className={`flex items-center justify-center w-11 h-11 rounded-full shrink-0 transition-colors ${selected ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground group-hover:bg-primary/10'}`}>
                        <CreditCard className="w-5 h-5" />
                      </div>
                      <div className="flex-1 min-w-0">
                        <p className="font-semibold text-sm">{method.label}</p>
                        <p className="text-xs text-muted-foreground mt-0.5">{method.desc}</p>
                      </div>
                      {method.logos && method.logos.length > 0 && (
                        <div className="flex flex-wrap items-center gap-2 sm:justify-end">
                          {method.logos.map((logo) => (
                            <div
                              key={logo.alt}
                              className="flex items-center justify-center h-8 px-2 rounded-md bg-white border border-border/60 shadow-sm"
                              title={logo.alt}
                            >
                              <img
                                src={logo.src}
                                alt={logo.alt}
                                loading="lazy"
                                decoding="async"
                                className="h-5 w-auto object-contain"
                              />
                            </div>
                          ))}
                        </div>
                      )}
                    </label>
                  );
                })}
              </div>
              <p className="text-xs text-muted-foreground flex items-center gap-1.5 pt-1">
                <Check className="w-3.5 h-3.5 text-success" /> {t('256-bit SSL versleuteling · PCI-DSS compliant', '256-bit SSL encryption · PCI-DSS compliant')}
              </p>
            </div>
          )}

          <div className="space-y-4 border-t border-border pt-8">
            <label className="flex items-start gap-2 cursor-pointer">
              <input type="checkbox" checked={form.acceptTerms} onChange={(e) => updateField('acceptTerms', e.target.checked)} className="rounded border-border text-primary mt-0.5" />
              <span className="text-sm">{t('Ik ga akkoord met de', 'I agree to the')} <Link to="/algemene-voorwaarden" className="text-primary hover:underline">{t('algemene voorwaarden', 'terms and conditions')}</Link> {t('en het', 'and the')} <Link to="/privacybeleid" className="text-primary hover:underline">{t('privacybeleid', 'privacy policy')}</Link>.</span>
            </label>
            {submitError && (
              <div className="p-3 bg-destructive/10 border border-destructive/20 rounded-lg flex items-center gap-2">
                <AlertCircle className="w-4 h-4 text-destructive shrink-0" /><p className="text-sm text-destructive">{submitError}</p>
              </div>
            )}
          </div>

          <div className="flex flex-col-reverse sm:flex-row items-stretch sm:items-center justify-between gap-4 mt-6">
            <Link to="/cart" className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors">
              <ArrowLeft className="w-4 h-4" /> {t('Terug naar wagen', 'Back to cart')}
            </Link>
            <button
              onClick={() => {
                if (!validateAndAdvance()) {
                  setSubmitError(t('Controleer je gegevens hierboven.', 'Please check your details above.'));
                  window.scrollTo({ top: 0, behavior: 'smooth' });
                  return;
                }
                if (!selectedRateId) { setSubmitError(t('Kies een verzendmethode.', 'Please choose a shipping method.')); return; }
                setSubmitError(null);
                handlePlaceOrder();
              }}
              disabled={!form.acceptTerms || isSubmitting || cartBusy}
              className="flex items-center justify-center gap-2 bg-primary text-primary-foreground font-semibold px-6 py-3 rounded-md hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed">
              {isSubmitting ? (<><Loader2 className="w-4 h-4 animate-spin" /> {t('Verwerken...', 'Processing...')}</>) : (<><Lock className="w-4 h-4" /> {t('Bestelling Plaatsen', 'Place Order')}</>)}
            </button>
          </div>
        </div>

        <div className="bg-card border border-border rounded-lg p-5 h-fit sticky top-24">
          <h3 className="font-bold mb-4 flex items-center gap-2">
            {t('Overzicht', 'Summary')}
            {cartBusy && <Loader2 className="w-3.5 h-3.5 animate-spin text-muted-foreground" />}
          </h3>
          <div className="space-y-2 text-sm">
            {items.map((item) => (
              <div key={item.key} className={`flex justify-between ${item.bundled ? 'pl-4 text-xs' : ''}`}>
                <span className="text-muted-foreground truncate mr-2">{item.bundled ? '↳ ' : ''}{item.name} ×{item.quantity}</span>
                <span>{item.bundled ? t('Inbegrepen', 'Included') : `€${item.lineTotal.toFixed(2)}`}</span>
              </div>
            ))}
          </div>
          <div className="border-t border-border mt-3 pt-3 space-y-2 text-sm">
            <div className="flex justify-between"><span className="text-muted-foreground">{t('Subtotaal', 'Subtotal')}</span><span>€{subtotal.toFixed(2)}</span></div>
            {appliedCoupon && (
              <div className="flex justify-between text-success">
                <span className="flex items-center gap-1">
                  {t('Korting', 'Discount')} ({appliedCoupon.code})
                  <button onClick={() => removeCoupon(appliedCoupon.code)} className="text-muted-foreground hover:text-destructive"><X className="w-3 h-3" /></button>
                </span>
                <span>-€{discount.toFixed(2)}</span>
              </div>
            )}
            {pointsDiscount > 0 && (
              <div className="flex justify-between text-success">
                <span className="flex items-center gap-1">{t('Puntenkorting', 'Points discount')} ({pointsToRedeem} pts)
                  <button onClick={() => setPointsToRedeem(0)} className="text-muted-foreground hover:text-destructive"><X className="w-3 h-3" /></button>
                </span>
                <span>-€{pointsDiscount.toFixed(2)}</span>
              </div>
            )}
            <div className="flex justify-between">
              <span className="text-muted-foreground">{t('Verzending', 'Shipping')}</span>
              <span>{!selectedRateId ? '—' : shippingCost === 0 ? t('Gratis', 'Free') : `€${shippingCost.toFixed(2)}`}</span>
            </div>
          </div>

          {isLoggedIn && loyalty && loyalty.canRedeem && pointsToRedeem === 0 && Boolean(CONFLUX_WAY_CODES[form.paymentMethod]) && (() => {
            const baseTotal = Math.max(0, subtotal - discount + shippingCost);
            const maxByCap = Math.floor((baseTotal * 0.10) / loyalty.pointsToEuro / 100) * 100;
            const maxPoints = Math.min(loyalty.availableBalance, Math.max(0, maxByCap));
            if (maxPoints < loyalty.minRedemption) return null;
            return (
              <div className="mt-3 p-3 bg-primary/5 border border-primary/20 rounded-lg">
                <div className="flex items-center gap-2 text-sm mb-2">
                  <Star className="w-4 h-4 text-primary" />
                  <span className="font-medium">{loyalty.availableBalance.toLocaleString(locale(lang))} {t('punten beschikbaar', 'points available')}</span>
                </div>
                <div className="flex gap-2">
                  <input type="number" min={loyalty.minRedemption} max={maxPoints} step={100}
                    placeholder={t(`Min. ${loyalty.minRedemption}`, `Min. ${loyalty.minRedemption}`)} id="points-input"
                    className="flex-1 px-3 py-2 text-sm border border-border rounded-md bg-background outline-none" />
                  <button type="button" onClick={() => {
                    const el = document.getElementById('points-input') as HTMLInputElement;
                    const val = parseInt(el?.value || '0', 10);
                    if (val >= loyalty.minRedemption && val <= maxPoints) setPointsToRedeem(val);
                  }} className="px-3 py-2 text-sm border border-border rounded-md hover:bg-muted transition-colors font-medium">
                    {t('Toepassen', 'Apply')}
                  </button>
                </div>
                <p className="text-xs text-muted-foreground mt-1">{t('Max.', 'Max.')} {maxPoints.toLocaleString(locale(lang))} {t('punten (10% van bestelling)', 'points (10% of order)')}</p>
              </div>
            );
          })()}

          {!appliedCoupon && (
            <form className="flex gap-2 mt-3" onSubmit={handleCouponSubmit}>
              <div className="relative flex-1">
                <Tag className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" />
                <input type="text" value={couponInput} onChange={(e) => setCouponInput(e.target.value)} placeholder={t('Kortingscode', 'Discount code')} disabled={applyCouponPending}
                  className="w-full pl-9 pr-3 py-2 text-sm border border-border rounded-md bg-background outline-none disabled:opacity-50" />
              </div>
              <button type="submit" disabled={applyCouponPending} className="px-3 py-2 text-sm border border-border rounded-md hover:bg-muted transition-colors font-medium disabled:opacity-50">
                {applyCouponPending ? <Loader2 className="w-4 h-4 animate-spin" /> : t('Toepassen', 'Apply')}
              </button>
            </form>
          )}
          {appliedCoupon && <p className="text-xs text-success mt-2">✓ {t('Code', 'Code')} "{appliedCoupon.code}" {t('toegepast', 'applied')}</p>}
          {couponError && <p className="text-xs text-destructive mt-2">{couponError}</p>}

          <div className="border-t border-border mt-3 pt-3 flex justify-between font-bold">
            <span>{t('Totaal', 'Total')}</span><span className="text-primary">€{total.toFixed(2)}</span>
          </div>
          {cart?.needsShippingAddress && !selectedRateId && (
            <p className="text-xs text-muted-foreground mt-2">{t('Vul uw verzendadres in om verzendkosten te berekenen.', 'Enter your shipping address to calculate shipping costs.')}</p>
          )}
        </div>
      </div>
    </div>
  );
}
