(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))i(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const f of r.addedNodes)f.tagName==="LINK"&&f.rel==="modulepreload"&&i(f)}).observe(document,{childList:!0,subtree:!0});function s(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(o){if(o.ep)return;o.ep=!0;const r=s(o);fetch(o.href,r)}})();const I=102e3,v="haixun.dev-console",t=e=>document.getElementById(e),a=w();function w(){try{return JSON.parse(localStorage.getItem(v)||"{}")}catch{return{}}}function d(){localStorage.setItem(v,JSON.stringify(a))}function c(e,n){const s=t("log"),i=n===void 0?String(e):`${e} ${JSON.stringify(n,null,2)}`;s.textContent=`${new Date().toLocaleTimeString()} ${i}
`+s.textContent}async function l(e,{method:n="GET",body:s,auth:i=!1}={}){const o={"Content-Type":"application/json"};i&&a.accessToken&&(o.Authorization=`Bearer ${a.accessToken}`);const r=await fetch(e,{method:n,headers:o,body:s===void 0?void 0:JSON.stringify(s)}),f=await r.text();let m;try{m=JSON.parse(f)}catch{throw new Error(`非 JSON 回應 ${e}: HTTP ${r.status}`)}if(m.code!==I)throw new Error(m.message||`API 錯誤 ${m.code}`);return m.data}function u(e,n){const s=t("authStatus");s.textContent=e,s.className="status"+(n?" ok":n===!1?" err":"")}function T(e){return`${e||"—"}`}async function $(){try{await l("/api/v1/health"),t("connStatus").textContent="API 連線正常",t("connStatus").className="status ok"}catch(e){t("connStatus").textContent="API 離線:"+e.message,t("connStatus").className="status err"}}function S(e){const n=t("personaList");if(n.innerHTML="",!(e!=null&&e.length)){n.innerHTML='
尚無人設';return}for(const s of e){const i=document.createElement("li");i.className=s.id===a.selectedPersonaId?"active":"",i.innerHTML=`${s.display_name||s.id}${s.style_benchmark?"@"+s.style_benchmark:"未分析"}`,i.onclick=()=>g(s.id),n.appendChild(i)}}async function h(){const e=await l("/api/v1/personas",{auth:!0});a.personas=e.list||[],S(a.personas),d(),c("人設列表已更新",{count:a.personas.length})}function g(e){a.selectedPersonaId=e,d(),S(a.personas||[]),t("btnStart8d").disabled=!e,t("btnReloadPersona").disabled=!e,y()}async function y(){const e=a.selectedPersonaId;if(!e)return;const n=await l(`/api/v1/personas/${encodeURIComponent(e)}`,{auth:!0});t("personaMeta").textContent=`${n.display_name||e} · benchmark @${n.style_benchmark||"—"}`,t("personaDetail").value=JSON.stringify(n,null,2),c("人設詳情",{id:e,style_benchmark:n.style_benchmark})}async function C(){const e=await l("/api/v1/auth/login",{method:"POST",body:{tenant_id:t("tenantId").value.trim(),email:t("email").value.trim(),password:t("password").value}});a.accessToken=e.access_token,a.refreshToken=e.refresh_token,a.uid=e.uid,d(),u(`已登入 uid=${e.uid}`,!0),c("登入成功",{uid:e.uid}),await h(),a.selectedPersonaId&&g(a.selectedPersonaId)}async function N(){const e=await l("/api/v1/auth/register",{method:"POST",body:{tenant_id:t("tenantId").value.trim(),email:t("email").value.trim(),password:t("password").value,display_name:t("email").value.split("@")[0]}});a.accessToken=e.access_token,a.refreshToken=e.refresh_token,a.uid=e.uid,d(),u(`註冊並登入 uid=${e.uid}`,!0),c("註冊成功",{uid:e.uid}),await h()}function O(){a.accessToken="",a.refreshToken="",a.uid="",d(),u("已登出",!1),t("personaList").innerHTML="",t("personaDetail").value="",t("btnStart8d").disabled=!0,t("btnReloadPersona").disabled=!0,c("已登出")}async function _(){const e=t("displayName").value.trim()||"新人設",n=await l("/api/v1/personas",{method:"POST",auth:!0,body:{display_name:e}});t("displayName").value="",await h(),g(n.id),c("建立人設",{id:n.id})}async function L(){const e=a.selectedPersonaId,n=t("benchmark").value.trim().replace(/^@/,"");if(!e||!n)throw new Error("請選人設並填對標帳號");const s=await l(`/api/v1/personas/${encodeURIComponent(e)}/style-analysis`,{method:"POST",auth:!0,body:{benchmark_username:n}});t("jobId").value=s.job_id,t("jobHint").textContent=s.message||"任務已建立",t("jobHint").className="status ok",c("8D 任務已建立",s),await b(),k()}function x(e){var s,i,o;if(!e)return;const n=((s=e.progress)==null?void 0:s.steps)||[];t("jobSteps").innerHTML=n.map(r=>`${T(r.status)} ${r.id} — ${r.message||""}
`).join(""),t("jobDetail").textContent=JSON.stringify({id:e.id,status:e.status,phase:e.phase,percentage:(i=e.progress)==null?void 0:i.percentage,summary:(o=e.progress)==null?void 0:o.summary,error:e.error,result:e.result},null,2),["succeeded","completed","failed","cancelled"].includes(e.status)&&(P(),(e.status==="succeeded"||e.status==="completed")&&y().catch(()=>{}))}async function b(){const e=t("jobId").value.trim();if(!e)return;const n=await l(`/api/v1/jobs/${encodeURIComponent(e)}`,{auth:!0});return x(n),c("Job 狀態",{id:n.id,status:n.status,phase:n.phase}),n}let p=null;function k(){P(),p=setInterval(()=>b().catch(e=>c("輪詢失敗",e.message)),3e3),t("btnAutoPoll").textContent="停止輪詢"}function P(){p&&clearInterval(p),p=null,t("btnAutoPoll").textContent="自動輪詢"}t("btnLogin").onclick=()=>C().catch(e=>{u(e.message,!1),c("登入失敗",e.message)});t("btnRegister").onclick=()=>N().catch(e=>{u(e.message,!1),c("註冊失敗",e.message)});t("btnLogout").onclick=O;t("btnCreatePersona").onclick=()=>_().catch(e=>c("建立失敗",e.message));t("btnRefreshPersonas").onclick=()=>h().catch(e=>c("載入失敗",e.message));t("btnReloadPersona").onclick=()=>y().catch(e=>c("載入失敗",e.message));t("btnStart8d").onclick=()=>L().catch(e=>{t("jobHint").textContent=e.message,t("jobHint").className="status err",c("8D 失敗",e.message)});t("btnPollJob").onclick=()=>b().catch(e=>c("查詢失敗",e.message));t("btnAutoPoll").onclick=()=>p?P():k();a.tenantId&&(t("tenantId").value=a.tenantId);t("tenantId").onchange=()=>{a.tenantId=t("tenantId").value,d()};a.accessToken&&(u(`token 已還原 uid=${a.uid||"?"}`,!0),h().then(()=>{a.selectedPersonaId&&g(a.selectedPersonaId)}).catch(()=>u("token 可能過期,請重新登入",!1)));$();