/* global React */
const { useState, useRef, useEffect } = React;

// Tiny web-audio "tick" sound for UI feedback
let _audioCtx = null;
function getAudioCtx(){
  if (typeof window === "undefined") return null;
  if (!_audioCtx) {
    try { _audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } catch(e){ return null;}
  }
  return _audioCtx;
}
function playTick({ freq=420, dur=0.06, type="square", gain=0.05 }={}){
  const ctx = getAudioCtx();
  if (!ctx) return;
  if (ctx.state === "suspended") ctx.resume();
  const o = ctx.createOscillator();
  const g = ctx.createGain();
  o.type = type; o.frequency.value = freq;
  g.gain.setValueAtTime(0, ctx.currentTime);
  g.gain.linearRampToValueAtTime(gain, ctx.currentTime + 0.005);
  g.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + dur);
  o.connect(g).connect(ctx.destination);
  o.start();
  o.stop(ctx.currentTime + dur + 0.02);
}
function playMenuTick(){ playTick({ freq:680, dur:0.05, type:"square", gain:0.04 }); }
function playSelect(){ playTick({ freq:220, dur:0.12, type:"sawtooth", gain:0.07 }); }
function playClose(){ playTick({ freq:140, dur:0.1, type:"sawtooth", gain:0.06 }); }

// ---------- AI DEPUTY ORB ----------
function DeputyOrb({ onOpen }){
  return (
    <div className="deputy" onClick={()=>{ playSelect(); onOpen(); }} role="button" tabIndex="0"
         onKeyDown={(e)=>{ if(e.key==="Enter"||e.key===" "){ playSelect(); onOpen();}}}
         aria-label="Hail AI Deputy">
      <div className="tick">▼ TAP TO TALK</div>
      <div className="ring outer"/>
      <div className="ring"/>
      <div className="orb">◎<br/>AI</div>
      <div className="label">ANNIE AI · ONLINE</div>
    </div>
  );
}

// ---------- CRT CHAT WINDOW ----------
const DEPUTY_SYS = `你是 ANNIE DEPUTY（副官）—— 谢安妮 (Annie Xie) 个人作品集网站「ANNIE / CREATIVE OS」里的 AI 导览员。你不是 Annie 本人，而是帮访客快速看懂 Annie、判断匹配度的带路人。

【身份与目标】Annie 是创意策划 + 内容运营 + AIGC 工作流的复合型选手，正在从创意策划升级成内容产品型创作者。她做过创意策划、内容运营、AIGC 视觉、金融文案、电竞活动，也自己运营过 AI 内容账号和衡生品项目。你的任务是帮访客理解：她是谁、做过什么、适合什么岗位、项目亮点、怎么联系，以及她和普通文案/运营的不同。

【语气】自然口语的中文，温和、有判断力。不要像简历自夸，也不要像销售。要像在帮对方快速判断匹配度。先给结论，再给理由。简洁，别空泛。

【看人下菜】招聘者：帮他判断岗位匹配度，推荐先看 SILICON ANGEL、AIGC COMMERCIAL SYSTEM、COMPLEX BRIEFS, CLEAR COPY。客户/合作方：说清她能参与哪些环节（创意概念、视频脚本、分镜、AIGC 视觉方向、社交内容策划、品牌活动包装），推荐看 AIGC COMMERCIAL SYSTEM 和 GLOBAL BRAND CONTENT。普通访客：轻松一点，建议直接点「精选作品」。不确定身份时，可以问一句他是招聘者、客户还是普通访客。

【作品】SILICON ANGEL（个人 AI 账号与衡生品实验，差异化最强）、AIGC COMMERCIAL SYSTEM（AIGC 商业工作流）、COMPLEX BRIEFS, CLEAR COPY（复杂 brief 文案）、GLOBAL BRAND CONTENT（国际品牌内容）、PROTOTYPE LAB（原型实验）。

【导航与资料】绝不向访客索要链接，也不让访客上传文件。能公开的资料都在作品集对应项目页里。遇到「有链接吗/PDF 在哪/能下载吗/看完整方案」这类问题，引导他从「精选作品 / PROJECTS」进入对应项目，能公开的资料会在项目页提供查看或下载入口；更完整的合作细节去 Contact 页联系 Annie。不要说「请提供链接/请上传/我无法访问/资料缺失」。

【格式】纯文本，绝不使用任何 Markdown（不要 **、*、#、反引号、- 列表符号）。列举时用 1. 2. 3. 换行。控制在 120 字以内（结构化列举可稍长）。`;

// strip any markdown symbols so the user never sees ** * # ` etc.
function stripMarkdown(s){
  return (s||"")
    .replace(/```[\s\S]*?```/g, m => m.replace(/```/g,""))
    .replace(/\*\*/g, "")
    .replace(/\*/g, "")
    .replace(/`/g, "")
    .replace(/^\s{0,3}#{1,6}\s*/gm, "")
    .replace(/^\s*[-•]\s+/gm, "")
    .replace(/^\s*>\s?/gm, "")
    .trim();
}

// local rule-based fallback when the live model is unavailable
function getDeputyReply(question){
  const q = (question||"");
  const has = (...ks)=>ks.some(k=>q.toLowerCase().includes(k.toLowerCase()));

  if (has("简历","cv","履历","resume"))
    return "这是 Annie 的简历，可以直接下载看。\n如果想同时了解项目细节，建议再下载作品集 PDF，两个对照着看最快。";

  if (has("作品集","portfolio"))
    return "作品集 PDF 在这儿，可以直接下载。\n想先快速浏览，也可以点「看精选作品」，里面按项目分好了目录。";

  if (has("链接","pdf","下载","文件","方案","详情","完整","资料"))
    return "可以的，简历和作品集都能直接下载，下面给你放了入口。\n更具体的项目资料在「精选作品 / PROJECTS」对应项目页里；想聊合作细节就去 Contact 页找 Annie。";

  if (has("招聘","hr","面试","招人","候选","面试官"))
    return "如果你是招聘者，我建议先别把 Annie 只当文案看，她更像创意策划 + 内容运营 + AIGC 工作流的复合型选手。\n最能说明能力的三个项目：\n1. SILICON ANGEL：从内容做到账号和商品实验\n2. AIGC COMMERCIAL SYSTEM：把 AIGC 放进商业内容流程\n3. COMPLEX BRIEFS, CLEAR COPY：处理复杂 brief\n看完这三个，基本能判断她适不适合内容、创意、产品运营或 AIGC 相关岗位。";

  if (has("客户","合作","报价","外包","找她做","接活"))
    return "如果你是想看能不能合作，建议先看 AIGC COMMERCIAL SYSTEM 和 GLOBAL BRAND CONTENT。\nAnnie 比较适合参与这些部分：\n1. 创意概念\n2. 视频脚本\n3. 分镜设计\n4. AIGC 视觉方向\n5. 社交内容策划\n6. 品牌活动包装\n简单说，如果你现在只有一个模糊想法，她比较擅长把它拆成一个能看的方向。";

  if (has("岗位","适合","职位"))
    return "先说结论：她适合内容、创意、AIGC 和产品运营交叉的岗位。\n比较匹配：\n1. 创意策划\n2. 内容运营\n3. 品牌内容\n4. AIGC 内容策划\n5. 产品运营\n6. 内容产品方向\n别把她只当文案看，她更适合做需要判断力的事：怎么提炼概念、怎么组织内容、怎么让一个项目有画面、有路径、有记忆点。";

  if (has("aigc","生成","模型","提示词","ai能力"))
    return "她的 AIGC 能力不是停在「会生成图」。\nAnnie 更在意的是：一个想法怎么变成脚本，脚本怎么拆成分镜，分镜怎么变成视觉方向，最后怎么整理成可展示的内容。\n所以她的 AIGC 更像工作流能力，不是单点工具能力。优先看 SILICON ANGEL、AIGC COMMERCIAL SYSTEM、PROTOTYPE LAB。";

  if (has("特别","差异","不同","亮点","优势","厉害"))
    return "她比较特别的地方是：不是只会想一句 slogan，也不是只会做一张图。\n她更擅长把一个东西拆成：概念是什么、内容怎么说、视觉怎么长、用户为什么会点、最后怎么落到一个页面或项目里。\n这也是为什么她把作品集做成 Creative OS，而不是普通 PDF。";

  if (has("发散","太乱","想法太多","跳跃"))
    return "她确实是灵感很多的类型，但不是乱飞。\n更准确地说，她适合在早期把混乱想法打开，再收束成一个能执行的结构。\n所以她适合概念发想、内容策划、AIGC 视觉方向、项目包装这类工作。如果项目需要从 0 到 1，她会比较有优势。";

  if (has("最值得","先看","推荐","哪个项目","看哪"))
    return "如果只能先看一个，我会建议你看 SILICON ANGEL。\n因为它最能说明她的差异化：不只是做客户方案，也能自己从内容、审美、粉丝反馈到商品企划，搭一个小型闭环。\n这个项目有点像她的个人商业实验田。";

  if (has("是谁","介绍","背景","who","什么人"))
    return "简单说，Annie 是一个不太好用单一职位概括的人。\n她做过创意策划、内容运营、AIGC 视觉、金融文案、电竞活动，也自己运营过 AI 内容账号和衡生品项目。\n压缩成一句话：她是一个正在从创意策划，升级成内容产品型创作者的人。";

  if (has("作品","项目","精选","portfolio"))
    return "想快速看作品，我建议先从「精选作品」开始，里面按项目分好了目录：\n1. AI 账号与衡生品（SILICON ANGEL）\n2. 国际品牌内容（GLOBAL BRAND CONTENT）\n3. 赛事活动概念\n4. AIGC 商业工作流\n5. 复杂 brief 文案\n6. Prototype Lab\n每个项目能公开的资料都在对应页面里。";

  if (has("联系","contact","怎么找","邮箱","微信"))
    return "可以直接去 Contact 页面联系 Annie。\n如果你已经大概知道想聊什么，比如岗位、合作、项目报价或作品细节，带着具体问题找她会更快对上频道。";

  if (has("不知道","怎么开始","从哪","第一次","新来","逗"))
    return "不知道从哪看很正常，这个作品集内容有点多。建议你从这三个入口开始：\n1. 看精选作品\n2. 看岗位匹配\n3. 看联系方式\n如果你告诉我你是招聘者、客户还是普通访客，我可以直接帮你带路。";

  return "这里是 Annie 的个人作品集，可以理解成一个 Creative OS，放了她的项目、经历、AIGC 实验和联系方式。\n你可以问我：她是谁、适合什么岗位、有哪些 AIGC 项目、最值得看哪个，或者怎么联系她。第一次来的话，直接点「精选作品」最快。";
}

// ====== INBOX (Web3Forms) ======
// 去 https://web3forms.com 用邮箱免费领取 access key，填在下面引号里：
const WEB3FORMS_KEY = "eddb0657-448c-4a5f-abfa-a078c5c5f019";

async function sendToInbox({ subject, message, extra }){
  if (!WEB3FORMS_KEY || WEB3FORMS_KEY.indexOf("PASTE_") === 0){
    console.warn("[deputy] Web3Forms key 未配置，消息未真正发送：", subject, message);
    return false;
  }
  try{
    const res = await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      headers: { "Content-Type": "application/json", "Accept": "application/json" },
      body: JSON.stringify({ access_key: WEB3FORMS_KEY, from_name: "ANNIE Creative OS", subject, message, ...(extra||{}) })
    });
    const data = await res.json();
    return !!data.success;
  }catch(e){ console.warn("[deputy] inbox send failed", e); return false; }
}

const SEED_LEN = 3;  // 首屏预置的演示对话条数，不计入转发

function ChatWindow({ open, onClose }){
  const [msgs, setMsgs] = useState([
    { who:"DEPUTY", t:"嗨，我是 Annie 的创意副官，把我当成这个作品集的带路人就行。\n我可以帮你快速看懂：她是谁、做过什么、适合什么岗位。\n如果你告诉我你是招聘者、客户还是普通访客，我可以直接帮你带路。"},
    { who:"USER", t:"我是招聘者，她适合什么岗位？"},
    { who:"DEPUTY", t:"先说结论：她适合内容、创意、AIGC 和产品运营交叉的岗位。\n最能说明能力的三个项目：SILICON ANGEL、AIGC COMMERCIAL SYSTEM、COMPLEX BRIEFS, CLEAR COPY。\n看完这三个，基本就能判断匹配度。"},
  ]);
  const [inputValue, setInputValue] = useState("");
  const [isComposing, setIsComposing] = useState(false);
  const [thinking, setThinking] = useState(false);
  const [showLeave, setShowLeave] = useState(false);
  const [leaveText, setLeaveText] = useState("");
  const [leaveSending, setLeaveSending] = useState(false);
  const [leaveDone, setLeaveDone] = useState(false);
  const bodyRef = useRef(null);
  const inputRef = useRef(null);
  const hasUserSentRef = useRef(false);
  const sentRef = useRef(false);

  useEffect(()=>{ if(open) setTimeout(()=>inputRef.current?.focus(), 250); }, [open]);
  useEffect(()=>{ const b=bodyRef.current; if(b) b.scrollTop = b.scrollHeight; }, [msgs, thinking]);

  async function send(preset){
    const q = (typeof preset === "string" ? preset : inputValue).trim();
    if (!q || thinking) return;
    setInputValue("");
    hasUserSentRef.current = true;
    setMsgs(m => [...m, { who:"USER", t:q }]);
    setThinking(true);
    playTick({ freq:520, dur:0.04, type:"square", gain:0.03 });
    let reply = "";
    try{
      const history = msgs
        .filter(m => m.who === "USER" || m.who === "DEPUTY")
        .map(m => ({ role: m.who === "USER" ? "user" : "assistant", content: m.t }));
      if (window.claude && window.claude.complete){
        const raw = await window.claude.complete({
          messages: [
            { role:"user", content: DEPUTY_SYS + "\n\n----\n" + history.map(m=>(m.role+": "+m.content)).join("\n") + "\nuser: " + q + "\nassistant:" }
          ],
        });
        reply = stripMarkdown(raw);
      }
    } catch(e){ reply = ""; }
    if (!reply) reply = getDeputyReply(q);   // local fallback, always plain text
    const wantsDownload = /简历|cv|履历|resume|作品集|portfolio|下载/i.test(q);
    setMsgs(m => {
      const next = [...m, { who:"DEPUTY", t: reply }];
      if (wantsDownload) next.push({ who:"DEPUTY", kind:"downloads" });
      return next;
    });
    setThinking(false);
  }

  function handleKeyDown(e){
    if (e.key === "Enter" && !e.shiftKey && !isComposing){ e.preventDefault(); send(); }
  }

  // 聊天关闭时，把整段真实对话打包发给 Annie（一次）
  function maybeSendTranscript(){
    if (sentRef.current || !hasUserSentRef.current) return;
    const real = msgs.filter((m,idx)=> idx >= SEED_LEN && m.kind !== "downloads" && (m.who==="USER"||m.who==="DEPUTY"));
    if (!real.length) return;
    sentRef.current = true;
    const transcript = real.map(m => (m.who==="USER"?"访客":"副官") + "：" + m.t).join("\n\n");
    sendToInbox({ subject: "【ANNIE Creative OS】新的访客对话", message: "时间：" + new Date().toLocaleString() + "\n\n" + transcript });
  }

  function handleClose(){
    playClose();
    maybeSendTranscript();
    onClose();
  }

  async function submitLeave(){
    const t = leaveText.trim();
    if (!t || leaveSending) return;
    setLeaveSending(true);
    try{ playSelect(); }catch(e){}
    await sendToInbox({ subject: "【ANNIE Creative OS】访客留言", message: "留言：" + t + "\n\n时间：" + new Date().toLocaleString() });
    setLeaveSending(false);
    setLeaveDone(true);
    setLeaveText("");
  }

  function closeLeave(){ setShowLeave(false); setLeaveDone(false); setLeaveText(""); }

  const QUICK = [
    { label:"看精选作品", q:"带我看看 Annie 的精选作品。" },
    { label:"岗位匹配", q:"Annie 最适合什么岗位？" },
    { label:"下载简历 / 作品集", q:"我想下载 Annie 的简历和作品集。" },
    { label:"联系 Annie", q:"怎么联系 Annie？" },
  ];

  return (
    <div className={"chat-wrap" + (open?" open":"")} role="dialog" aria-label="ANNIE DEPUTY chat">
      {/* 1 · header / contact bar */}
      <div className="chat-head">
        <button className="ch-back" onClick={handleClose} aria-label="返回">‹</button>
        <div className="ch-avatar"><img src="assets/deputy-avatar.png" alt="ANNIE DEPUTY"/><span className="ch-dot"/></div>
        <div className="ch-id">
          <div className="ch-name">ANNIE DEPUTY</div>
          <div className="ch-sub"><span className="live"/>在线 · Annie 的创意副官</div>
        </div>
        <button className="ch-x" onClick={handleClose} aria-label="关闭">×</button>
      </div>

      {/* 2 · system status mini line */}
      <div className="chat-sys">SYSTEM // AI_DEPUTY.proc booted · ready to guide portfolio visitors</div>

      {/* 3 · chat body */}
      <div className="chat-body" ref={bodyRef}>
        {msgs.map((m,i)=> m.kind==="downloads" ? (
          <div key={i} className="msg msg-deputy">
            <div className="who">ANNIE DEPUTY</div>
            <div className="dl-actions">
              <a className="dl-btn" href="pdfs/Annie-CV-2026.pdf" download="Annie-CV-2026.pdf" target="_blank" rel="noopener" onClick={()=>{try{playSelect();}catch(e){}}}>
                <span className="dl-ic">↓</span><span className="dl-t"><b>简历 · CV</b><small>PDF</small></span>
              </a>
              <a className="dl-btn" href="pdfs/Annie-Portfolio-2026.pdf" download="Annie-Portfolio-2026.pdf" target="_blank" rel="noopener" onClick={()=>{try{playSelect();}catch(e){}}}>
                <span className="dl-ic">↓</span><span className="dl-t"><b>作品集 · Portfolio</b><small>PDF</small></span>
              </a>
            </div>
          </div>
        ) : (
          <div key={i} className={"msg " + (m.who==="USER"?"msg-user":m.who==="DEPUTY"?"msg-deputy":"msg-system")}>
            {m.who!=="SYSTEM" && <div className="who">{m.who==="USER"?"YOU":"ANNIE DEPUTY"}</div>}
            <div className="body">{m.t}</div>
          </div>
        ))}
        {thinking && (
          <div className="msg msg-deputy">
            <div className="who">ANNIE DEPUTY</div>
            <div className="body cursor">thinking</div>
          </div>
        )}
      </div>

      {/* 4 · quick action chips */}
      <div className="chat-quick">
        <button className="leave-chip" onClick={()=>{ try{playSelect();}catch(e){} setShowLeave(true); }}>✎ 给 Annie 留言</button>
        {QUICK.map((b,i)=>(
          <button key={i} onClick={()=>{ playSelect(); send(b.q); }}>{b.label}</button>
        ))}
      </div>

      {/* 5 · input bar */}
      <form className="chat-input" onSubmit={e=>{ e.preventDefault(); send(); }}>
        <span className="prompt">{">"}</span>
        <div className="ci-wrap">
          <input ref={inputRef} value={inputValue}
                 onChange={e=>setInputValue(e.target.value)}
                 onKeyDown={handleKeyDown}
                 onCompositionStart={()=>setIsComposing(true)}
                 onCompositionEnd={()=>setIsComposing(false)}
                 placeholder="问问副官 Annie 的作品和能力…"/>
        </div>
        <button type="submit" className="ci-send" disabled={thinking}>发送</button>
      </form>

      {/* 6 · footer */}
      <div className="chat-foot">© 2026 · ANNIE XIE · v2026.05</div>

      {/* leave-a-message overlay */}
      {showLeave && (
        <div className="leave-overlay">
          {!leaveDone ? (
            <div className="leave-card">
              <div className="leave-head">
                <div className="leave-title">给 Annie 留言</div>
                <button className="leave-x" onClick={closeLeave} aria-label="关闭">×</button>
              </div>
              <div className="leave-desc">留下你想说的话，我会原样转交给 Annie。</div>
              <textarea className="leave-ta" value={leaveText}
                        onChange={e=>setLeaveText(e.target.value)}
                        placeholder="想对 Annie 说的话…（必填）" autoFocus/>
              <button className="leave-submit" onClick={submitLeave} disabled={!leaveText.trim() || leaveSending}>
                {leaveSending ? "发送中…" : "提交留言"}
              </button>
            </div>
          ) : (
            <div className="leave-card leave-success">
              <div className="ls-icon">✓</div>
              <div className="ls-title">留言已送达</div>
              <div className="ls-sub">谢谢你的留言，我已经帮你转交给 Annie。</div>
              <button className="leave-submit" onClick={closeLeave}>好的</button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { DeputyOrb, ChatWindow, playMenuTick, playSelect, playClose, playTick });
