(function () {
    "use strict";
    if (window.AIWKLocalPcBridge && window.AIWKLocalPcBridge.__v123) return;

    const VERSION = "v123-pc-identity-bridge";
    const STORE_KEY = "AIWK_PC_IDENTITY_BRIDGE_SETTINGS_V1";
    let ws = null;
    let seq = 0;
    const pending = new Map();

    function now() { return new Date().toLocaleTimeString(); }
    function safe(v) { return String(v == null ? "" : v); }
    const settingsMemory = { value: null, storage: "memory" };
    function defaultSettings() { return { enabled: false, auto_connect: false, url: "ws://127.0.0.1:8768", token: "" }; }
    function loadSettings() {
        if (settingsMemory.value) return Object.assign(defaultSettings(), settingsMemory.value);
        try {
            const raw = localStorage.getItem(STORE_KEY) || localStorage.getItem("AIWK_LOCAL_PC_BRIDGE_SETTINGS_V1");
            if (raw) {
                settingsMemory.value = Object.assign(defaultSettings(), JSON.parse(raw));
                settingsMemory.storage = "localStorage";
                return Object.assign(defaultSettings(), settingsMemory.value);
            }
        } catch (err) {}
        return defaultSettings();
    }
    function saveSettings(s) {
        const doc = Object.assign(defaultSettings(), s || {}, { saved_at: new Date().toISOString(), version: VERSION });
        settingsMemory.value = doc;
        try {
            localStorage.setItem(STORE_KEY, JSON.stringify(doc));
            settingsMemory.storage = "localStorage";
            return { ok: 1, storage: "localStorage" };
        } catch (err) {
            // v123: localStorage quota 초과는 오류로 터뜨리지 않는다.
            // 같은 프로필에 기존 도메인 저장값이 많을 수 있으므로 chrome.storage.local로 fallback한다.
            settingsMemory.storage = "memory";
            try { localStorage.removeItem("AIWK_LOCAL_PC_BRIDGE_SETTINGS_V1"); } catch (_) {}
            try {
                if (chrome && chrome.storage && chrome.storage.local) {
                    chrome.storage.local.set({ [STORE_KEY]: doc }, function () {});
                    settingsMemory.storage = "chrome.storage.local";
                    return { ok: 1, storage: "chrome.storage.local", local_error: err && err.message ? err.message : String(err) };
                }
            } catch (_) {}
            return { ok: 1, storage: "memory", local_error: err && err.message ? err.message : String(err) };
        }
    }
    function getProfileInstanceId() {
        try {
            const keys = ["AIWK_PROFILE_INSTANCE_ID", "profile_instance_id", "AIWK_EXT4_PROFILE_INSTANCE_ID"];
            for (const k of keys) {
                const v = localStorage.getItem(k);
                if (v) return v;
            }
        } catch (e) {}
        return "";
    }
    function makePanel() {
        let panel = document.getElementById("aiwk_local_pc_bridge_panel");
        if (panel) return panel;
        panel = document.createElement("div");
        panel.id = "aiwk_local_pc_bridge_panel";
        panel.setAttribute("data-aiwk-module-window", "1");
        panel.setAttribute("data-aiwk-window-label", "AIWK PC Identity");
        panel.setAttribute("data-aiwk-module-id", "core.pc.local_bridge");
        panel.style.cssText = "position:fixed;left:16px;bottom:16px;z-index:2147483646;width:340px;max-width:92vw;max-height:72vh;overflow:auto;resize:both;background:#111827;color:#e5e7eb;border:1px solid #38bdf8;border-radius:10px;box-shadow:0 8px 28px rgba(0,0,0,.45);font:12px Arial, sans-serif;";
        panel.innerHTML = '' +
            '<div data-aiwk-lpb-head="1" data-aiwk-win-title="1" style="display:flex;align-items:center;gap:6px;padding:7px 8px;background:#0f172a;border-radius:10px 10px 0 0;">' +
            '<b style="flex:1;">AIWK PC Identity Bridge</b><span style="font-size:11px;color:#93c5fd;">v123</span></div>' +
            '<div data-aiwk-lpb-body="1" style="padding:8px;display:flex;flex-direction:column;gap:5px;">' +
            '<div style="font-size:11px;color:#fde68a;">역할: PC/Chrome Profile/Client/Tab 정체성 확인 전용. PC 제어 기능 아님.</div>' +
            '<label><input type="checkbox" data-aiwk-lpb-enabled="1"> 사용함</label>' +
            '<label><input type="checkbox" data-aiwk-lpb-auto="1"> 자동연결</label>' +
            '<label>url<input data-aiwk-lpb-url="1" style="width:100%;box-sizing:border-box;background:#030712;color:#e5e7eb;border:1px solid #374151;border-radius:4px;padding:4px;"></label>' +
            '<label>token<input data-aiwk-lpb-token="1" type="password" style="width:100%;box-sizing:border-box;background:#030712;color:#e5e7eb;border:1px solid #374151;border-radius:4px;padding:4px;"></label>' +
            '<div style="display:flex;gap:4px;flex-wrap:wrap;">' +
            '<button data-aiwk-lpb-save="1">저장</button><button data-aiwk-lpb-connect="1">연결</button><button data-aiwk-lpb-disconnect="1">끊기</button>' +
            '<button data-aiwk-lpb-hello="1">identity</button><button data-aiwk-lpb-profiles="1">profiles</button><button data-aiwk-lpb-bind="1">profile bind</button><button data-aiwk-lpb-map="1">map</button></div>' +
            '<div data-aiwk-lpb-state="1" style="padding:5px;background:#020617;border:1px solid #1f2937;border-radius:5px;">disconnected</div>' +
            '<div data-aiwk-lpb-log="1" style="height:130px;overflow:auto;background:#020617;border:1px solid #1f2937;border-radius:5px;padding:5px;white-space:pre-wrap;"></div>' +
            '</div>';
        document.documentElement.appendChild(panel);
        if (window.AIWKWindowControls) window.AIWKWindowControls.enhance(panel, { key: "AIWK_PC_IDENTITY_BRIDGE_WIN", label: "AIWK PC Identity" });
        return panel;
    }
    function btnStyle(panel) { Array.from(panel.querySelectorAll('button')).forEach(b => { b.style.margin='1px'; b.style.background='#1f2937'; b.style.color='#e5e7eb'; b.style.border='1px solid #4b5563'; b.style.borderRadius='4px'; b.style.padding='3px 6px'; }); }
    function log(panel, text) { const el = panel.querySelector('[data-aiwk-lpb-log="1"]'); if (!el) return; const line = document.createElement('div'); line.textContent = now() + ' ' + safe(text).slice(0, 1000); el.appendChild(line); while (el.children.length > 80) el.removeChild(el.firstChild); el.scrollTop = el.scrollHeight; }
    function setState(panel, text) { const el = panel.querySelector('[data-aiwk-lpb-state="1"]'); if (el) el.textContent = text; }
    function renderSettings(panel) { const s = loadSettings(); panel.querySelector('[data-aiwk-lpb-enabled="1"]').checked = !!s.enabled; panel.querySelector('[data-aiwk-lpb-auto="1"]').checked = !!s.auto_connect; panel.querySelector('[data-aiwk-lpb-url="1"]').value = s.url || 'ws://127.0.0.1:8768'; panel.querySelector('[data-aiwk-lpb-token="1"]').value = s.token || ''; }
    function readPanelSettings(panel) { return { enabled: !!panel.querySelector('[data-aiwk-lpb-enabled="1"]').checked, auto_connect: !!panel.querySelector('[data-aiwk-lpb-auto="1"]').checked, url: panel.querySelector('[data-aiwk-lpb-url="1"]').value.trim() || 'ws://127.0.0.1:8768', token: panel.querySelector('[data-aiwk-lpb-token="1"]').value.trim() }; }
    function currentProfileData() { return { profile_instance_id: getProfileInstanceId(), url: location.href, title: document.title, host: location.host, href: location.href, at: new Date().toISOString() }; }
    function send(act, data) {
        const s = loadSettings();
        if (!s.enabled) return Promise.resolve({ ok:0, error_code:'LOCAL_IDENTITY_DISABLED', solution:'사용함 체크 후 저장하십시오.' });
        if (!ws || ws.readyState !== WebSocket.OPEN) return Promise.resolve({ ok:0, error_code:'LOCAL_IDENTITY_NOT_CONNECTED', solution:'연결 버튼을 누르십시오.' });
        const id = 'ext_' + Date.now() + '_' + (++seq);
        const packet = { v:1, id, act, token:s.token, from:{ endpoint:'ext4', href:location.href, title:document.title }, data:data || {} };
        return new Promise(resolve => { const timer=setTimeout(()=>{ pending.delete(id); resolve({ ok:0, id, error_code:'LOCAL_IDENTITY_TIMEOUT' }); }, 4000); pending.set(id,{resolve,timer}); ws.send(JSON.stringify(packet)); });
    }
    function connect(panel) {
        const s = loadSettings();
        if (!s.enabled) { log(panel, 'ERR LOCAL_IDENTITY_DISABLED / 사용함 체크 후 저장'); return; }
        if (!s.token) { log(panel, 'ERR TOKEN_EMPTY / AIWK_PC local_bridge.token 입력 필요'); return; }
        if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) { log(panel, 'already connecting/connected'); return; }
        setState(panel, 'connecting ' + s.url);
        try { ws = new WebSocket(s.url); } catch (err) { log(panel, 'ERR WS_CREATE ' + err.message); return; }
        ws.onopen = () => { setState(panel, 'connected'); log(panel, 'connected ' + s.url); send('identity_hello', currentProfileData()).then(res => log(panel, 'identity ' + JSON.stringify(res).slice(0,900))); };
        ws.onclose = () => { setState(panel, 'disconnected'); log(panel, 'closed'); };
        ws.onerror = () => { setState(panel, 'error'); log(panel, 'ERR websocket error / py aiwk_mypc_agent.py --local-ws 확인'); };
        ws.onmessage = ev => { let res; try { res = JSON.parse(ev.data); } catch (err) { log(panel, 'ERR JSON ' + safe(ev.data).slice(0,300)); return; } const p=pending.get(res.id); if(p){ clearTimeout(p.timer); pending.delete(res.id); p.resolve(res); } else log(panel, 'recv ' + JSON.stringify(res).slice(0,800)); };
    }
    function disconnect(panel) { try { if (ws) ws.close(); } catch (err) {} ws = null; setState(panel, 'disconnected'); log(panel, 'disconnect'); }
    function bind(panel) {
        if (panel.__aiwkLpbBound) return; panel.__aiwkLpbBound = true; btnStyle(panel);
        panel.querySelector('[data-aiwk-lpb-save="1"]').addEventListener('click', () => { const s=readPanelSettings(panel); const saved=saveSettings(s); log(panel, 'saved enabled=' + (s.enabled?1:0) + ' url=' + s.url + ' via=' + (saved.storage||'unknown')); });
        panel.querySelector('[data-aiwk-lpb-connect="1"]').addEventListener('click', () => { saveSettings(readPanelSettings(panel)); connect(panel); });
        panel.querySelector('[data-aiwk-lpb-disconnect="1"]').addEventListener('click', () => disconnect(panel));
        panel.querySelector('[data-aiwk-lpb-hello="1"]').addEventListener('click', () => send('identity_hello', currentProfileData()).then(res => log(panel, 'identity ' + JSON.stringify(res).slice(0,1000))));
        panel.querySelector('[data-aiwk-lpb-profiles="1"]').addEventListener('click', () => send('chrome_profiles_list', {}).then(res => log(panel, 'profiles ' + JSON.stringify(res).slice(0,1000))));
        panel.querySelector('[data-aiwk-lpb-bind="1"]').addEventListener('click', () => send('profile_bind', currentProfileData()).then(res => log(panel, 'profile_bind ' + JSON.stringify(res).slice(0,1000))));
        panel.querySelector('[data-aiwk-lpb-map="1"]').addEventListener('click', () => send('profile_map', {}).then(res => log(panel, 'map ' + JSON.stringify(res).slice(0,1000))));
    }
    function destroy() { disconnect(makePanel()); const panel = document.getElementById("aiwk_local_pc_bridge_panel"); if (panel) { try { if (panel.__aiwkDestroy) panel.__aiwkDestroy(); else panel.remove(); } catch (err) {} } window.AIWKLocalPcBridge = null; }
    window.addEventListener("AIWK_MODULE_UNLOAD", function (ev) { const id = ev && ev.detail && ev.detail.module_id; if (!id || id === "core.pc.local_bridge" || id === "*") destroy(); });
    function start() { const panel=makePanel(); bind(panel); renderSettings(panel); log(panel, 'ready ' + VERSION + ' / ws://127.0.0.1:8768 identity only'); const s=loadSettings(); if(s.enabled && s.auto_connect) connect(panel); }
    window.AIWKLocalPcBridge = { __v123: true, start, destroy, send, connect: () => connect(makePanel()), panel: makePanel };
    start();
})();
