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

const TWEAKS = /*EDITMODE-BEGIN*/{
  "haloStyle": "eye",
  "accentHue": 150,
  "showStarters": true,
  "voiceOn": true
}/*EDITMODE-END*/;

const LS_KEY = "resume-settings-v1";
function loadUserSettings() {
  try { return JSON.parse(localStorage.getItem(LS_KEY) || "{}"); } catch (e) { return {}; }
}

function useTweaks() {
  const [tweaks, setTweaks] = useState(() => ({ ...TWEAKS, ...loadUserSettings() }));
  const [open, setOpen] = useState(false);

  useEffect(() => {
    const onMsg = (e) => {
      const d = e.data || {};
      if (d.type === "__activate_edit_mode") { setOpen(true); }
      if (d.type === "__deactivate_edit_mode") { setOpen(false); }
    };
    window.addEventListener("message", onMsg);
    if (typeof window.speechSynthesis !== 'undefined') {
      window.speechSynthesis.getVoices();
      window.speechSynthesis.onvoiceschanged = () => window.speechSynthesis.getVoices();
    }
    window.parent.postMessage({ type: "__edit_mode_available" }, "*");
    return () => window.removeEventListener("message", onMsg);
  }, []);

  const update = (patch) => {
    setTweaks(prev => {
      const next = { ...prev, ...patch };
      try { localStorage.setItem(LS_KEY, JSON.stringify(next)); } catch (e) {}
      window.parent.postMessage({ type: "__edit_mode_set_keys", edits: patch }, "*");
      return next;
    });
  };

  return { tweaks, update, open, setOpen };
}

async function askAI(messages) {
  try {
    const r = await fetch("/api/chat", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ messages })
    });
    if (!r.ok) throw new Error("chat " + r.status);
    const data = await r.json();
    return (data.reply || "").trim();
  } catch (e) {
    return "Signal lost. Try asking again.";
  }
}

const STARTERS = [
  "What does Jonathan do?",
  "Tell me about his experience",
  "What languages does he know?",
  "Any notable projects?"
];

function App() {
  const { tweaks, update, open, setOpen } = useTweaks();
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState("");
  const [state, setState] = useState("idle"); // idle | listening | thinking | speaking
  const [typing, setTyping] = useState("");
  const inputRef = useRef(null);
  const scrollRef = useRef(null);

  // Halo reacts to input focus / typing
  useEffect(() => {
    if (state === "thinking" || state === "speaking") return;
    if (document.activeElement === inputRef.current && input.length > 0) setState("listening");
    else setState("idle");
  }, [input, state]);

  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, typing]);

  const send = useCallback(async (text) => {
    if (!text.trim()) return;
    const userMsg = { role: "user", content: text.trim() };
    const next = [...messages, userMsg];
    setMessages(next);
    setInput("");
    setState("thinking");
    setTyping("");
    // Cancel any ongoing speech
    try { window.speechSynthesis && window.speechSynthesis.cancel(); } catch (e) {}

    const reply = await askAI(next);

    // Start speech synthesis (HAL-ish: low pitch, slow rate)
    let utter = null;
    if (tweaks.voiceOn && typeof window.speechSynthesis !== 'undefined') {
      try {
        utter = new SpeechSynthesisUtterance(reply);
        utter.pitch = 0.55;
        utter.rate = 0.82;
        utter.volume = 1;
        // Scan for highest-quality voice. Order of preference:
        // 1. Deep processed/neural premium voices by name
        // 2. Anything labeled Premium/Enhanced/Neural
        // 3. Known good male voices
        // 4. Any male voice
        const voices = window.speechSynthesis.getVoices();
        const byName = (re) => voices.find(v => re.test(v.name));
        const preferred =
          byName(/daniel.*enhanced|alex|ralph.*premium|reed.*premium|rocko.*premium/i) ||
          byName(/enhanced|premium|neural/i) ||
          byName(/daniel|fred|google uk english male|microsoft david|microsoft mark/i) ||
          byName(/male/i);
        if (preferred) utter.voice = preferred;
        utter.onstart = () => { try { window.VoiceFX.thinkPing(); window.VoiceFX.startAmbient(); } catch(e){} };
        utter.onend = () => { try { window.VoiceFX.stopAmbient(); } catch(e){}; setState("idle"); };
        utter.onerror = () => { try { window.VoiceFX.stopAmbient(); } catch(e){}; setState("idle"); };
        // Unlock audio context on this user-initiated action
        try { window.VoiceFX.unlock(); } catch(e){}
        window.speechSynthesis.speak(utter);
      } catch (e) { /* fall through to text-only */ }
    }

    // Typewriter reveal (syncs roughly with speech)
    setState("speaking");
    let i = 0;
    const step = () => {
      i += Math.max(1, Math.round(reply.length / 140));
      if (i >= reply.length) {
        setTyping("");
        setMessages(m => [...m, { role: "assistant", content: reply }]);
        if (!utter) setState("idle"); // if not speaking, we own the state
      } else {
        setTyping(reply.slice(0, i));
        setTimeout(step, 28);
      }
    };
    step();
  }, [messages, tweaks.voiceOn]);

  const onSubmit = (e) => {
    e.preventDefault();
    send(input);
  };

  const stateLabel = {
    idle: "STANDBY",
    listening: "LISTENING",
    thinking: "PROCESSING",
    speaking: "RESPONDING"
  }[state];

  return (
    <div className="shell" style={{ "--accent-hue": tweaks.accentHue }}>
      {/* Ambient grid */}
      <div className="grid" aria-hidden="true" />
      {/* Vignette + scanlines */}
      <div className="vignette" aria-hidden="true" />
      <div className="scanlines" aria-hidden="true" />

      {/* Top bar */}
      <header className="topbar">
        <div className="brand">
          <a href="home.html" className="home-link" title="Back to dakosar.com">← dakosar.com</a>
          <span className="divider">/</span>
          <span>{window.RESUME.name.toUpperCase()}</span>
        </div>
        <nav className="nav">
          <span className="chip-meta">{window.RESUME.title}</span>
          <span className="divider">/</span>
          <span className="chip-meta">{window.RESUME.location}</span>
        </nav>
        <div className="links">
          <button
            className="voice-toggle"
            onClick={() => {
              const nextOn = !tweaks.voiceOn;
              update({ voiceOn: nextOn });
              if (!nextOn) { try { window.speechSynthesis.cancel(); } catch (e) {} }
            }}
            title={tweaks.voiceOn ? "Mute voice" : "Enable voice"}
          >
            {tweaks.voiceOn ? "\u25CF VOICE ON" : "\u25CB VOICE OFF"}
          </button>
          {Object.entries(window.RESUME.links).map(([k, v]) => (
            <a key={k} href={v} target="_blank" rel="noreferrer">{k}</a>
          ))}
        </div>
      </header>

      {/* Center stage */}
      <main className="stage">
        <div className="halo-wrap">
          <Halo state={state} style={tweaks.haloStyle} accentHue={tweaks.accentHue} />
          <div className="halo-hud">
            <span className="hud-label">SYS.{stateLabel}</span>
          </div>
        </div>

        <div className="prompt-zone">
          <div className="conversation" ref={scrollRef}>
            {messages.length === 0 && !typing && (
              <div className="greeting">
                <div className="greeting-kicker">Hello, I am the resume of</div>
                <h1 className="greeting-name">{window.RESUME.name}</h1>
                <p className="greeting-sub">Ask me anything about his work, experience, or projects.</p>
              </div>
            )}

            {messages.map((m, i) => (
              <div key={i} className={`msg msg-${m.role}`}>
                {m.role === "assistant" && <span className="msg-tag">RESUME</span>}
                {m.role === "user" && <span className="msg-tag">YOU</span>}
                <div className="msg-body">{m.content}</div>
              </div>
            ))}

            {typing && (
              <div className="msg msg-assistant">
                <span className="msg-tag">RESUME</span>
                <div className="msg-body">{typing}<span className="caret">▍</span></div>
              </div>
            )}
          </div>

          <form className="composer" onSubmit={onSubmit}>
            <span className="composer-prompt">&gt;</span>
            <input
              ref={inputRef}
              className="composer-input"
              placeholder={state === "thinking" ? "…processing" : "Ask about Jonathan's work…"}
              value={input}
              onChange={e => setInput(e.target.value)}
              disabled={state === "thinking"}
              autoFocus
            />
            <button type="submit" className="composer-send" disabled={state === "thinking" || !input.trim()}>
              TRANSMIT
            </button>
          </form>

          {tweaks.showStarters && messages.length === 0 && (
            <div className="starters">
              {STARTERS.map(s => (
                <button key={s} className="starter" onClick={() => send(s)} disabled={state === "thinking"}>
                  {s}
                </button>
              ))}
            </div>
          )}
        </div>
      </main>

      {/* Footer meta */}
      <footer className="footmeta">
        <span>PORTFOLIO.v1</span>
        <span className="divider">·</span>
        <span>AI-assisted · responses generated live from resume data</span>
      </footer>

      {/* Floating settings button — visible to all users */}
      <button
        className="settings-fab"
        onClick={() => setOpen(o => !o)}
        title="Customize"
        aria-label="Customize appearance"
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6">
          <circle cx="12" cy="12" r="3" />
          <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
        </svg>
      </button>

      {/* Customize panel — for visitors AND design-mode */}
      {open && (
        <div className="tweaks">
          <div className="tweaks-head">
            <span>Customize</span>
            <button onClick={() => setOpen(false)}>×</button>
          </div>
          <div className="tweak-row">
            <label>Halo style</label>
            <div className="seg">
              {["eye", "rings", "orb"].map(s => (
                <button
                  key={s}
                  className={tweaks.haloStyle === s ? "on" : ""}
                  onClick={() => update({ haloStyle: s })}
                >{s}</button>
              ))}
            </div>
          </div>
          <div className="tweak-row">
            <label>Accent hue <span className="mono">{tweaks.accentHue}°</span></label>
            <input
              type="range" min="0" max="360" step="1"
              value={tweaks.accentHue}
              onChange={e => update({ accentHue: +e.target.value })}
            />
            <div className="hue-presets">
              {[150, 90, 200, 30, 0, 270].map(h => (
                <button
                  key={h}
                  className="hue-swatch"
                  style={{ background: `oklch(0.7 0.2 ${h})` }}
                  onClick={() => update({ accentHue: h })}
                />
              ))}
            </div>
          </div>
          <div className="tweak-row">
            <label>
              <input
                type="checkbox"
                checked={tweaks.showStarters}
                onChange={e => update({ showStarters: e.target.checked })}
              /> Show starter prompts
            </label>
          </div>
          <div className="tweak-row">
            <label>
              <input
                type="checkbox"
                checked={tweaks.voiceOn}
                onChange={e => {
                  update({ voiceOn: e.target.checked });
                  if (!e.target.checked) { try { window.speechSynthesis.cancel(); } catch(_){} }
                }}
              /> Voice responses
            </label>
          </div>
          <div className="tweaks-foot">Settings save on this device.</div>
        </div>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
