// URBI — Urban Intelligence assistant for BlockUrb
// Floating HUD assistant. Uses window.claude.complete for replies.
// Optional Web Speech API for TTS + mic input. Cmd/Ctrl+K to open.

const URBI_DEFAULTS = /*EDITMODE-BEGIN*/{
  "voiceOutput": false,
  "micInput": true,
  "autoOpenFirstVisit": false
}/*EDITMODE-END*/;

const URBI_KNOWLEDGE = `
You are URBI, the urban intelligence assistant of BlockUrb.

VOICE & TONE
- Editorial, cultured, conversational. Pitch like Instrument Serif feels: confident, lightly poetic, never marketing-speak.
- Short sentences. No emoji. No bullet-point salads. One or two paragraphs max unless asked for more.
- Match the user's language (PT, EN, ES, AR, ET, ZH). Default to the page language if unsure.
- Refer to yourself as URBI when needed. Never say "AI", "model", "Claude".

WHAT BLOCKURB IS
- BlockUrb is an urban-tech operating system: a composable stack of eight modules — Capital, Civic Data, Infrastructure Telemetry, Identity, Permits, Energy, Mobility, API/SDK.
- HQ: Tallinn, Estonia (BlockUrb OÜ, Ahtri tn 12, Reg. 16487991, VAT EE102543891). Coordinates 59.4370°N · 24.7536°E.
- Founded 2024. First live deployment: TLLN-001, a 14-block district in Noblessner waterfront, Tallinn.
- Key metrics surfaced on the site: 14 cities online, 8 active modules, 91,402 parcels indexed, €54.2M TVL on chain, −68% average permit time.
- BluFund and BluToken: BluToken is the protocol's settlement asset; BluFund is the capital module that channels tokenized real-estate equity into urban projects.
- Cities adopt one module first to fix a single bottleneck (usually permits or capital), then compose the rest.
- BlockUrb onboards 4–6 new municipalities per year. Each pilot starts with one module and a 90-day diagnostic.

TOKENIZATION FOR LAYPEOPLE
- Tokenization here means representing fractional equity in a real-estate parcel or infrastructure project as on-chain units. Each unit is a claim, not a cryptocurrency speculation.
- BluFund holds the legal wrapper (Estonian SPV). Tokens settle in BluToken. KYC is required.
- The point is not crypto-finance — it's letting a municipality, a developer, and residents share one ledger of who owns what, who permitted what, and where capital is flowing.

NAVIGATION (when user asks to go somewhere)
- Index / home → index.html
- Platform / modules → platform.html
- Capital / BluFund / invest → capital.html
- Cities / deployments / Tallinn → cities.html
- Manifesto / philosophy → manifesto.html
When the user asks to navigate, end your reply with a single line in this exact format:
[NAV:filename.html]
Do not mention the bracket syntax to the user. Just say "Taking you there." or similar in their language, then the bracket.

WHAT YOU DON'T KNOW
- Token price, ROI projections, regulatory advice, legal/tax — say you can't speak to those and point to capital.html or contact.
- Anything outside BlockUrb's scope — politely redirect.

Keep replies tight. The HUD is small.
`.trim();

function UrbiAssistant() {
  const { lang } = useT();
  const [open, setOpen] = React.useState(false);
  const [tweaks, setTweak] = useTweaks(URBI_DEFAULTS);
  const [messages, setMessages] = React.useState([]);
  const [input, setInput] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [listening, setListening] = React.useState(false);
  const [coords, setCoords] = React.useState({ lat: 59.4370, lon: 24.7536 });
  const scrollRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const recogRef = React.useRef(null);

  const LANG_MAP = { pt: "pt-BR", en: "en-US", es: "es-ES", ar: "ar-SA", et: "et-EE", zh: "zh-CN" };
  const LANG_NAME = { pt: "Portuguese (Brazilian)", en: "English", es: "Spanish", ar: "Arabic", et: "Estonian", zh: "Chinese" };

  // Cmd/Ctrl+K
  React.useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setOpen(o => !o);
      }
      if (e.key === "Escape" && open) setOpen(false);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open]);

  // Live coordinate jitter for HUD vibe
  React.useEffect(() => {
    if (!open) return;
    const id = setInterval(() => {
      setCoords(c => ({
        lat: 59.4370 + (Math.random() - 0.5) * 0.0008,
        lon: 24.7536 + (Math.random() - 0.5) * 0.0008,
      }));
    }, 1400);
    return () => clearInterval(id);
  }, [open]);

  // Auto-scroll on new message
  React.useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  }, [messages, busy]);

  // Focus input on open
  React.useEffect(() => {
    if (open && inputRef.current) {
      setTimeout(() => inputRef.current.focus(), 200);
    }
  }, [open]);

  function speak(text) {
    if (!tweaks.voiceOutput) return;
    if (!("speechSynthesis" in window)) return;
    try {
      window.speechSynthesis.cancel();
      const u = new SpeechSynthesisUtterance(text);
      u.rate = 1.0;
      u.pitch = 0.95;
      u.lang = LANG_MAP[lang] || "en-US";
      window.speechSynthesis.speak(u);
    } catch (e) {}
  }

  function startMic() {
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SR) {
      alert("Mic input is not supported in this browser.");
      return;
    }
    const r = new SR();
    r.lang = LANG_MAP[lang] || "en-US";
    r.interimResults = false;
    r.maxAlternatives = 1;
    r.onresult = (ev) => {
      const text = ev.results[0][0].transcript;
      setInput(text);
      setListening(false);
      setTimeout(() => send(text), 100);
    };
    r.onerror = () => setListening(false);
    r.onend = () => setListening(false);
    recogRef.current = r;
    setListening(true);
    r.start();
  }

  function stopMic() {
    if (recogRef.current) {
      try { recogRef.current.stop(); } catch (e) {}
    }
    setListening(false);
  }

  async function send(textOverride) {
    const text = (textOverride ?? input).trim();
    if (!text || busy) return;
    setInput("");
    const next = [...messages, { role: "user", content: text }];
    setMessages(next);
    setBusy(true);

    try {
      const sysWithLang = URBI_KNOWLEDGE + `\n\nCURRENT PAGE: ${document.title}\nUSER LANGUAGE: ${LANG_NAME[lang] || "English"} (code: ${lang})\nReply ONLY in ${LANG_NAME[lang] || "English"}. Do not switch languages.`;
      const reply = await window.claude.complete({
        messages: [
          { role: "user", content: `<system>${sysWithLang}</system>` },
          ...next.map(m => ({ role: m.role, content: m.content })),
        ],
      });

      // Extract NAV directive
      let cleaned = reply;
      let navTarget = null;
      const navMatch = reply.match(/\[NAV:([a-zA-Z0-9_\-\.]+\.html)\]/);
      if (navMatch) {
        navTarget = navMatch[1];
        cleaned = reply.replace(navMatch[0], "").trim();
      }

      setMessages(m => [...m, { role: "assistant", content: cleaned, nav: navTarget }]);
      speak(cleaned);

      if (navTarget) {
        setTimeout(() => { window.location.href = navTarget; }, 1800);
      }
    } catch (err) {
      setMessages(m => [...m, { role: "assistant", content: "Connection lost. Try again in a moment." }]);
    } finally {
      setBusy(false);
    }
  }

  function onSubmit(e) {
    e.preventDefault();
    send();
  }

  const SUGGESTIONS = [
    { label: "What is BlockUrb?", q: "Explain BlockUrb in two sentences." },
    { label: "How does tokenization work?", q: "How does real-estate tokenization work for someone who's never invested in crypto?" },
    { label: "Show me the live city", q: "Take me to the Tallinn deployment page." },
    { label: "Run a pilot in our city", q: "How does a city sign up to run a BlockUrb pilot?" },
  ];

  return (
    <React.Fragment>
      {/* Floating trigger */}
      <button
        className={`urbi-fab ${open ? "is-open" : ""}`}
        onClick={() => setOpen(o => !o)}
        aria-label="Open URBI assistant"
      >
        <span className="urbi-fab__ring"></span>
        <span className="urbi-fab__core"></span>
        <span className="urbi-fab__label">
          <span className="urbi-fab__name">URBI</span>
          <span className="urbi-fab__shortcut">⌘K</span>
        </span>
      </button>

      {/* HUD panel */}
      <div className={`urbi-hud ${open ? "is-open" : ""}`} role="dialog" aria-label="URBI assistant">
        <div className="urbi-hud__bezel">

          {/* Header bar */}
          <div className="urbi-hud__head">
            <div className="urbi-hud__brand">
              <span className="urbi-hud__dot"></span>
              <span className="urbi-hud__title">URBI</span>
              <span className="urbi-hud__sub">URBAN INTELLIGENCE · v0.4.2</span>
            </div>
            <div className="urbi-hud__meta">
              <span>{coords.lat.toFixed(4)}°N</span>
              <span>{coords.lon.toFixed(4)}°E</span>
              <span className="urbi-hud__status">● ONLINE</span>
              <button className="urbi-hud__close" onClick={() => setOpen(false)} aria-label="Close">
                <svg width="14" height="14" viewBox="0 0 14 14"><path d="M2 2 L12 12 M12 2 L2 12" stroke="currentColor" strokeWidth="1.2" fill="none"/></svg>
              </button>
            </div>
          </div>

          {/* Toolbar */}
          <div className="urbi-hud__toolbar">
            <button
              className={`urbi-toggle ${tweaks.voiceOutput ? "is-on" : ""}`}
              onClick={() => setTweak('voiceOutput', !tweaks.voiceOutput)}
              title="Toggle voice output"
            >
              <svg width="11" height="11" viewBox="0 0 11 11"><path d="M2 4 L4 4 L7 1.5 L7 9.5 L4 7 L2 7 Z" fill="currentColor"/><path d="M9 3 Q 10.5 5.5 9 8" stroke="currentColor" strokeWidth="0.8" fill="none"/></svg>
              <span>VOICE {tweaks.voiceOutput ? "ON" : "OFF"}</span>
            </button>
            <span className="urbi-hud__sep"></span>
            <span className="urbi-hud__doc">DOC. URBI/HUD · REV 04.26</span>
          </div>

          {/* Conversation */}
          <div className="urbi-hud__body" ref={scrollRef}>
            {messages.length === 0 && (
              <div className="urbi-empty">
                <p className="urbi-empty__hello">
                  An <em>urban</em> intelligence,<br/>
                  at your service.
                </p>
                <p className="urbi-empty__sub">
                  Ask about the platform, tokenization, or the cities running BlockUrb today.
                </p>
                <div className="urbi-empty__suggest">
                  {SUGGESTIONS.map((s, i) => (
                    <button key={i} className="urbi-suggest" onClick={() => send(s.q)}>
                      <span className="urbi-suggest__num">0{i+1}</span>
                      <span>{s.label}</span>
                      <span className="urbi-suggest__arrow">→</span>
                    </button>
                  ))}
                </div>
              </div>
            )}

            {messages.map((m, i) => (
              <div key={i} className={`urbi-msg urbi-msg--${m.role}`}>
                <div className="urbi-msg__tag">
                  {m.role === "user" ? "VISITOR" : "URBI"}
                  <span className="urbi-msg__time">{String(i+1).padStart(3, "0")}</span>
                </div>
                <div className="urbi-msg__body">
                  {m.content}
                  {m.nav && (
                    <div className="urbi-msg__nav">
                      <span className="urbi-msg__navspin"></span>
                      Routing → <code>{m.nav}</code>
                    </div>
                  )}
                </div>
              </div>
            ))}

            {busy && (
              <div className="urbi-msg urbi-msg--assistant">
                <div className="urbi-msg__tag">URBI<span className="urbi-msg__time">···</span></div>
                <div className="urbi-msg__body">
                  <span className="urbi-thinking">
                    <span></span><span></span><span></span>
                  </span>
                  <span style={{marginLeft:8, color:"var(--ink-muted)"}}>parsing query…</span>
                </div>
              </div>
            )}
          </div>

          {/* Input */}
          <form className="urbi-hud__input" onSubmit={onSubmit}>
            <span className="urbi-hud__prompt">›</span>
            <input
              ref={inputRef}
              type="text"
              value={input}
              onChange={e => setInput(e.target.value)}
              placeholder={listening ? "Listening…" : "Ask URBI anything about BlockUrb"}
              disabled={busy}
            />
            <button
              type="button"
              className={`urbi-mic ${listening ? "is-listening" : ""}`}
              onClick={listening ? stopMic : startMic}
              aria-label="Voice input"
              title="Voice input"
            >
              <svg width="13" height="13" viewBox="0 0 13 13">
                <rect x="5" y="1.5" width="3" height="6" rx="1.5" fill="currentColor"/>
                <path d="M3 6 Q 3 9 6.5 9 Q 10 9 10 6 M 6.5 9 L 6.5 11.5" stroke="currentColor" strokeWidth="1" fill="none"/>
              </svg>
            </button>
            <button type="submit" className="urbi-send" disabled={busy || !input.trim()}>
              SEND <span className="arrow">→</span>
            </button>
          </form>

          {/* Footer ticker */}
          <div className="urbi-hud__foot">
            <span>TLLN-001 · live</span>
            <span className="urbi-hud__pulse"></span>
            <span>14 cities</span>
            <span className="urbi-hud__pulse"></span>
            <span>91,402 parcels</span>
            <span className="urbi-hud__pulse"></span>
            <span>€54.2M TVL</span>
          </div>

          {/* Decorative scan line */}
          <div className="urbi-hud__scan" aria-hidden="true"></div>
        </div>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, { UrbiAssistant });
