// Animated WhatsApp-Chat Demos.
//
// Drei Skripte:
//   HERO_SCRIPT       — Stamm-Kunde im READY-State zeigt die „Idee egal —
//                       sag einfach was du heute gemacht hast"-UX: ein vage
//                       gehaltener Wunsch ("Erstelle mir ein Werbevideo"),
//                       Basti wählt einen Reel-Angle aus den Optionen,
//                       Kling rendert, das fertige Reel wird geliefert.
//                       Spiegelt das Verhalten von ``content_workflow``
//                       wenn der Customer-Prompt keinen Topic-Hint enthält.
//   ONBOARDING_SCRIPT — Erstkunde, Bot crawlt die Website, extrahiert
//                       Logo/Tonalität, liefert das erste Beispiel-Reel.
//   REVISION_SCRIPT   — „Text ändern"-Feature: Kling-Video bleibt, nur
//                       Overlay-Text wird neu komponiert.
//
// ChatDemo ist parametrisiert: pass `script={...}` um zwischen ihnen zu
// wechseln.
const { useState, useEffect, useRef } = React;

const HERO_SCRIPT = [
  // Erste Runde: Customer hat keine konkrete Idee → fragt nach generischem
  // Video → Basti würfelt den Angle. Anna liefert Caption + Hashtags + Slot.
  // Spiegelt das echte content_workflow-Verhalten wenn Vera den Prompt mit
  // leerem ``topic`` an Basti weitergibt.
  { side: "out", text: "Erstelle mir ein Werbevideo", delay: 1400 },
  { side: "in",  typing: 1200 },
  { side: "in",  text: "Klar! Ich übernehme den Vorschlag — *E-Check am Verteiler* passt grad gut zu deiner Marke.\nDein Kontingent diesen Monat: 8 Videos verbleibend.", delay: 3000 },
  { side: "in",  typing: 2800 },
  // Reel-Tile als <video> mit JPG-Poster — autoplay+muted+loop. Browser
  // zeigt den Poster solange das MP4 noch lädt oder fehlt; sobald es da
  // ist, läuft das Reel im Chat-Bubble in Endlosschleife.
  { side: "in",  media: { kind: "reel", caption: "Reel · E-Check am Verteiler", src: "examples/demo-reel-1.jpg", video: "examples/demo-reel-1.mp4" }, delay: 2600 },
  { side: "in",  text: "Caption + 12 Hashtags fertig. Empfehlung: heute 8:00-9:00 posten. Text-Änderung gratis, falls du noch was anpassen willst.", delay: 2200 },
  // Zweite Runde: konkreter Wunsch wird respektiert.
  { side: "out", text: "Mach noch eins: Wallbox-Aktion 30%", delay: 2400 },
  { side: "in",  typing: 1200 },
  { side: "in",  text: "Verstanden — *Wallbox-Aktion* mit 30%-Hinweis. Übernehme deine Zahlen 1:1. Rendere los, dauert paar Minuten.", delay: 2800 },
  { side: "in",  typing: 3000 },
  { side: "in",  media: { kind: "reel", caption: "Reel · Wallbox-Aktion 30%", src: "examples/demo-reel-1.jpg", video: "examples/demo-reel-1.mp4" }, delay: 2600 },
  { side: "in",  text: "Caption + Hashtags + Posting-Empfehlung dabei.", delay: 2400 },
  { side: "out", actions: ["Text ändern"], delay: 2000 },
];

// SALE_PROMO_SCRIPT — der „konkreter Wunsch wird respektiert"-Flow.
// Lebt in einer dedizierten Sektion unter den Beispielen, nicht im Hero,
// damit der Hero den „keine Idee nötig"-Punkt sauber rüberbringt.
//
// Spiegelt ``prompt_intent.parse_user_prompt`` — mandatory_facts:
// [„30% Rabatt", „Wallbox"] werden in ``proof`` gemergt und überleben
// den Claims-Scrub. Richard baut den Reel-Plan, Anna übernimmt die
// exakte Promo-Zahl in der Caption.
const SALE_PROMO_SCRIPT = [
  { side: "out", text: "Erstelle ein Reel für Sale 30% auf Wallboxen", delay: 1400 },
  { side: "in",  typing: 1200 },
  { side: "in",  text: "Verstanden — *Wallbox-Aktion* mit 30%-Rabatt-Hinweis. Übernehme deine Zahlen 1:1.", delay: 2800 },
  { side: "in",  typing: 3000 },
  { side: "in",  media: { kind: "reel", caption: "Reel · Wallbox-Aktion 30%", src: "examples/demo-reel-1.jpg", video: "examples/demo-reel-1.mp4" }, delay: 2600 },
  { side: "in",  text: "Caption + 8 Hashtags fertig. Empfehlung: heute 17:00-19:00 posten — der Slot wo Kunden Feierabend-Scroll machen.", delay: 2400 },
  { side: "out", actions: ["Text ändern", "Passt — danke"], delay: 2000 },
];

// REVISION_SCRIPT — zeigt das "Text ändern"-Feature, der wichtigste UX-Win
// der 2026-05-12-Iteration. Der Customer schickt das fertige Reel an einen
// Kollegen, merkt dass eine Info fehlt (Rabatt 30%), und ändert nur den
// Overlay-Text. Das Kling-Video selbst wird aus dem R2-Cache wiederverwendet,
// nur der Composite läuft neu → keine Quota wird verbraucht, kein neuer
// fal.ai-Render. Spiegelt den realen rerender_video_overlay_only-Pfad.
const REVISION_SCRIPT = [
  { side: "in",  media: { kind: "reel", caption: "Reel · Wallbox-Aktion", src: "examples/demo-reel-1.jpg", video: "examples/demo-reel-1.mp4" }, delay: 1600 },
  { side: "in",  text: "Fertig. Caption + 6 Hashtags dabei. Format: Reel.\nText-Änderung gratis & unbegrenzt — dein Video bleibt gleich.", delay: 2800 },
  { side: "out", actions: ["Text ändern"], delay: 2200 },
  { side: "in",  typing: 1100 },
  { side: "in",  text: "Was soll am Text anders werden? Schreib mir kurz die neue Richtung oder den genauen Satz.", delay: 2600 },
  { side: "out", text: "Bitte 30% Rabatt-Hinweis rein", delay: 2200 },
  { side: "in",  typing: 1000 },
  { side: "in",  text: "Alles klar, ich tausche nur den Text — Video bleibt gleich.", delay: 2200 },
  { side: "in",  typing: 2200 },
  // Selbes demo-reel-1.mp4 nochmal — in echt würde das Composite mit
  // dem neuen Overlay-Text drüber laufen, aber für die Demo genügt das
  // identische MP4 (der Caption-Text darüber ist anders).
  { side: "in",  media: { kind: "reel", caption: "Reel · Wallbox 30% Rabatt", src: "examples/demo-reel-1.jpg", video: "examples/demo-reel-1.mp4" }, delay: 2400 },
  { side: "out", actions: ["Passt — danke"], delay: 1800 },
];

// Onboarding sequence mirrors the real Vera/Felix flow: customer types
// the website URL → Felix crawls it and extracts logo, Slogan,
// Tonalität → Robert turns the raw research into a structured brand
// profile → the customer is invited to request the first Reel. The
// customer never uploads anything in this happy path — the website
// carries everything Felix needs.
//
// The final media bubble is a sample Reel preview, shown as an ``in``
// bubble (from the bot):
//   examples/demo-reel-1.mp4  — mirrors the kind of Reel the
//                                   customer gets on first request.
//
// ``*bold*`` segments are rendered as <strong> via renderRichText()
// below — so the chat bubble shows real bold text, not literal asterisks.
const ONBOARDING_SCRIPT = [
  { side: "out", text: "Servus! Wie geht's los?", delay: 1200 },
  { side: "in",  typing: 1200 },
  { side: "in",  text: "Hi! Ich bin dein KI-Video-Assistent — ich baue dir fertige Werbevideos per WhatsApp. Schreib mir *Name + Branche*, oder einfach deine *Website-URL* — den Rest finde ich selbst.", delay: 3200 },
  { side: "out", text: "www.elektriker-flieger.at", delay: 2000 },
  { side: "in",  typing: 1400 },
  { side: "in",  text: "Schau mir die Website kurz an …", delay: 1800 },
  { side: "in",  typing: 3000 },
  { side: "in",  text: "Logo gefunden ✓\nSchriftart erkannt ✓\nSlogan + Markenfarben extrahiert ✓\nStandort: Amstetten und Umgebung", delay: 3200 },
  { side: "in",  typing: 1600 },
  { side: "in",  text: "*Markenprofil bereit:*\n• Elektriker Flieger\n• Amstetten und Umgebung\n• Branche: Elektrotechnik\n• Tonalität: handwerklich, präzise", delay: 3200 },
  { side: "in",  typing: 1400 },
  { side: "in",  text: "So sieht ein Werbevideo von mir für dich aus — schreib einfach *Video: dein Thema* und ich leg los:", delay: 2400 },
  { side: "in",  typing: 2400 },
  { side: "in",  media: { kind: "reel", caption: "Reel · Elektriker Flieger", src: "examples/demo-reel-1.jpg", video: "examples/demo-reel-1.mp4" }, delay: 2600 },
  { side: "out", actions: ["Top — leg los"], delay: 2000 },
];

const Tick = () => (
  <svg viewBox="0 0 18 12" width="14" height="12" fill="none" stroke="#34B7F1" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
    <path d="m1 6 3 3 6-6M7 9l3 3 7-7"/>
  </svg>
);

// Renders a chat-bubble string with two pieces of WhatsApp-style
// formatting honoured:
//   *bold*  → <strong>bold</strong>
//   \n      → <br/>
// Both are hardcoded into HERO_SCRIPT / ONBOARDING_SCRIPT / REVISION_SCRIPT
// so XSS isn't a concern — but use split/map instead of
// dangerouslySetInnerHTML so React still owns reconciliation.
function renderRichText(text) {
  if (!text) return text;
  const lines = text.split("\n");
  return lines.map((line, lineIdx) => {
    const parts = line.split(/(\*[^*]+\*)/g).filter(Boolean);
    const segments = parts.map((p, i) => {
      if (p.length > 2 && p.startsWith("*") && p.endsWith("*")) {
        return <strong key={i}>{p.slice(1, -1)}</strong>;
      }
      return <React.Fragment key={i}>{p}</React.Fragment>;
    });
    return (
      <React.Fragment key={lineIdx}>
        {segments}
        {lineIdx < lines.length - 1 && <br/>}
      </React.Fragment>
    );
  });
}

function ChatDemo({ script = HERO_SCRIPT } = {}) {
  const [shown, setShown] = useState([]);
  const [running, setRunning] = useState(true);
  const bodyRef = useRef(null);
  const ioRef = useRef(null);

  // Restart loop when finishing.
  useEffect(() => {
    if (!running) return;
    let alive = true;
    let timeouts = [];
    const run = async () => {
      setShown([]);
      let acc = 0;
      for (let i = 0; i < script.length; i++) {
        const step = script[i];
        acc += step.delay || step.typing || 1000;
        const t = setTimeout(() => {
          if (!alive) return;
          setShown((s) => {
            // remove a typing placeholder if next bubble belongs to same author
            const filtered = s.filter((x) => x.kind !== "typing");
            if (step.typing) return [...filtered, { kind: "typing", side: step.side, key: i }];
            return [...filtered, { ...step, kind: step.media ? "media" : step.actions ? "actions" : "text", key: i }];
          });
        }, acc);
        timeouts.push(t);
      }
      // restart after a pause
      const tEnd = setTimeout(() => alive && run(), acc + 5000);
      timeouts.push(tEnd);
    };
    run();
    return () => { alive = false; timeouts.forEach(clearTimeout); };
  }, [running, script]);

  // Pause when offscreen (perf, esp. on mobile)
  useEffect(() => {
    if (!bodyRef.current) return;
    const io = new IntersectionObserver(([e]) => setRunning(e.isIntersecting), { threshold: 0.1 });
    io.observe(bodyRef.current);
    ioRef.current = io;
    return () => io.disconnect();
  }, []);

  // auto scroll inside body
  useEffect(() => {
    if (bodyRef.current) {
      bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
    }
  }, [shown]);

  return (
    <div className="chat-shell">
      <div className="chat-header">
        <div className="chat-avatar">
          <img
            src="assets/adaconda-logo.png"
            alt="adaconda"
            style={{width: "100%", height: "100%", objectFit: "cover", borderRadius: "50%", display: "block"}}
          />
        </div>
        <div>
          <div className="who">adaconda</div>
          <div className="status">online · antwortet meist sofort</div>
        </div>
        <div className="chat-header-actions">
          <Icon.Video />
          <Icon.Phone />
        </div>
      </div>
      <div className="chat-body" ref={bodyRef}>
        {shown.map((b) => {
          if (b.kind === "typing") {
            return (
              <div key={b.key} className="bubble in" style={{padding:"4px 8px"}}>
                <span className="typing"><span/><span/><span/></span>
              </div>
            );
          }
          if (b.kind === "media") {
            // Media bubble rendering. Three cases:
            //   1. ``b.media.video`` set → <video> mit JPG-Poster.
            //      Reels werden so im Chat als echte Loops abgespielt;
            //      solange das MP4 nicht da ist, zeigt der Browser den
            //      Poster.
            //   2. ``b.media.src`` set (kein video) → statisches <img>
            //      für Posts und Uploads.
            //   3. Beides leer → leere Thumb (Fallback).
            const m = b.media;
            const fillStyle = {width:"100%", height:"100%", objectFit:"cover", display:"block"};
            return (
              <div key={b.key} className={`bubble media ${b.side}`}>
                <div className="media-thumb">
                  {m.video ? (
                    <video
                      src={m.video}
                      poster={m.src}
                      autoPlay
                      muted
                      loop
                      playsInline
                      preload="auto"
                      style={fillStyle}
                    />
                  ) : m.src ? (
                    <img
                      src={m.src}
                      alt={m.caption}
                      style={fillStyle}
                    />
                  ) : null}
                </div>
                <div className="media-caption">
                  {m.caption} <Tick/>
                </div>
              </div>
            );
          }
          if (b.kind === "actions") {
            return (
              <div key={b.key} className="bubble actions">
                {b.actions.map((a,i) => (
                  <button key={i}>{a}</button>
                ))}
              </div>
            );
          }
          return (
            <div key={b.key} className={`bubble ${b.side}`}>
              {renderRichText(b.text)}
              <span className="ts">
                {timeFor(b.key)}
                {b.side === "out" && <Tick/>}
              </span>
            </div>
          );
        })}
      </div>
      <div className="chat-input">
        <span className="chat-input-field">Nachricht…</span>
        <span className="chat-input-send"><Icon.Send/></span>
      </div>
    </div>
  );
}

// Convenience wrapper for the onboarding-flow demo. Passes the onboarding
// script into the same ChatDemo machinery so the visual + animation behaviour
// stays in lock-step with the Hero chat.
function OnboardingChatDemo() {
  return <ChatDemo script={ONBOARDING_SCRIPT} />;
}

// Revision-flow demo — used in the "Text ändern" feature deep-dive section.
function RevisionChatDemo() {
  return <ChatDemo script={REVISION_SCRIPT} />;
}

// Sale-promo demo — used in the "Konkreter Wunsch"-Sektion bei den
// Beispielen. Zeigt den specific-prompt flow mit Wallbox-Aktion.
function SalePromoChatDemo() {
  return <ChatDemo script={SALE_PROMO_SCRIPT} />;
}

function timeFor(i) {
  const base = 14*60 + 32; // 14:32
  const m = (base + i) % (24*60);
  const h = Math.floor(m / 60);
  const mm = m % 60;
  return `${String(h).padStart(2,"0")}:${String(mm).padStart(2,"0")}`;
}

window.ChatDemo = ChatDemo;
window.OnboardingChatDemo = OnboardingChatDemo;
window.RevisionChatDemo = RevisionChatDemo;
window.SalePromoChatDemo = SalePromoChatDemo;
