'use client';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import PageLayout from '../../components/PageLayout';
import { useRouter } from 'next/navigation';
import { useActiveCoffees } from '../hooks/getActiveCoffees';
import { getStandardVatRate, getVatRates } from './hooks/getTaxRate';
import { subscribeAbo } from './hooks/subscribeAbo';
import useAuthStore from '../../store/authStore'
import { useShippingFees } from '../hooks/useShippingFees';
import { useAboContractTemplateHtml } from './hooks/useAboContractTemplateHtml'
import SignaturePad from './components/SignaturePad'
import { Dialog, DialogActions, DialogBody, DialogTitle } from '../../components/dialog'
import { createReferralLink } from '../../referral-management/hooks/generateReferralLink'

const COLORS = ['#1C2B4A', '#233357', '#2A3B66', '#314475', '#3A4F88', '#5B6C9A']; // dark blue palette

function extractTemplateVariables(templateHtml: string | null | undefined): string[] {
  if (!templateHtml) return []
  const vars = new Set<string>()
  const re = /\{\{\s*([a-zA-Z0-9_.-]+)\s*\}\}/g
  let match: RegExpExecArray | null
  while ((match = re.exec(templateHtml)) !== null) {
    if (match[1]) vars.add(match[1])
  }
  return Array.from(vars).sort((a, b) => a.localeCompare(b))
}

function escapeHtml(value: string): string {
  return value
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
}

function hashString(value: string): number {
  // djb2
  let hash = 5381
  for (let i = 0; i < value.length; i++) {
    hash = ((hash << 5) + hash) ^ value.charCodeAt(i)
  }
  return hash >>> 0
}

export default function SummaryPage() {
  const router = useRouter();
  const { coffees, loading, error } = useActiveCoffees();
  const user = useAuthStore(state => state.user)
  const { feeByPieceCount, loading: shippingLoading, error: shippingError } = useShippingFees();
  const { html: contractHtml, loading: contractLoading, error: contractError } = useAboContractTemplateHtml()
  const [isContractPreviewOpen, setIsContractPreviewOpen] = useState(false)
  const [contractPdfUrl, setContractPdfUrl] = useState<string>('')
  const [contractPdfKey, setContractPdfKey] = useState<string>('')
  const [contractPdfLoading, setContractPdfLoading] = useState(false)
  const [contractPdfError, setContractPdfError] = useState<string | null>(null)
  const [selections, setSelections] = useState<Record<string, number>>({});
  const [selectedPlanCapsules, setSelectedPlanCapsules] = useState<60 | 120>(120);
  const [isForSelf, setIsForSelf] = useState(true);
  const [signatureDataUrl, setSignatureDataUrl] = useState('')
  const [form, setForm] = useState({
    firstName: '',
    lastName: '',
    email: '',
    street: '',
    postalCode: '',
    city: '',
    country: 'DE',
    frequency: 'monatlich',
    startDate: '',
    recipientEmail: '',
    recipientName: '',
    recipientNotes: '',
  });
  const [showThanks, setShowThanks] = useState(false);
  const [guestMailtoHref, setGuestMailtoHref] = useState<string>('')
  const [guestInviteLink, setGuestInviteLink] = useState<string>('')
  const [confetti, setConfetti] = useState<{ left: number; delay: number; color: string }[]>([]);
  const [taxRate, setTaxRate] = useState(0.07); // minimal fallback only
  const [vatRates, setVatRates] = useState<{ code: string; rate: number | null }[]>([]);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [submitLoading, setSubmitLoading] = useState(false);
  const initialCountryRef = useRef(form.country)

  const templateVariableNames = useMemo(() => extractTemplateVariables(contractHtml), [contractHtml])
  const templateVariableNamesKey = useMemo(() => templateVariableNames.join('|'), [templateVariableNames])
  const [contractVariables, setContractVariables] = useState<Record<string, string>>({})

  useEffect(() => {
    if (!templateVariableNamesKey) return
    setContractVariables(prev => {
      let changed = false
      const next: Record<string, string> = { ...prev }
      for (const name of templateVariableNames) {
        if (next[name] === undefined) {
          next[name] = ''
          changed = true
        }
      }
      return changed ? next : prev
    })
  }, [templateVariableNamesKey, templateVariableNames])

  const populatedContractHtml = useMemo(() => {
    if (!contractHtml) return null
    // Replace placeholders with escaped user-entered values so placeholders never show.
    return contractHtml.replace(/\{\{\s*([a-zA-Z0-9_.-]+)\s*\}\}/g, (_whole, varName: string) => {
      if (varName === 'signatureImage' && !contractVariables[varName] && signatureDataUrl) {
        const safeUrl = String(signatureDataUrl)
        if (safeUrl.startsWith('data:image/')) {
          const src = escapeHtml(safeUrl)
          return `<img alt="Signature" src="${src}" style="max-width: 100%; max-height: 120px;" />`
        }
      }

      const value = contractVariables[varName] ?? ''
      return escapeHtml(String(value))
    })
  }, [contractHtml, contractVariables, signatureDataUrl])

  const contractPdfCacheKey = useMemo(() => {
    if (!populatedContractHtml) return ''
    return String(hashString(populatedContractHtml))
  }, [populatedContractHtml])

  useEffect(() => {
    // Cleanup blob URL when it changes or on unmount.
    return () => {
      if (contractPdfUrl) URL.revokeObjectURL(contractPdfUrl)
    }
  }, [contractPdfUrl])

  const closeContractPreview = () => {
    setIsContractPreviewOpen(false)
    setContractPdfError(null)
    setContractPdfLoading(false)
    setContractPdfKey('')
    if (contractPdfUrl) {
      URL.revokeObjectURL(contractPdfUrl)
      setContractPdfUrl('')
    }
  }

  const openContractPreview = async () => {
    if (!populatedContractHtml) return

    setIsContractPreviewOpen(true)
    setContractPdfError(null)

    // Reuse only if the populated HTML hasn't changed.
    if (contractPdfUrl && contractPdfKey === contractPdfCacheKey) return

    if (contractPdfUrl) {
      URL.revokeObjectURL(contractPdfUrl)
      setContractPdfUrl('')
    }

    setContractPdfLoading(true)
    try {
      const [jsPdfMod, html2canvasMod] = await Promise.all([import('jspdf'), import('html2canvas')])
      const jsPDF: any = (jsPdfMod as any).jsPDF || (jsPdfMod as any).default
      const html2canvas: any = (html2canvasMod as any).default || html2canvasMod

      const parser = new DOMParser()
      const doc = parser.parseFromString(populatedContractHtml, 'text/html')
      const styles = Array.from(doc.querySelectorAll('style'))
        .map(s => s.textContent || '')
        .join('\n')
      const bodyHtml = doc.body?.innerHTML || ''

      const wrapper = document.createElement('div')
      wrapper.style.position = 'fixed'
      wrapper.style.left = '-10000px'
      wrapper.style.top = '0'
      wrapper.style.width = '794px' // approx A4 width at 96dpi
      wrapper.style.background = '#ffffff'
      wrapper.innerHTML = `<style>${styles}</style>${bodyHtml}`
      document.body.appendChild(wrapper)

      try {
        const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' })

        const pageWidth = pdf.internal.pageSize.getWidth()
        const pageHeight = pdf.internal.pageSize.getHeight()

        const marginX = 24
        const marginTop = 24
        const marginBottom = 24

        const usableWidth = pageWidth - marginX * 2
        const usableHeight = pageHeight - marginTop - marginBottom

        const renderCanvasToPdf = (canvas: HTMLCanvasElement, pageIndex: number) => {
          const imgWidthPt = usableWidth
          const pxPerPt = canvas.width / imgWidthPt
          const sliceHeightPx = Math.max(1, Math.floor(usableHeight * pxPerPt))

          let yPx = 0
          let sliceIndex = 0
          while (yPx < canvas.height) {
            const remainingPx = canvas.height - yPx
            const currentSliceHeightPx = Math.min(sliceHeightPx, remainingPx)

            const sliceCanvas = document.createElement('canvas')
            sliceCanvas.width = canvas.width
            sliceCanvas.height = currentSliceHeightPx
            const ctx = sliceCanvas.getContext('2d')
            if (!ctx) break

            ctx.drawImage(
              canvas,
              0,
              yPx,
              canvas.width,
              currentSliceHeightPx,
              0,
              0,
              canvas.width,
              currentSliceHeightPx
            )

            const imgData = sliceCanvas.toDataURL('image/png')
            const imgHeightPt = currentSliceHeightPx / pxPerPt

            const isFirstOverall = pageIndex === 0 && sliceIndex === 0
            if (!isFirstOverall) pdf.addPage()
            pdf.addImage(imgData, 'PNG', marginX, marginTop, imgWidthPt, imgHeightPt)

            yPx += currentSliceHeightPx
            sliceIndex++
          }
        }

        // Split at explicit .pageBreak markers (in document order, even when nested)
        // to avoid cutting content between pages.
        const docRoot = wrapper.querySelector('.doc') as HTMLElement | null
        const pageRoot = docRoot ?? wrapper
        const breakEls = Array.from(pageRoot.querySelectorAll('.pageBreak')) as HTMLElement[]

        if (breakEls.length === 0) {
          const canvas: HTMLCanvasElement = await html2canvas(wrapper, {
            scale: Math.min(2, window.devicePixelRatio || 1),
            backgroundColor: '#ffffff',
            useCORS: true,
          })
          renderCanvasToPdf(canvas, 0)
        } else {
          const range = document.createRange()
          range.setStart(pageRoot, 0)

          const fragments: DocumentFragment[] = []
          for (const br of breakEls) {
            range.setEndBefore(br)
            const frag = range.cloneContents()
            if (frag.childNodes.length > 0) fragments.push(frag)
            range.setStartAfter(br)
          }
          range.setEnd(pageRoot, pageRoot.childNodes.length)
          const lastFrag = range.cloneContents()
          if (lastFrag.childNodes.length > 0) fragments.push(lastFrag)

          if (fragments.length === 0) {
            const canvas: HTMLCanvasElement = await html2canvas(wrapper, {
              scale: Math.min(2, window.devicePixelRatio || 1),
              backgroundColor: '#ffffff',
              useCORS: true,
            })
            renderCanvasToPdf(canvas, 0)
          } else {
            for (let pageIndex = 0; pageIndex < fragments.length; pageIndex++) {
              const pageWrapper = document.createElement('div')
              pageWrapper.style.position = 'fixed'
              pageWrapper.style.left = '-10000px'
              pageWrapper.style.top = '0'
              pageWrapper.style.width = '794px'
              pageWrapper.style.background = '#ffffff'
              pageWrapper.innerHTML = `<style>${styles}</style>`

              const pageDoc = document.createElement('div')
              pageDoc.className = docRoot?.className || 'doc'
              pageDoc.appendChild(fragments[pageIndex])
              pageWrapper.appendChild(pageDoc)
              document.body.appendChild(pageWrapper)
              try {
                const canvas: HTMLCanvasElement = await html2canvas(pageWrapper, {
                  scale: Math.min(2, window.devicePixelRatio || 1),
                  backgroundColor: '#ffffff',
                  useCORS: true,
                })
                renderCanvasToPdf(canvas, pageIndex)
              } finally {
                document.body.removeChild(pageWrapper)
              }
            }
          }
        }

        const blob = pdf.output('blob') as Blob
        const url = URL.createObjectURL(blob)
        setContractPdfUrl(url)
        setContractPdfKey(contractPdfCacheKey)
      } finally {
        document.body.removeChild(wrapper)
      }
    } catch (e: any) {
      setContractPdfError(e?.message || 'Failed to generate PDF preview.')
    } finally {
      setContractPdfLoading(false)
    }
  }

  useEffect(() => {
    try {
      const raw = sessionStorage.getItem('coffeeSelections');
      if (raw) setSelections(JSON.parse(raw));
      const rawPlan = sessionStorage.getItem('coffeeAboSizeCapsules');
      if (rawPlan === '60' || rawPlan === '120') {
        setSelectedPlanCapsules(Number(rawPlan) as 60 | 120);
      }
    } catch {}
  }, []);

  useEffect(() => {
    if (!showThanks) return;
    const items = Array.from({ length: 40 }).map(() => ({
      left: Math.random() * 100,
      delay: Math.random() * 0.6,
      color: COLORS[Math.floor(Math.random() * COLORS.length)],
    }));
    setConfetti(items);
  }, [showThanks]);

  const selectedEntries = useMemo(
    () =>
      Object.entries(selections)
        .map(([id, qty]) => {
          const coffee = coffees.find(c => c.id === id);
          return coffee ? { coffee, quantity: qty } : null;
        })
        .filter(Boolean) as { coffee: ReturnType<typeof useActiveCoffees>['coffees'][number]; quantity: number }[],
    [selections, coffees]
  );

  // NEW: computed packs/capsules for validation
  const totalCapsules = useMemo(
    () => selectedEntries.reduce((sum, e) => sum + e.quantity, 0),
    [selectedEntries]
  )
  const totalPacks = totalCapsules / 10
  const requiredPacks = selectedPlanCapsules / 10

  // NEW: capture logged-in user id for referral
  const rawUserId = user?.id
  const currentUserId = typeof rawUserId === 'number'
    ? rawUserId
    : (typeof rawUserId === 'string' && /^\d+$/.test(rawUserId) ? Number(rawUserId) : undefined)
  console.info('[SummaryPage] currentUserId:', currentUserId)

  // Countries list from backend VAT rates (fallback to current country if list empty)
  const countryOptions = useMemo(() => {
    const currentCode = (form.country || 'DE').toUpperCase();
    const opts = vatRates.length > 0 ? vatRates.map(r => r.code) : [currentCode]
    if (!opts.includes(currentCode)) opts.unshift(currentCode)
    console.info('[SummaryPage] countryOptions:', opts)
    return opts
  }, [vatRates, form.country]);

  // Load VAT rates list from backend and set initial taxRate
  useEffect(() => {
    let active = true;
    (async () => {
      const mountCountry = initialCountryRef.current
      console.info('[SummaryPage] Loading vat rates (mount). country:', mountCountry)
      const list = await getVatRates();
      if (!active) return;
      console.info('[SummaryPage] getVatRates result count:', list.length)
      setVatRates(list);
      const upper = mountCountry.toUpperCase();
      const match = list.find(r => r.code === upper);
      if (match?.rate != null) {
        console.info('[SummaryPage] Initial taxRate from list:', match.rate, 'country:', upper)
        setTaxRate(match.rate);
      } else {
        const rate = await getStandardVatRate(mountCountry);
        console.info('[SummaryPage] Fallback taxRate via getStandardVatRate:', rate, 'country:', upper)
        setTaxRate(rate ?? 0.07);
      }
    })();
    return () => { active = false; };
  }, []); // mount-only

  // Update taxRate when country changes (from backend only)
  useEffect(() => {
    let active = true;
    (async () => {
      const upper = form.country.toUpperCase();
      console.info('[SummaryPage] Country changed:', upper)
      const fromList = vatRates.find(r => r.code === upper)?.rate;
      if (fromList != null) {
        console.info('[SummaryPage] taxRate from existing list:', fromList)
        if (active) setTaxRate(fromList);
        return;
      }
      const rate = await getStandardVatRate(form.country);
      console.info('[SummaryPage] taxRate via getStandardVatRate:', rate)
      if (active) setTaxRate(rate ?? 0.07);
    })();
    return () => { active = false; };
  }, [form.country, vatRates]);

  const totalPrice = useMemo(
    () => selectedEntries.reduce((sum, e) => sum + (e.quantity / 10) * e.coffee.pricePer10, 0),
    [selectedEntries]
  );

  const shippingFee = useMemo(() => {
    const v = feeByPieceCount[selectedPlanCapsules];
    return Number.isFinite(Number(v)) ? Number(v) : 0;
  }, [feeByPieceCount, selectedPlanCapsules]);

  const netWithShipping = useMemo(
    () => totalPrice + shippingFee,
    [totalPrice, shippingFee]
  );

  const taxAmount = useMemo(() => totalPrice * taxRate, [totalPrice, taxRate]);
  const taxAmountWithShipping = useMemo(() => netWithShipping * taxRate, [netWithShipping, taxRate]);
  const totalWithTax = useMemo(() => netWithShipping + taxAmountWithShipping, [netWithShipping, taxAmountWithShipping]);

  const handleInput = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value }));
  };

  const handleRecipientNotes = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value }));
  };

  const fillFromLoggedInData = () => {
    if (!user) {
      setSubmitError('No logged-in user data found to fill the fields.');
      return;
    }

    const pick = (...values: any[]) => {
      for (const value of values) {
        if (typeof value === 'string' && value.trim() !== '') return value.trim();
      }
      return '';
    };

    setSubmitError(null);
    setForm(prev => ({
      ...prev,
      firstName: pick(user.firstName, user.firstname, user.givenName, user.first_name) || prev.firstName,
      lastName: pick(user.lastName, user.lastname, user.familyName, user.last_name) || prev.lastName,
      email: pick(user.email, user.mail) || prev.email,
      street: pick(user.street, user.addressStreet, user.address?.street, user.address_line_1) || prev.street,
      postalCode: pick(user.postalCode, user.zipCode, user.zip, user.addressPostalCode, user.address?.postalCode) || prev.postalCode,
      city: pick(user.city, user.addressCity, user.town, user.address?.city) || prev.city,
      country: (pick(user.country, user.countryCode, user.addressCountry, user.address?.country) || prev.country).toUpperCase(),
    }));
  };

  const requiredSelfFields: Array<keyof typeof form> = [
    'firstName',
    'lastName',
    'email',
    'street',
    'postalCode',
    'city',
    'country',
    'frequency',
  ]

  const hasRequiredSelfFields = requiredSelfFields.every(k => form[k].trim() !== '')
  const hasRequiredGiftFields = isForSelf || form.recipientEmail.trim() !== ''

  const canSubmit =
    selectedEntries.length > 0 &&
    totalPacks === requiredPacks &&
    hasRequiredSelfFields &&
    hasRequiredGiftFields;

  const backToSelection = () => router.push('/coffee-abonnements');

  const submit = async () => {
    if (!canSubmit || submitLoading) return
    // NEW: guard (defensive) — backend requires selected package size
    if (totalPacks !== requiredPacks) {
      setSubmitError(`Order must contain exactly ${requiredPacks} packs (${selectedPlanCapsules} capsules).`)
      return
    }
    if (!isForSelf && !form.recipientEmail.trim()) {
      setSubmitError('Recipient email is required when the subscription is for someone else.')
      return
    }

    setSubmitError(null)
    setSubmitLoading(true)
    try {
      const recipientEmail = form.recipientEmail.trim()
      const recipientName = form.recipientName.trim()

      const payload = {
        items: selectedEntries.map(entry => ({
          coffeeId: entry.coffee.id,
          quantity: Math.round(entry.quantity / 10), // packs
        })),
        billing_interval: 'month',
        interval_count: 1,
        is_auto_renew: true,
        is_for_self: isForSelf,
        // NEW: pass customer fields
        firstName: form.firstName.trim(),
        lastName: form.lastName.trim(),
        email: form.email.trim(),
        street: form.street.trim(),
        postalCode: form.postalCode.trim(),
        city: form.city.trim(),
        country: form.country.trim(),
        frequency: form.frequency.trim(),
        startDate: form.startDate.trim() || undefined,
        recipient_email: isForSelf ? undefined : form.recipientEmail.trim(),
        recipient_name: isForSelf ? undefined : (form.recipientName.trim() || undefined),
        recipient_notes: isForSelf ? undefined : (form.recipientNotes.trim() || undefined),
        // NEW: always include referred_by if available
        referred_by: typeof currentUserId === 'number' ? currentUserId : undefined,
      }
      console.info('[SummaryPage] subscribeAbo payload:', payload)
      // NEW: explicit JSON preview to match request body
      console.info('[SummaryPage] subscribeAbo payload JSON:', JSON.stringify(payload))
      await subscribeAbo(payload)

      // TEMP: Guest email workaround (ignore contract/PDF for mail)
      // Open an email draft to the recipient when subscription is for someone else.
      if (!isForSelf && recipientEmail) {
        try {
          // A referral token is required for /register, so we generate a 1-time referral link.
          const refRes = await createReferralLink({ expiresInDays: 7, maxUses: 1 })
          const refBody: any = (refRes as any)?.body
          const refCode =
            refBody?.data?.code ||
            refBody?.data?.token ||
            refBody?.data?.ref ||
            refBody?.code ||
            refBody?.token ||
            refBody?.ref ||
            ''

          const origin = typeof window !== 'undefined' ? window.location.origin : ''
          const guestLink = refCode
            ? (origin
              ? `${origin}/register?ref=${encodeURIComponent(String(refCode))}&guest=true`
              : `/register?ref=${encodeURIComponent(String(refCode))}&guest=true`)
            : ''

          setGuestInviteLink(guestLink)

          if (!guestLink) {
            console.warn('[SummaryPage] Guest invite: could not generate referral token/link', { refBody })
            setGuestMailtoHref('')
          } else {
            const subject = 'Profit Planet – Guest access for your coffee abonnement'
            const body =
              `Hallo${recipientName ? ` ${recipientName}` : ''},\n\n` +
              `du wurdest eingeladen, um Zugriff auf dein Kaffee-Abonnement zu erhalten.\n\n` +
              `Bitte registriere dich hier als Gast:\n${guestLink}\n\n` +
              `Liebe Grüße\nProfit Planet`

            const mailto = `mailto:${recipientEmail}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
            setGuestMailtoHref(mailto)
            try {
              window.location.href = mailto
            } catch {}
          }
        } catch (e) {
          console.warn('[SummaryPage] Guest invite: failed to create referral link', e)
          setGuestMailtoHref('')
          setGuestInviteLink('')
        }
      } else {
        setGuestMailtoHref('')
        setGuestInviteLink('')
      }

      setShowThanks(true);
      try { sessionStorage.removeItem('coffeeSelections'); } catch {}
      try { sessionStorage.removeItem('coffeeAboSizeCapsules'); } catch {}
    } catch (e: any) {
      setSubmitError(e?.message || 'Subscription could not be created.');
    } finally {
      setSubmitLoading(false);
    }
  };

  return (
    <PageLayout>
      <div className="mx-auto max-w-6xl px-4 py-10 space-y-8 bg-gradient-to-b from-white to-[#1C2B4A0D]">
        <div className="flex items-center justify-between">
          <h1 className="text-3xl font-bold tracking-tight">
            <span className="text-[#1C2B4A]">Summary & Details</span>
          </h1>
          <button
            onClick={backToSelection}
            className="rounded-md border border-gray-300 px-3 py-2 text-sm hover:bg-gray-100"
          >
            Back to selection
          </button>
        </div>

        {/* Stepper */}
        <div className="flex items-center gap-3 text-sm text-gray-600">
          <div className="flex items-center opacity-60">
            <span className="h-8 w-8 rounded-full bg-gray-200 text-gray-600 flex items-center justify-center font-semibold">1</span>
            <span className="ml-2 font-medium">Selection</span>
          </div>
          <div className="h-px flex-1 bg-gray-200" />
          <div className="flex items-center">
            <span className="h-8 w-8 rounded-full bg-[#1C2B4A] text-white flex items-center justify-center font-semibold">2</span>
            <span className="ml-2 font-medium">Summary</span>
          </div>
        </div>

        {error && (
          <div className="rounded-xl border p-6 bg-white shadow-sm">
            <p className="text-sm text-red-700 mb-4">{error}</p>
            <button
              onClick={backToSelection}
              className="rounded-md bg-[#1C2B4A] text-white px-4 py-2 font-semibold hover:bg-[#1C2B4A]/90"
            >
              Back to selection
            </button>
          </div>
        )}

        {/* submit error */}
        {submitError && (
          <div className="rounded-xl border p-6 bg-white shadow-sm">
            <p className="text-sm text-red-700">{submitError}</p>
          </div>
        )}

        {loading ? (
          <div className="rounded-xl border p-6 bg-white shadow-sm">
            <div className="h-20 rounded-md bg-gray-100 animate-pulse" />
          </div>
        ) : selectedEntries.length === 0 ? (
          <div className="rounded-xl border p-6 bg-white shadow-sm">
            <p className="text-sm text-gray-600 mb-4">No selection found.</p>
            <button
              onClick={backToSelection}
              className="rounded-md bg-[#1C2B4A] text-white px-4 py-2 font-semibold hover:bg-[#1C2B4A]/90"
            >
              Back to selection
            </button>
          </div>
        ) : (
          <div className="grid gap-8 lg:grid-cols-3">
            {/* Left: Customer data */}
            <section className="lg:col-span-2">
              <h2 className="text-xl font-semibold mb-4">1. Your details</h2>
              <div className="rounded-xl border border-[#1C2B4A]/20 bg-white/80 backdrop-blur-sm p-6 shadow-lg">
                <button
                  type="button"
                  onClick={fillFromLoggedInData}
                  className="mb-4 w-full rounded-md border border-[#1C2B4A] px-3 py-2 text-sm font-medium text-[#1C2B4A] hover:bg-[#1C2B4A]/5"
                >
                  Fill fields with logged in data
                </button>
                {/* Toggle: For myself / For someone else */}
                <div className="flex gap-2 mb-4">
                  <button
                    type="button"
                    onClick={() => setIsForSelf(true)}
                    className={`flex-1 rounded-md px-3 py-2 text-sm font-medium transition ${
                      isForSelf
                        ? 'bg-[#1C2B4A] text-white shadow'
                        : 'border border-[#1C2B4A] text-[#1C2B4A] hover:bg-[#1C2B4A]/5'
                    }`}
                  >
                    For myself
                  </button>
                  <button
                    type="button"
                    onClick={() => setIsForSelf(false)}
                    className={`flex-1 rounded-md px-3 py-2 text-sm font-medium transition ${
                      !isForSelf
                        ? 'bg-[#1C2B4A] text-white shadow'
                        : 'border border-[#1C2B4A] text-[#1C2B4A] hover:bg-[#1C2B4A]/5'
                    }`}
                  >
                    For someone else
                  </button>
                </div>
                <div className="grid gap-4 sm:grid-cols-2">
                  {/* inputs translated */}
                  <div>
                    <label className="block text-sm font-medium mb-1">First name</label>
                    <input name="firstName" value={form.firstName} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  <div>
                    <label className="block text-sm font-medium mb-1">Last name</label>
                    <input name="lastName" value={form.lastName} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  <div className="sm:col-span-2">
                    <label className="block text-sm font-medium mb-1">Email</label>
                    <input type="email" name="email" value={form.email} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  <div className="sm:col-span-2">
                    <label className="block text-sm font-medium mb-1">Street & No.</label>
                    <input name="street" value={form.street} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  <div>
                    <label className="block text-sm font-medium mb-1">ZIP</label>
                    <input name="postalCode" value={form.postalCode} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  <div>
                    <label className="block text-sm font-medium mb-1">City</label>
                    <input name="city" value={form.city} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  <div>
                    <label className="block text-sm font-medium mb-1">Country</label>
                    <select name="country" value={form.country} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]">
                      {countryOptions.map(code => (
                        <option key={code} value={code}>{code}</option>
                      ))}
                    </select>
                  </div>
                  <div>
                    <label className="block text-sm font-medium mb-1">Delivery interval</label>
                    <select name="frequency" value={form.frequency} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]">
                      <option value="monatlich">Monthly</option>
                      <option value="zweimonatlich">Every 2 months</option>
                      <option value="vierteljährlich">Quarterly</option>
                    </select>
                  </div>
                  <div>
                    <label className="block text-sm font-medium mb-1">Start date (optional)</label>
                    <input type="date" name="startDate" value={form.startDate} onChange={handleInput} className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]" />
                  </div>
                  {!isForSelf && (
                    <>
                      <div className="sm:col-span-2">
                        <label className="block text-sm font-medium mb-1">Recipient email</label>
                        <input
                          type="email"
                          name="recipientEmail"
                          value={form.recipientEmail}
                          onChange={handleInput}
                          className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]"
                        />
                      </div>
                      <div className="sm:col-span-2">
                        <label className="block text-sm font-medium mb-1">Recipient name (optional)</label>
                        <input
                          name="recipientName"
                          value={form.recipientName}
                          onChange={handleInput}
                          className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]"
                        />
                      </div>
                      <div className="sm:col-span-2">
                        <label className="block text-sm font-medium mb-1">Recipient note (optional)</label>
                        <textarea
                          name="recipientNotes"
                          value={form.recipientNotes}
                          onChange={handleRecipientNotes}
                          className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]"
                          rows={3}
                        />
                      </div>
                    </>
                  )}
                </div>

                {/* Contract preview + signature (frontend only for now) */}
                <div className="mt-6 border-t border-gray-200 pt-6">
                  <h3 className="text-base font-semibold text-gray-900 mb-2">Contract template preview (ABO)</h3>
                  <p className="text-xs text-gray-600 mb-3">
                    This is the ABO contract HTML template (populated from the fields below, frontend-only).
                  </p>

                  {contractLoading ? (
                    <div className="rounded-lg border border-gray-200 bg-gray-50 px-4 py-3 text-sm text-gray-700">
                      Loading contract preview…
                    </div>
                  ) : contractError ? (
                    <div className="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900">
                      Contract preview could not be loaded: {contractError}
                    </div>
                  ) : populatedContractHtml ? (
                    <>
                      {templateVariableNames.length > 0 && (
                        <div className="mb-4 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3">
                          <div className="text-sm font-semibold text-gray-900 mb-2">Contract variables</div>
                          <div className="grid gap-4">
                            {templateVariableNames.map(varName => (
                              <div key={varName}>
                                <label className="block text-xs font-medium mb-1 text-gray-700">{varName}</label>
                                <input
                                  value={contractVariables[varName] ?? ''}
                                  onChange={e =>
                                    setContractVariables(prev => ({ ...prev, [varName]: e.target.value }))
                                  }
                                  className="w-full rounded border px-3 py-2 bg-white border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#1C2B4A]"
                                />
                              </div>
                            ))}
                          </div>
                        </div>
                      )}
                      <button
                        type="button"
                        onClick={openContractPreview}
                        className="inline-flex items-center justify-center rounded-md bg-[#1C2B4A] text-white px-4 py-2 text-sm font-semibold hover:bg-[#1C2B4A]/90"
                      >
                        Open preview
                      </button>
                    </>
                  ) : (
                    <div className="rounded-lg border border-gray-200 bg-gray-50 px-4 py-3 text-sm text-gray-700">
                      Contract template is not available.
                    </div>
                  )}

                  <div className="mt-4">
                    <SignaturePad value={signatureDataUrl} onChange={setSignatureDataUrl} />
                  </div>
                </div>

                <Dialog open={isContractPreviewOpen} onClose={closeContractPreview} size="5xl">
                  <DialogTitle>ABO contract preview (PDF)</DialogTitle>
                  <DialogBody>
                    {contractPdfError ? (
                      <div className="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900">
                        PDF preview could not be generated: {contractPdfError}
                      </div>
                    ) : contractPdfLoading ? (
                      <div className="rounded-lg border border-gray-200 bg-gray-50 px-4 py-3 text-sm text-gray-700">
                        Generating PDF preview…
                      </div>
                    ) : contractPdfUrl ? (
                      <div className="rounded-lg border border-gray-300 bg-white overflow-hidden">
                        <iframe
                          title="ABO Contract PDF Preview"
                          className="w-full h-[75vh]"
                          src={contractPdfUrl}
                        />
                      </div>
                    ) : (
                      <div className="rounded-lg border border-gray-200 bg-gray-50 px-4 py-3 text-sm text-gray-700">
                        No PDF preview available.
                      </div>
                    )}
                  </DialogBody>
                  <DialogActions>
                    <button
                      type="button"
                      onClick={closeContractPreview}
                      className="rounded-md border border-gray-300 px-4 py-2 text-sm font-semibold hover:bg-gray-50"
                    >
                      Close
                    </button>
                  </DialogActions>
                </Dialog>

                <button
                  onClick={submit}
                  disabled={!canSubmit || submitLoading}
                  className={`group w-full mt-6 rounded-lg px-4 py-3 font-semibold transition inline-flex items-center justify-center ${
                    canSubmit && !submitLoading ? 'bg-[#1C2B4A] text-white hover:bg-[#1C2B4A]/90 shadow-md hover:shadow-lg' : 'bg-gray-200 text-gray-600 cursor-not-allowed'
                  }`}
                >
                  {submitLoading ? 'Creating…' : 'Complete subscription'}
                  <svg className={`ml-2 h-5 w-5 transition-transform ${canSubmit ? 'group-hover:translate-x-0.5' : ''}`} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                    <path fillRule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l5.999 6a1 1 0 010 1.414l-6 6a1 1 0 11-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clipRule="evenodd" />
                  </svg>
                </button>
                {!canSubmit && (
                  <p className="text-xs text-gray-500 mt-2">
                    {isForSelf
                      ? 'Please select coffees and fill all required buyer fields.'
                      : 'Please select coffees and fill all required buyer fields plus recipient email.'}
                  </p>
                )}
              </div>
            </section>

            {/* Right: Order summary */}
            <section className="lg:col-span-1">
              <h2 className="text-xl font-semibold mb-4">2. Your selection</h2>
              <div className="rounded-xl border border-[#1C2B4A]/20 bg-white/80 backdrop-blur-sm p-6 shadow-lg lg:sticky lg:top-6">
                {selectedEntries.map(entry => (
                  <div key={entry.coffee.id} className="flex justify-between text-sm border-b last:border-b-0 pb-2 last:pb-0">
                    <div className="flex flex-col">
                      <span className="font-medium">{entry.coffee.name}</span>
                      <span className="text-xs text-gray-500">
                        {entry.quantity} pcs • <span className="inline-flex items-center font-semibold text-[#1C2B4A]">€{entry.coffee.pricePer10}/10</span>
                      </span>
                    </div>
                    <div className="text-right font-semibold">€{((entry.quantity / 10) * entry.coffee.pricePer10).toFixed(2)}</div>
                  </div>
                ))}

                {/* Shipping */}
                <div className="flex justify-between text-sm border-b pb-2">
                  <span className="text-sm font-medium">Shipping</span>
                  <span className="text-sm font-semibold">
                    {shippingLoading ? (
                      'Loading…'
                    ) : shippingFee === 0 ? (
                      'FREE SHIPPING'
                    ) : (
                      `€${shippingFee.toFixed(2)}`
                    )}
                  </span>
                </div>

                {shippingError && (
                  <div className="mt-2 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800">
                    Shipping fees could not be loaded: {shippingError}
                  </div>
                )}

                <div className="flex justify-between pt-2 border-t">
                  <span className="text-sm font-semibold">Total (net)</span>
                  <span className="text-lg font-extrabold tracking-tight text-[#1C2B4A]">€{netWithShipping.toFixed(2)}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-sm">Tax ({(taxRate * 100).toFixed(1)}%)</span>
                  <span className="text-sm font-medium">€{taxAmountWithShipping.toFixed(2)}</span>
                </div>
                <div className="flex items-center justify-between">
                  <span className="text-sm font-semibold">Total incl. tax</span>
                  <span className="text-xl font-extrabold text-[#1C2B4A]">€{totalWithTax.toFixed(2)}</span>
                </div>
                {/* Validation summary (refined design) */}
                <div className="mt-2 text-xs text-gray-700">
                  Selected: {totalCapsules} capsules ({totalPacks} packs of 10). Target: {selectedPlanCapsules} capsules ({requiredPacks} packs).
                  {totalPacks !== requiredPacks && (
                    <span className="ml-2 inline-flex items-center rounded-md bg-red-50 text-red-700 px-2 py-1 border border-red-200">
                      Exactly {requiredPacks} packs ({selectedPlanCapsules} capsules) are required.
                    </span>
                  )}
                </div>
              </div>
            </section>
          </div>
        )}
      </div>

      {/* Thank you overlay */}
      {showThanks && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
          <div className="relative mx-4 w-full max-w-md rounded-2xl bg-white p-8 text-center shadow-2xl">
            <div className="pointer-events-none absolute inset-0 overflow-hidden">
              {confetti.map((c, i) => (
                <span key={i} className="confetti" style={{ left: `${c.left}%`, animationDelay: `${c.delay}s`, background: c.color }} />
              ))}
            </div>

            <div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-[#1C2B4A]/10 text-[#1C2B4A] pop">
              <svg viewBox="0 0 24 24" className="h-9 w-9" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M20 6L9 17l-5-5" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            <h3 className="text-2xl font-bold">Thanks for your subscription!</h3>
            <p className="mt-1 text-sm text-gray-600">
              {isForSelf
                ? 'Subscription created.'
                : guestMailtoHref
                  ? 'Subscription created. Email draft opened for the guest invite.'
                  : 'Subscription created. Guest invite email could not be prepared.'}
            </p>

            {!isForSelf && guestMailtoHref && (
              <div className="mt-4">
                <a
                  href={guestMailtoHref}
                  className="inline-flex items-center justify-center rounded-lg bg-[#1C2B4A] text-white px-4 py-2 font-semibold hover:bg-[#1C2B4A]/90"
                >
                  Open guest email draft again
                </a>
              </div>
            )}

            {!isForSelf && guestInviteLink && (
              <div className="mt-3 text-xs text-gray-600 break-words">
                Guest registration link: <a className="underline" href={guestInviteLink} target="_blank" rel="noreferrer">{guestInviteLink}</a>
              </div>
            )}

            <div className="mt-6 grid gap-3 sm:grid-cols-2">
              <button onClick={() => { setShowThanks(false); backToSelection(); }} className="rounded-lg bg-[#1C2B4A] text-white px-4 py-2 font-semibold hover:bg-[#1C2B4A]/90">
                Back to selection
              </button>
              <button onClick={() => setShowThanks(false)} className="rounded-lg border border-gray-300 px-4 py-2 font-semibold hover:bg-gray-50">
                Close
              </button>
            </div>

            <style jsx>{`
              .confetti {
                position: absolute;
                top: -10%;
                width: 8px;
                height: 12px;
                border-radius: 2px;
                opacity: 0.9;
                animation: fall 1.8s linear forwards;
              }
              @keyframes fall {
                0%   { transform: translateY(0) rotate(0deg); }
                100% { transform: translateY(110vh) rotate(720deg); }
              }
              .pop {
                animation: pop 450ms ease-out forwards;
              }
              @keyframes pop {
                0%   { transform: scale(0.6); opacity: 0; }
                60%  { transform: scale(1.08); opacity: 1; }
                100% { transform: scale(1); }
              }
            `}</style>
          </div>
        </div>
      )}
    </PageLayout>
  );
}
