/* Live Operations canvas — animated 4-stage procurement pipeline.
   Tokens spawn at REQ, flow rightward through 4 stages on stable lanes,
   transforming code at each stage. Side panel logs every transition. */

const { useState, useEffect, useRef, useMemo } = React;

const FLOW_STAGES = [
  { key: 'REQ', label: ['Requisition',    'Αίτημα'],          sub: ['site asks',            'εργοτάξιο ζητά'],         color: '#5b8df0' },
  { key: 'PO',  label: ['Purchase order', 'Παραγγελία'],      sub: ['procurement approves', 'προμήθειες εγκρίνουν'],  color: '#5b8df0' },
  { key: 'GRN', label: ['Goods received', 'Παραλαβή'],        sub: ['site confirms',        'εργοτάξιο επιβεβαιώνει'], color: '#22c55e' },
  { key: 'INV', label: ['Invoice match',  'Συμφωνία τιμολ.'], sub: ['finance reconciles',   'οικονομικά κλείνουν'],   color: '#c9a227' },
];

const FLOW_SITES = [
  'Limassol Tower B', 'Nicosia Marina', 'Larnaca Logistics',
  'Paphos Resort', 'Strovolos Office', 'Engomi Hospital'
];

const FLOW_ITEMS = [
  { code: 'CS030.21', exp: 'M', name: ['Rebar B500C Ø16',    'Σίδερο B500C Ø16'],   sup: 'Sidenor' },
  { code: 'CS030.40', exp: 'M', name: ['Ready-mix C30/37',   'Σκυρόδεμα C30/37'],   sup: 'Vassiliko' },
  { code: 'CS030.40', exp: 'L', name: ['Pump crew · 2 days', 'Συνεργείο αντλίας · 2 ημ.'], sup: 'Lafarge' },
  { code: 'CS030.55', exp: 'P', name: ['Formwork panels',    'Καλούπια'],           sup: 'Doka' },
  { code: 'CS030.55', exp: 'S', name: ['Site PPE kit',       'Εξοπλισμός ΜΑΠ'],     sup: 'Safety+' },
  { code: 'CS030.21', exp: 'M', name: ['Steel mesh Q188',    'Πλέγμα Q188'],        sup: 'Sidenor' },
  { code: 'CS030.04', exp: 'L', name: ['Crane operator',     'Χειριστής γερανού'],  sup: 'Petrou Lifting' },
  { code: 'CS030.62', exp: 'P', name: ['Vibrator IREN 38mm', 'Δονητής IREN 38mm'],  sup: 'Doka' },
  { code: 'CS030.71', exp: 'M', name: ['Aluminum frames',    'Πλαίσια αλουμινίου'], sup: 'Etem' },
  { code: 'CS030.21', exp: 'M', name: ['Cement OPC 42.5',    'Τσιμέντο OPC 42.5'],  sup: 'Vassiliko' },
];

const TOTAL_DURATION = 18000;
const DOCK_RATIO = 0.30;
const LANES = 4;

const fmtMoney = (n) => '€ ' + n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });

function useLang() {
  const [lang, setLang] = useState(() => document.documentElement.lang || 'en');
  useEffect(() => {
    const mo = new MutationObserver(() => setLang(document.documentElement.lang || 'en'));
    mo.observe(document.documentElement, { attributes: true, attributeFilter: ['lang'] });
    return () => mo.disconnect();
  }, []);
  return lang;
}
const tx = (lang, en, gr) => (lang === 'gr' ? gr : en);

function OperisFlow() {
  const lang = useLang();
  const li = lang === 'gr' ? 1 : 0;

  const [tokens, setTokens] = useState(() => {
    const t0 = Date.now();
    const initial = [];
    for (let i = 0; i < LANES; i++) initial.push(makeToken(t0 - (i / LANES) * TOTAL_DURATION, i));
    return initial;
  });
  const [events, setEvents] = useState(() => seedEvents(lang));
  const [now, setNow] = useState(Date.now());
  const [paused, setPaused] = useState(false);
  const [focused, setFocused] = useState(null);
  const seenStageRef = useRef({});

  useEffect(() => {
    if (paused) return;
    let raf;
    const loop = () => {
      const t = Date.now();
      setNow(t);
      setTokens(ts => {
        let changed = false;
        const next = ts.map(tok => {
          if ((t - tok.spawn) > TOTAL_DURATION) { changed = true; return makeToken(tok.spawn + TOTAL_DURATION, tok.lane); }
          return tok;
        });
        return changed ? next : ts;
      });
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, [paused]);

  useEffect(() => {
    const newEvents = [];
    for (const tok of tokens) {
      const stage = computeStage(tok, now);
      if (stage < 0 || stage > 3) continue;
      const last = seenStageRef.current[tok.id];
      if (last === undefined || stage > last) {
        seenStageRef.current[tok.id] = stage;
        if (last !== undefined) newEvents.push(makeEvent(tok, stage, now, lang));
      }
    }
    if (newEvents.length) setEvents(es => [...newEvents.reverse(), ...es].slice(0, 14));
  }, [tokens, now, lang]);

  const stageCounts = useMemo(() => {
    const c = [0, 0, 0, 0];
    for (const t of tokens) { const s = computeStage(t, now); if (s >= 0 && s < 4) c[s]++; }
    return c;
  }, [tokens, now]);

  const kpis = [
    { l: tx(lang, 'Active sites',     'Ενεργά εργοτάξια'), v: '12', d: tx(lang, '+2 this month',     '+2 αυτόν τον μήνα') },
    { l: tx(lang, 'In-flight POs',    'POs σε εξέλιξη'),    v: String(stageCounts[1] + stageCounts[0]).padStart(2,'0'), d: tx(lang, 'across 6 suppliers', 'σε 6 προμηθευτές') },
    { l: tx(lang, 'Awaiting GRN',     'Σε αναμονή GRN'),    v: String(stageCounts[2]).padStart(2,'0'),              d: tx(lang, 'avg dock time 1.4d', 'μέσος χρόνος 1.4η') },
    { l: tx(lang, 'Reconciled (24h)', 'Συμφωνημένα (24ώ)'), v: events.filter(e => e.stage === 3).length + 18 + '',  d: tx(lang, '3-way match',        'τριμερής αντιστοίχιση') },
  ];

  return (
    <section id="how" className="relative py-24 sm:py-32 border-y border-line bg-ink2/40 overflow-hidden">
      <div className="absolute inset-0 grid-bg opacity-30 pointer-events-none"></div>
      <div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-accent/40 to-transparent"></div>

      <div className="relative max-w-7xl mx-auto px-5 sm:px-8">
        <div className="mb-10 flex items-end justify-between flex-wrap gap-4">
          <div>
            <div className="eyebrow mb-3">/02 — {tx(lang, 'Live operations', 'Ζωντανές λειτουργίες')}</div>
            <h2 className="text-3xl sm:text-5xl font-semibold tracking-tight max-w-3xl text-balance">
              {tx(lang, 'A single operating ledger, from estimate to invoice.', 'Ένα ενιαίο καθολικό λειτουργίας, από εκτίμηση σε τιμολόγιο.')}
            </h2>
            <p className="mt-4 text-muted max-w-2xl text-pretty">
              {tx(lang,
                'Every requisition, PO, delivery and invoice as one continuous flow — across every site, in real time. This is the workflow we replace your spreadsheets with.',
                'Κάθε αίτημα, PO, παράδοση και τιμολόγιο σε μια συνεχή ροή — σε κάθε εργοτάξιο, σε πραγματικό χρόνο. Αυτή είναι η ροή που αντικαθιστά τα φύλλα σας.')}
            </p>
          </div>
          <div className="flex items-center gap-2">
            <span className="inline-flex items-center gap-1.5 text-[11px] font-mono px-2.5 py-1.5 rounded-md border border-line2 bg-white/[0.02] text-muted">
              <span className="dot bg-emerald-400 pulse-soft"></span> LIVE · {tx(lang, 'simulated', 'προσομοίωση')}
            </span>
            <button onClick={() => setPaused(p => !p)} className="btn-ghost text-[12px] px-3 py-1.5 rounded-md inline-flex items-center gap-1.5 font-mono">
              {paused
                ? <><svg width="10" height="10" viewBox="0 0 12 12" fill="currentColor"><path d="M3 2v8l7-4z"/></svg>{tx(lang, 'play', 'αναπαραγωγή')}</>
                : <><svg width="10" height="10" viewBox="0 0 12 12" fill="currentColor"><rect x="3" y="2" width="2.5" height="8"/><rect x="7" y="2" width="2.5" height="8"/></svg>{tx(lang, 'pause', 'παύση')}</>
              }
            </button>
          </div>
        </div>

        <div className="grid grid-cols-2 sm:grid-cols-4 gap-px bg-line border border-line rounded-xl overflow-hidden mb-6">
          {kpis.map(k => (
            <div key={k.l} className="bg-ink px-4 py-4">
              <div className="eyebrow text-[10px]">{k.l}</div>
              <div className="mt-1.5 text-2xl font-semibold font-mono tabular-nums tracking-tight">{k.v}</div>
              <div className="text-[11px] text-muted/80 mt-0.5">{k.d}</div>
            </div>
          ))}
        </div>

        <div className="grid lg:grid-cols-[1fr_320px] gap-6">
          <div className="relative card overflow-hidden">
            <div className="grid grid-cols-4 border-b border-line">
              {FLOW_STAGES.map((s, i) => (
                <button key={s.key} onClick={() => setFocused(focused === i ? null : i)}
                  className={`text-left px-4 py-4 border-r border-line last:border-r-0 transition ${focused === i ? 'bg-accent/[0.07]' : 'hover:bg-white/[0.02]'}`}>
                  <div className="flex items-center gap-2">
                    <span className="font-mono text-[10px] text-muted">0{i+1}</span>
                    <span className="font-mono text-[10px] uppercase tracking-wider opacity-80" style={{color: s.color}}>{s.key}</span>
                    <span className="ml-auto inline-flex items-center gap-1 text-[10px] font-mono text-muted">
                      <span className="dot pulse-soft" style={{background: s.color}}></span>
                      {String(stageCounts[i]).padStart(2,'0')}
                    </span>
                  </div>
                  <div className="mt-1 text-[14px] font-medium text-chalk">{s.label[li]}</div>
                  <div className="text-[11px] text-muted">{s.sub[li]}</div>
                </button>
              ))}
            </div>

            <div className="relative h-[520px]">
              <svg className="absolute inset-0 w-full h-full pointer-events-none" preserveAspectRatio="none">
                <defs>
                  <linearGradient id="trackGrad" x1="0" y1="0" x2="1" y2="0">
                    <stop offset="0%" stopColor="rgba(91,141,240,0)"/>
                    <stop offset="10%" stopColor="rgba(91,141,240,0.35)"/>
                    <stop offset="90%" stopColor="rgba(201,162,39,0.35)"/>
                    <stop offset="100%" stopColor="rgba(201,162,39,0)"/>
                  </linearGradient>
                </defs>
                {[0.22, 0.42, 0.62, 0.82].map((y, idx) => (
                  <line key={idx} x1="2%" x2="98%" y1={`${y*100}%`} y2={`${y*100}%`} stroke="rgba(232,237,245,0.05)" strokeDasharray="3 5" />
                ))}
                {[0.25, 0.5, 0.75].map((x, idx) => (
                  <line key={idx} x1={`${x*100}%`} x2={`${x*100}%`} y1="6%" y2="94%" stroke="rgba(232,237,245,0.06)" />
                ))}
                <line x1="3%" x2="97%" y1="50%" y2="50%" stroke="url(#trackGrad)" strokeWidth="1.2"/>
              </svg>

              {tokens.map(tok => {
                const phase = (now - tok.spawn) / TOTAL_DURATION;
                if (phase < 0 || phase > 1.05) return null;
                const xRaw = 0.06 + phase * 0.88;
                const x = Math.max(0.07, Math.min(0.93, xRaw));
                const laneFrac = (tok.lane + 0.5) / LANES;
                const y = 0.16 + laneFrac * 0.70;
                const stage = Math.max(0, Math.min(3, Math.floor(phase * 4)));
                const stageProgress = (phase * 4) - stage;
                const isDocked = stageProgress > (1 - DOCK_RATIO);
                return <FlowToken key={tok.id} token={tok} stage={stage} docked={isDocked} x={x} y={y} li={li} />;
              })}

              {focused !== null && (
                <div className="absolute inset-x-4 bottom-3 z-20">
                  <div className="bg-ink/95 border border-line2 rounded-lg p-3 flex items-center gap-3 backdrop-blur">
                    <span className="font-mono text-[10px] px-2 py-0.5 rounded border" style={{ color: FLOW_STAGES[focused].color, borderColor: FLOW_STAGES[focused].color + '55' }}>
                      {FLOW_STAGES[focused].key}
                    </span>
                    <span className="text-[12px] text-muted">{FOCUS_BLURB[focused][li]}</span>
                    <button onClick={() => setFocused(null)} className="ml-auto text-muted hover:text-chalk text-[11px] font-mono">{tx(lang, 'close', 'κλείσιμο')}</button>
                  </div>
                </div>
              )}
            </div>

            <div className="px-4 py-2.5 border-t border-line flex items-center text-[10.5px] font-mono text-muted">
              <span>ops.stream → 4 {tx(lang, 'stages', 'στάδια')}</span>
              <span className="mx-2 opacity-40">·</span>
              <span>{tokens.length} {tx(lang, 'in flight', 'σε ροή')}</span>
              <span className="ml-auto flex items-center gap-3">
                <span className="flex items-center gap-1.5"><span className="dot bg-sky-400"></span>REQ</span>
                <span className="flex items-center gap-1.5"><span className="dot bg-sky-400"></span>PO</span>
                <span className="flex items-center gap-1.5"><span className="dot bg-emerald-400"></span>GRN</span>
                <span className="flex items-center gap-1.5"><span className="dot bg-amber-400"></span>INV</span>
              </span>
            </div>
          </div>

          <div className="card flex flex-col">
            <div className="px-4 py-3 border-b border-line flex items-center">
              <span className="eyebrow">{tx(lang, 'Event stream', 'Ροή γεγονότων')}</span>
              <span className="ml-auto inline-flex items-center gap-1.5 text-[10px] font-mono text-muted">
                <span className="dot bg-emerald-400 blink"></span> {events.length}
              </span>
            </div>
            <div className="flex-1 min-h-[420px] max-h-[420px] overflow-hidden relative">
              {events.length === 0 && (
                <div className="absolute inset-0 grid place-items-center text-[11px] font-mono text-muted/60">
                  {tx(lang, 'awaiting first event…', 'σε αναμονή πρώτου γεγονότος…')}
                </div>
              )}
              <ul className="text-[12px] font-mono divide-y divide-line/60">
                {events.map((e, i) => (
                  <li key={e.id + '-' + e.stage} className={`px-4 py-2.5 flex items-start gap-2 ${i === 0 ? 'bg-accent/[0.06]' : ''}`}>
                    <span className="dot mt-1.5 shrink-0" style={{ background: FLOW_STAGES[e.stage].color }}></span>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-1.5 text-[10.5px] text-muted">
                        <span className="text-chalk/90">{e.timeStr}</span>
                        <span className="opacity-50">·</span>
                        <span style={{ color: FLOW_STAGES[e.stage].color }}>{FLOW_STAGES[e.stage].key}</span>
                        <span className="opacity-50">·</span>
                        <span className="truncate">{e.site}</span>
                      </div>
                      <div className="mt-0.5 text-[11.5px] text-chalk/90 truncate">{e.message}</div>
                    </div>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function FlowToken({ token, stage, docked, x, y, li }) {
  const s = FLOW_STAGES[stage];
  const code = token.codes[stage];
  return (
    <div className="absolute select-none transition-[opacity,transform] duration-700 ease-out"
      style={{ left: `${x*100}%`, top: `${y*100}%`, transform: 'translate(-50%, -50%)', zIndex: docked ? 5 : 3 }}>
      <div className={`rounded-md border bg-ink/90 backdrop-blur px-2.5 py-1.5 shadow-lg ${docked ? 'ring-1' : ''}`}
        style={{
          borderColor: s.color + '55',
          boxShadow: docked ? `0 0 0 1px ${s.color}55, 0 6px 24px -4px ${s.color}44` : `0 4px 14px -4px rgba(0,0,0,0.6)`,
          width: 172,
        }}>
        <div className="flex items-center gap-1.5 text-[10px] font-mono">
          <span style={{ color: s.color }} className="truncate">{code}</span>
          <span className="text-muted">·</span>
          <span className="text-muted truncate">{token.item.code}</span>
          <span className="ml-auto font-mono text-[9px] px-1 rounded-sm border border-line2 text-muted shrink-0">{token.item.exp}</span>
        </div>
        <div className="mt-0.5 text-[11px] text-chalk/90 truncate">{token.item.name[li]}</div>
        <div className="mt-0.5 flex items-center justify-between text-[10px] text-muted/80 font-mono gap-2">
          <span className="truncate">{token.site}</span>
          <span className="text-chalk/80 tabular-nums shrink-0">{token.amountFmt}</span>
        </div>
      </div>
    </div>
  );
}

function makeToken(spawn, lane) {
  const item = FLOW_ITEMS[Math.floor(Math.random() * FLOW_ITEMS.length)];
  const site = FLOW_SITES[Math.floor(Math.random() * FLOW_SITES.length)];
  const n = 1000 + Math.floor(Math.random() * 8999);
  const amt = 400 + Math.floor(Math.random() * 28000) + Math.random();
  return {
    id: spawn + '-' + lane + '-' + Math.random().toString(36).slice(2, 6),
    spawn, item, site, amount: amt, amountFmt: fmtMoney(amt), lane,
    codes: ['REQ-26-' + n, 'PO-26-' + (n + 100), 'GRN-' + (7000 + (n % 999)), 'INV-' + (44000 + (n % 999))],
  };
}
function computeStage(tok, now) {
  const phase = (now - tok.spawn) / TOTAL_DURATION;
  if (phase < 0) return -1;
  if (phase > 1) return 4;
  return Math.max(0, Math.min(3, Math.floor(phase * 4)));
}
function makeEvent(tok, stage, now, lang) {
  const t = new Date(now);
  const timeStr = t.toLocaleTimeString('en-GB', { hour12: false });
  const li = lang === 'gr' ? 1 : 0;
  let msg;
  if (stage === 0)      msg = tx(lang, `Raised ${tok.codes[0]} — ${tok.item.name[0]}`,           `Δημιουργήθηκε ${tok.codes[0]} — ${tok.item.name[1]}`);
  else if (stage === 1) msg = tx(lang, `PO ${tok.codes[1]} issued to ${tok.item.sup} · ${tok.amountFmt}`, `PO ${tok.codes[1]} προς ${tok.item.sup} · ${tok.amountFmt}`);
  else if (stage === 2) msg = tx(lang, `GRN ${tok.codes[2]} signed at ${tok.site}`,              `GRN ${tok.codes[2]} υπογράφηκε στο ${tok.site}`);
  else                  msg = tx(lang, `Matched ${tok.codes[3]} — 3-way OK`,                     `Αντιστοιχίστηκε ${tok.codes[3]} — 3-way OK`);
  return { id: tok.id, stage, site: tok.site, message: msg, timeStr };
}
function seedEvents(lang) {
  const out = [];
  const t = Date.now();
  for (let i = 0; i < 5; i++) {
    const tok = makeToken(t - (i + 1) * 9000, i % LANES);
    const stage = (3 - i + 4) % 4;
    out.push(makeEvent(tok, stage, t - i * 6500, lang));
  }
  return out;
}

const FOCUS_BLURB = [
  ['Site requisitions raised on phone or tablet — activity code, exp type, quantity, photos.',
   'Αιτήματα εργοταξίου από κινητό ή tablet — κωδικός δραστηριότητας, τύπος, ποσότητα, φωτογραφίες.'],
  ['Procurement turns approved requests into POs with multi-level approvals and budget guardrails.',
   'Οι προμήθειες μετατρέπουν τα εγκεκριμένα αιτήματα σε POs με πολυεπίπεδες εγκρίσεις και όρια προϋπολογισμού.'],
  ['Goods received notes signed at the gate — partial deliveries, damage notes, photos, all linked to PO lines.',
   'Σημειώματα παραλαβής υπογεγραμμένα στην πύλη — τμηματικές παραδόσεις, ζημιές, φωτογραφίες, όλα συνδεδεμένα με τις γραμμές PO.'],
  ['Three-way match — PO ⇄ GRN ⇄ invoice — pushed to your ERP through the open REST API.',
   'Τριμερής αντιστοίχιση — PO ⇄ GRN ⇄ τιμολόγιο — αποστολή στο ERP μέσω ανοιχτού REST API.'],
];

const flowRoot = document.getElementById('flow-mount');
if (flowRoot) ReactDOM.createRoot(flowRoot).render(<OperisFlow />);
