// Tracking screen — looks up a submission and renders the real timeline.

const STATUSES = {
  submitted:             { label: 'Submitted',   tone: 'slate', description: 'We received your claim and will pass it to the distributor.', Icon: IconPackage },
  submitting:            { label: 'Sending',     tone: 'slate', description: 'Forwarding your claim to the distributor.', Icon: IconPackage },
  upstream_pending:      { label: 'Forwarded',   tone: 'blue',  description: 'Distributor has your claim and is queuing it for review.', Icon: IconClock },
  upstream_under_review: { label: 'Under review', tone: 'blue', description: 'The distributor is checking your submission.', Icon: IconClock },
  approved:              { label: 'Approved',    tone: 'green', description: 'Your bundle has been approved and is being prepared.', Icon: IconCheck },
  rejected:              { label: 'Rejected',    tone: 'red',   description: 'Something wasn\'t accepted. See the timeline below for details.', Icon: IconAlertCircle },
  failed:                { label: 'Needs attention', tone: 'red', description: 'We hit a problem forwarding your claim. Our team will retry.', Icon: IconAlertCircle },
  draft:                 { label: 'Draft',       tone: 'slate', description: 'Claim not yet submitted.', Icon: IconClock },
};

const TONE = {
  slate: { bg: 'bg-slate-100', text: 'text-slate-700', ring: 'ring-slate-200' },
  blue:  { bg: 'bg-blue-50',   text: 'text-blue-700',   ring: 'ring-blue-200' },
  green: { bg: 'bg-green-50',  text: 'text-green-700',  ring: 'ring-green-200' },
  red:   { bg: 'bg-red-50',    text: 'text-red-700',    ring: 'ring-red-200' },
};

const EVENT_COPY = {
  created:                  { bold: 'We received your claim',                                           type: 'done' },
  file_uploaded:            { bold: 'Files uploaded',                                                   type: 'info' },
  upstream_manual_submit:   { bold: 'Forwarded to the distributor (Pali Pali Trading Sdn Bhd)',         type: 'info' },
  upstream_sent:            { bold: 'Forwarded to the distributor (Pali Pali Trading Sdn Bhd)',        type: 'info' },
  upstream_ack:             { bold: 'Distributor acknowledged your claim',                              type: 'done' },
  upstream_status:          { bold: 'Distributor updated your claim status',                            type: 'active' },
  admin_note:               { bold: 'Note from Smith3D',                                                 type: 'info' },
  admin_status_change:      { bold: 'Status updated',                                                    type: 'active' },
  error:                    { bold: 'We hit a problem forwarding your claim',                            type: 'error' },
};

function TrackingScreen({ onBack, initialRef }) {
  const [ref, setRef] = React.useState(initialRef || '');
  const [submission, setSubmission] = React.useState(null);
  const [events, setEvents] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState('');
  const [lightbox, setLightbox] = React.useState(null);

  const load = React.useCallback(async (r) => {
    const clean = String(r || '').trim().toUpperCase();
    if (!clean) return;
    setLoading(true); setError('');
    try {
      const res = await fetch(`/api/submissions/${encodeURIComponent(clean)}`);
      if (res.status === 404) {
        setError('We couldn\'t find that reference. Double-check and try again.');
        setSubmission(null); setEvents([]);
        return;
      }
      if (!res.ok) throw new Error('fetch failed');
      const data = await res.json();
      setSubmission(data.submission);
      setEvents(data.events || []);
      // Pin the ref into the URL so it lands in browser history — makes the
      // tracking page shareable and easy to return to from history / bookmarks.
      const target = `/track/${encodeURIComponent(data.submission.smith3d_ref)}`;
      if (window.location.pathname !== target) {
        window.history.pushState({}, '', target);
      }
    } catch (e) {
      setError('Something went wrong. Please try again in a moment.');
    } finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => {
    if (initialRef) { setRef(initialRef); load(initialRef); }
  }, [initialRef, load]);

  // Keep the view in sync with the URL on back/forward, since load() pushes
  // a new entry whenever a ref resolves. Without this, hitting Back after a
  // lookup changes the URL but not the screen.
  React.useEffect(() => {
    const onPop = () => {
      const parts = window.location.pathname.split('/').filter(Boolean);
      if (parts[0] !== 'track') return;
      const urlRef = parts[1] ? decodeURIComponent(parts[1]).toUpperCase() : null;
      const curRef = submission?.smith3d_ref || null;
      if (!urlRef && curRef) {
        setSubmission(null); setEvents([]); setError('');
      } else if (urlRef && urlRef !== curRef) {
        setRef(urlRef);
        load(urlRef);
      }
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, [submission, load]);

  if (!submission) {
    return (
      <LookupView
        refVal={ref}
        setRefVal={setRef}
        loading={loading}
        error={error}
        onSubmit={(val) => load(val || ref)}
        onBack={onBack}
      />
    );
  }

  const st = STATUSES[submission.status] || STATUSES.submitted;
  const tone = TONE[st.tone];
  const StatusIcon = st.Icon;

  const clearView = () => {
    setSubmission(null); setEvents([]); setError('');
    if (window.location.pathname !== '/track') {
      window.history.pushState({}, '', '/track');
    }
  };

  return (
    <div className="min-h-full bg-neutral-50">
      <div className="max-w-[520px] mx-auto px-4 py-4 pb-10 space-y-3">
        <div className="flex items-center gap-2 pb-1">
          <button onClick={onBack} className="w-9 h-9 rounded-lg hover:bg-neutral-100 grid place-items-center text-neutral-600">
            <IconChevronLeft size={18}/>
          </button>
          <div>
            <div className="text-[18px] font-bold tracking-tight text-neutral-900">Your claim</div>
            <div className="text-[12px] text-neutral-500 font-mono">{submission.smith3d_ref}</div>
          </div>
          <button onClick={clearView}
            className="ml-auto text-[12px] text-neutral-500 hover:text-neutral-800 px-2 py-1 rounded">
            Look up another
          </button>
        </div>

        <div className="rounded-xl border border-neutral-200 bg-white overflow-hidden">
          <div className={`px-5 py-5 ${tone.bg}`}>
            <div className="flex items-center gap-3">
              <div className={`w-12 h-12 rounded-full bg-white ring-4 ${tone.ring} grid place-items-center shrink-0`}>
                <StatusIcon size={22} className={tone.text}/>
              </div>
              <div className="flex-1 min-w-0">
                <div className={`text-[11px] font-medium uppercase tracking-wider ${tone.text} opacity-80`}>Status</div>
                <div className="text-[20px] font-bold tracking-tight text-neutral-900 leading-tight">{st.label}</div>
              </div>
            </div>
            <div className="text-[13px] text-neutral-700 mt-3 leading-snug">
              {submission.status_note || st.description}
            </div>
          </div>
          <div className="px-5 py-3 flex items-center gap-3 text-[12.5px] text-neutral-600 bg-white border-t border-neutral-100">
            <div className="w-8 h-8 rounded-md bg-gradient-to-br from-orange-100 to-orange-50 grid place-items-center border border-orange-100 shrink-0">
              <FilamentIllustration size={24}/>
            </div>
            <div className="flex-1 min-w-0">
              <div className="text-[13px] font-medium text-neutral-800 truncate">
                {submission.product_series || 'Bambu Lab X2D Combo'} — {submission.gift_choice || 'Filament bundle'}
              </div>
              <div className="text-[11.5px] text-neutral-500">
                Submitted {formatDateTime(submission.created_at)} · RM 354 value
              </div>
            </div>
          </div>
        </div>

        <Card>
          <div className="px-5 pt-5 pb-1 flex items-center justify-between">
            <div className="text-[14px] font-semibold tracking-tight text-neutral-900">Activity</div>
            <div className="text-[11px] text-neutral-400">Most recent first</div>
          </div>
          <div className="px-5 pb-5 pt-3">
            <Timeline events={events}/>
          </div>
        </Card>

        <Card>
          <div className="px-5 pt-5 pb-3 text-[14px] font-semibold tracking-tight text-neutral-900">Submission details</div>
          <div className="px-5 pb-5 space-y-3">
            <SummaryRow label="Serial number" value={submission.serial_number} mono/>
            <SummaryRow label="Purchase date" value={formatDate(submission.purchase_date)}/>
            <SummaryRow label="Purchased from" value={submission.purchase_source}/>
            {submission.upstream_ref && (
              submission.upstream_tracking_url ? (
                <div className="flex items-center justify-between gap-3 text-[13px]">
                  <span className="text-neutral-500">Distributor ref</span>
                  <a href={submission.upstream_tracking_url} target="_blank" rel="noopener noreferrer"
                    className="inline-flex items-center gap-1 text-[var(--s3-orange)] font-mono text-[12px] hover:underline underline-offset-2">
                    {submission.upstream_ref}
                    <IconExternalLink size={12}/>
                  </a>
                </div>
              ) : <SummaryRow label="Distributor ref" value={submission.upstream_ref} mono/>
            )}
            {submission.upstream_status && <SummaryRow label="Distributor status" value={submission.upstream_status}/>}

            <div>
              <div className="text-[11px] font-medium text-neutral-500 uppercase tracking-wider mb-2">Photos</div>
              <div className="grid grid-cols-2 gap-2">
                <PhotoThumb label="SN sticker" photos={submission.sn_photos || []} subRef={submission.smith3d_ref}
                  onOpen={() => setLightbox({ kind: 'sn', photos: submission.sn_photos || [] })}/>
                <PhotoThumb label="Invoice" photos={submission.invoice_photos || []} subRef={submission.smith3d_ref}
                  onOpen={() => setLightbox({ kind: 'inv', photos: submission.invoice_photos || [] })}/>
              </div>
            </div>

            <div className="pt-3 border-t border-neutral-100">
              <div className="text-[11px] font-medium text-neutral-500 uppercase tracking-wider mb-1.5">Ship to</div>
              <div className="text-[13.5px] text-neutral-800 leading-relaxed">
                {submission.full_name}<br/>
                {submission.addr_line1}<br/>
                {submission.addr_line2 && <>{submission.addr_line2}<br/></>}
                {submission.postcode} {submission.city}, {submission.country}
              </div>
              <div className="text-[12px] text-neutral-500 mt-2 flex flex-wrap items-center gap-x-3 gap-y-1">
                <span className="flex items-center gap-1.5"><IconPhone size={12}/> {submission.contact_number}</span>
                <span className="flex items-center gap-1.5"><IconMail size={12}/> {submission.email}</span>
              </div>
            </div>
          </div>
        </Card>

        <div className="px-4 py-3 text-[11.5px] text-neutral-500 leading-relaxed text-center">
          We check with the distributor for updates periodically. If your status hasn't moved in 14 days, reply to the confirmation email and we'll chase them.
        </div>
      </div>

      {lightbox && (
        <PhotoLightbox subRef={submission.smith3d_ref} photos={lightbox.photos} onClose={() => setLightbox(null)}/>
      )}
    </div>
  );
}

function fileUrl(subRef, key) {
  return `/api/submissions/${encodeURIComponent(subRef)}/file/${encodeURIComponent(key)}`;
}

function PhotoThumb({ label, photos, subRef, onOpen }) {
  const first = photos?.[0];
  const count = photos?.length || 0;
  const isImage = first && String(first.mime || '').startsWith('image/');
  return (
    <button onClick={onOpen} disabled={!count}
      className="group rounded-lg overflow-hidden border border-neutral-200 bg-neutral-100 aspect-[4/3] relative disabled:opacity-60 disabled:cursor-not-allowed">
      {first ? (
        isImage ? (
          <img src={fileUrl(subRef, first.key)} alt={label}
            className="w-full h-full object-cover"
            loading="lazy"/>
        ) : (
          <div className="w-full h-full bg-gradient-to-br from-neutral-50 to-neutral-200 grid place-items-center">
            <div className="text-center">
              <IconFileText size={32} className="text-neutral-400 mx-auto"/>
              <div className="text-[10px] text-neutral-500 mt-1 uppercase font-semibold tracking-wide">
                {String(first.mime || '').includes('pdf') ? 'PDF' : 'FILE'}
              </div>
            </div>
          </div>
        )
      ) : (
        <div className="w-full h-full bg-gradient-to-br from-neutral-50 to-neutral-200 grid place-items-center">
          <IconCamera size={28} className="text-neutral-400"/>
        </div>
      )}
      <div className="absolute inset-x-0 bottom-0 p-1.5 bg-gradient-to-t from-black/60 to-transparent text-white text-[10.5px]">
        {label}{count > 1 ? ` · ${count}` : ''}
      </div>
    </button>
  );
}

// Full-screen viewer for user's own uploaded photos. Swipe / arrow-key
// through multiple; PDFs open in a new tab (most mobile browsers can't
// render PDF inside an <iframe> inside a fullscreen overlay reliably).
function PhotoLightbox({ subRef, photos, onClose }) {
  const [idx, setIdx] = React.useState(0);
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowLeft') setIdx(i => Math.max(0, i - 1));
      if (e.key === 'ArrowRight') setIdx(i => Math.min(photos.length - 1, i + 1));
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [photos.length, onClose]);

  if (!photos?.length) return null;
  const cur = photos[idx];
  const isImage = String(cur.mime || '').startsWith('image/');
  const url = fileUrl(subRef, cur.key);

  return (
    <div className="fixed inset-0 z-50 bg-black/95 flex items-center justify-center"
      onClick={onClose}>
      <div className="absolute top-3 left-3 right-3 flex items-center gap-2 text-white text-[13px]">
        <div className="px-2 py-1 rounded bg-white/10 backdrop-blur font-mono truncate max-w-[60%]">
          {cur.name || cur.key}
        </div>
        {photos.length > 1 && (
          <div className="px-2 py-1 rounded bg-white/10 backdrop-blur">
            {idx + 1} / {photos.length}
          </div>
        )}
        <a href={url} target="_blank" rel="noopener noreferrer"
          onClick={e => e.stopPropagation()}
          className="ml-auto px-2.5 py-1 rounded bg-white/10 backdrop-blur hover:bg-white/20 inline-flex items-center gap-1 text-[12px]">
          Open
          <IconExternalLink size={12}/>
        </a>
        <button onClick={(e) => { e.stopPropagation(); onClose(); }}
          className="w-9 h-9 rounded-full bg-white/10 backdrop-blur grid place-items-center hover:bg-white/20">
          <IconX size={18}/>
        </button>
      </div>

      <div onClick={e => e.stopPropagation()} className="max-w-full max-h-full p-4 flex items-center justify-center">
        {isImage ? (
          <img src={url} alt={cur.name || cur.key}
            className="max-w-full max-h-[85vh] object-contain rounded"/>
        ) : (
          <div className="bg-white rounded-lg p-8 max-w-sm text-center">
            <IconFileText size={48} className="text-neutral-400 mx-auto"/>
            <div className="mt-3 font-medium text-neutral-800 break-all">{cur.name || cur.key}</div>
            <div className="text-[12.5px] text-neutral-500 mt-1">
              {String(cur.mime || '').includes('pdf') ? 'PDF document' : 'File'}
            </div>
            <a href={url} target="_blank" rel="noopener noreferrer"
              className="mt-4 inline-flex items-center gap-1.5 px-4 h-10 rounded-full bg-[var(--s3-orange)] text-white text-[13px] font-semibold">
              Open in new tab
              <IconExternalLink size={13}/>
            </a>
          </div>
        )}
      </div>

      {photos.length > 1 && (
        <>
          <button onClick={(e) => { e.stopPropagation(); setIdx(i => Math.max(0, i - 1)); }}
            disabled={idx === 0}
            className="absolute left-3 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-white/10 backdrop-blur text-white grid place-items-center hover:bg-white/20 disabled:opacity-30">
            <IconChevronLeft size={20}/>
          </button>
          <button onClick={(e) => { e.stopPropagation(); setIdx(i => Math.min(photos.length - 1, i + 1)); }}
            disabled={idx === photos.length - 1}
            className="absolute right-3 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-white/10 backdrop-blur text-white grid place-items-center hover:bg-white/20 disabled:opacity-30">
            <IconChevronRight size={20}/>
          </button>
        </>
      )}
    </div>
  );
}

function Timeline({ events }) {
  if (!events?.length) return <div className="text-[13px] text-neutral-500">No activity yet.</div>;
  return (
    <div className="relative">
      {events.map((e, i) => {
        const last = i === events.length - 1;
        const copy = EVENT_COPY[e.kind] || { bold: e.kind, type: 'info' };
        const typeTone = {
          active:  { dot: 'bg-blue-500 ring-blue-100',   pulse: true },
          success: { dot: 'bg-green-500 ring-green-100', pulse: false },
          error:   { dot: 'bg-red-500 ring-red-100',     pulse: false },
          done:    { dot: 'bg-neutral-300 ring-neutral-100', pulse: false },
          info:    { dot: 'bg-neutral-400 ring-neutral-100', pulse: false },
        }[copy.type] || { dot: 'bg-neutral-300 ring-neutral-100', pulse: false };
        const dt = new Date(e.created_at);
        return (
          <div key={i} className="flex gap-3 pb-5 last:pb-0">
            <div className="relative flex flex-col items-center shrink-0">
              <div className={`w-3 h-3 rounded-full ring-[3px] relative ${typeTone.dot} ${typeTone.pulse ? 'animate-pulse' : ''}`}/>
              {!last && <div className="flex-1 w-px bg-neutral-200 mt-1"/>}
            </div>
            <div className="flex-1 min-w-0 -mt-0.5">
              <div className="flex items-baseline gap-2 flex-wrap">
                <div className="text-[11.5px] font-medium text-neutral-500 tabular-nums">
                  {dt.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })} · {dt.toLocaleTimeString('en-GB', { hour: 'numeric', minute: '2-digit', hour12: true }).toLowerCase()}
                </div>
              </div>
              <div className="text-[13.5px] text-neutral-900 leading-snug mt-0.5">{e.message || copy.bold}</div>
              {e.payload?.upstream_ref && (
                <div className="text-[12.5px] text-neutral-500 mt-0.5 leading-snug font-mono">ref {e.payload.upstream_ref}</div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function SummaryRow({ label, value, mono }) {
  return (
    <div className="flex items-center justify-between gap-3 text-[13px]">
      <span className="text-neutral-500">{label}</span>
      <span className={`text-neutral-900 text-right ${mono ? 'font-mono text-[12px]' : ''}`}>{value || '—'}</span>
    </div>
  );
}

function LookupView({ refVal, setRefVal, onSubmit, loading, error, onBack }) {
  const [scannerOpen, setScannerOpen] = React.useState(false);
  const [sn, setSn] = React.useState('');

  const refValid = /^S3D-[A-Z0-9]{6}$/i.test(refVal);
  const snValid = sn.replace(/\s/g, '').length >= 12;

  const go = async (e) => {
    e?.preventDefault();
    if (refValid) { onSubmit(refVal); return; }
    if (snValid) {
      try {
        const r = await fetch(`/api/submissions/by-serial/${encodeURIComponent(sn.toUpperCase())}`);
        if (r.ok) {
          const d = await r.json();
          setRefVal(d.smith3d_ref);
          onSubmit(d.smith3d_ref);
          return;
        }
      } catch (_e) { /* fall through to error */ }
      onSubmit(refVal);
    }
  };

  return (
    <div className="min-h-full bg-neutral-50">
      <div className="max-w-[520px] mx-auto px-4 py-4 pb-10">
        <div className="flex items-center gap-2 pb-3">
          <button onClick={onBack} className="w-9 h-9 rounded-lg hover:bg-neutral-100 grid place-items-center text-neutral-600">
            <IconChevronLeft size={18}/>
          </button>
          <div className="text-[18px] font-bold tracking-tight text-neutral-900">Track a claim</div>
        </div>
        <Card>
          <div className="px-5 py-5">
            <div className="flex items-center gap-2.5">
              <div className="w-8 h-8 rounded-full bg-orange-50 grid place-items-center shrink-0">
                <IconSearch size={15} className="text-[var(--s3-orange)]"/>
              </div>
              <h2 className="text-[16px] font-semibold tracking-tight text-neutral-900">Find your submission</h2>
            </div>
            <form onSubmit={go} className="mt-4 space-y-4">
              <div>
                <Label htmlFor="ref">Reference number</Label>
                <Input id="ref" mono placeholder="S3D-XXXXXX" value={refVal}
                  invalid={!!error && !refValid && !snValid}
                  autoCapitalize="characters" autoCorrect="off" spellCheck={false}
                  onChange={e => setRefVal(e.target.value.toUpperCase())}/>
                <div className="text-[11.5px] text-neutral-400 mt-1.5">
                  We emailed this on submission. Starts with <span className="font-mono">S3D-</span>.
                </div>
              </div>
              <div className="relative flex items-center py-1" aria-hidden>
                <div className="flex-1 h-px bg-neutral-200"/>
                <span className="mx-3 text-[10.5px] font-semibold uppercase tracking-[0.14em] text-neutral-400">or</span>
                <div className="flex-1 h-px bg-neutral-200"/>
              </div>
              <div>
                <Label htmlFor="sn-track">Printer serial number</Label>
                <div className="flex gap-2">
                  <div className="flex-1">
                    <Input id="sn-track" mono placeholder="01P00C4A..." value={sn}
                      invalid={!!error && !refValid && !snValid}
                      autoCapitalize="characters" autoCorrect="off" spellCheck={false}
                      onChange={e => setSn(e.target.value.toUpperCase())}/>
                  </div>
                  <button type="button" onClick={() => setScannerOpen(true)}
                    className="shrink-0 h-11 px-3 rounded-lg bg-neutral-900 text-white text-[12.5px] font-semibold flex items-center gap-1.5 active:scale-95 transition">
                    <IconCamera size={15}/> Scan
                  </button>
                </div>
              </div>
              {error && <div className="text-[12px] text-red-600">{error}</div>}
              <Button type="submit" variant="primary" size="lg" className="w-full" disabled={loading || (!refValid && !snValid)}>
                {loading ? 'Looking up…' : <>Track claim <IconChevronRight size={18}/></>}
              </Button>
            </form>
            <div className="mt-4 pt-4 border-t border-neutral-100 space-y-2">
              <div className="text-[12.5px] text-neutral-600 leading-relaxed">
                Lost both? Reach out with the address on your invoice and we'll find your claim.
              </div>
              <ContactLinks/>
            </div>
          </div>
        </Card>
      </div>
      <ScannerModal open={scannerOpen}
        onClose={() => setScannerOpen(false)}
        onDetect={(v) => { setSn(v); setScannerOpen(false); }}/>
    </div>
  );
}

function formatDateTime(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  return d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}

Object.assign(window, { TrackingScreen });
