// /AIWK_COMMON/modules/chart/demo.js
// AIWK v102-stage4.9-ext4-store-resize-noise-fix
(function () {
    "use strict";

    const AIWK = window.AIWK;

    const CONFIG_KEY = "chart_demo_config_v082";
    const DEFAULT_CONFIG = {
        title: "AIWK 차트 MVP",
        template: "dev",
        skin: "nssb-dark",
        chartType: "line",
        dataSource: "sample.inline",
        actionMode: "monitor_only",
        data: [
            { label: "09:00", value: 22 },
            { label: "10:00", value: 26 },
            { label: "11:00", value: 24 },
            { label: "12:00", value: 31 },
            { label: "13:00", value: 35 },
            { label: "14:00", value: 33 }
        ]
    };

    function clone(obj) {
        return JSON.parse(JSON.stringify(obj));
    }

    function loadConfig() {
        try {
            const raw = localStorage.getItem(CONFIG_KEY);
            if (!raw) return clone(DEFAULT_CONFIG);
            const cfg = JSON.parse(raw);
            return normalizeConfig(cfg);
        } catch (err) {
            return clone(DEFAULT_CONFIG);
        }
    }

    function saveConfig(cfg) {
        const next = normalizeConfig(cfg);
        localStorage.setItem(CONFIG_KEY, JSON.stringify(next));
        return next;
    }

    function normalizeConfig(cfg) {
        cfg = cfg && typeof cfg === "object" ? cfg : {};
        const out = clone(DEFAULT_CONFIG);
        Object.keys(cfg).forEach(function (k) { out[k] = cfg[k]; });
        out.title = String(out.title || DEFAULT_CONFIG.title).trim() || DEFAULT_CONFIG.title;
        out.template = ["dev", "viewer"].includes(String(out.template || "")) ? String(out.template) : "dev";
        out.skin = ["nssb-dark", "nssb-light", "cyan", "dark", "light", "purple", "clean"].includes(String(out.skin || "")) ? String(out.skin) : "nssb-dark";
        out.chartType = ["line", "bar"].includes(String(out.chartType || "")) ? String(out.chartType) : "line";
        out.dataSource = String(out.dataSource || "sample.inline").trim() || "sample.inline";
        out.actionMode = String(out.actionMode || "monitor_only").trim() || "monitor_only";
        if (!Array.isArray(out.data)) out.data = clone(DEFAULT_CONFIG.data);
        out.data = out.data.map(function (row, idx) {
            row = row && typeof row === "object" ? row : {};
            return { label: String(row.label || (idx + 1)), value: Number(row.value || 0) || 0 };
        });
        if (!out.data.length) out.data = clone(DEFAULT_CONFIG.data);
        return out;
    }

    function el(tag, cls, text) {
        const node = document.createElement(tag);
        if (cls) node.className = cls;
        if (text !== undefined) node.textContent = text;
        return node;
    }

    function button(text, action) {
        const b = document.createElement("button");
        b.type = "button";
        b.className = "aiwk-btn";
        b.dataset.chartAction = action;
        b.textContent = text;
        return b;
    }

    function input(label, value, key) {
        const wrap = el("label", "aiwk-chart-field select-text");
        const t = el("span", "select-text", label);
        const i = document.createElement("input");
        i.className = "aiwk-chart-input";
        i.value = value || "";
        i.dataset.chartKey = key;
        wrap.appendChild(t);
        wrap.appendChild(i);
        return wrap;
    }

    function select(label, value, key, items) {
        const wrap = el("label", "aiwk-chart-field select-text");
        const t = el("span", "select-text", label);
        const s = document.createElement("select");
        s.className = "aiwk-chart-input";
        s.dataset.chartKey = key;
        items.forEach(function (item) {
            const opt = document.createElement("option");
            opt.value = item.value;
            opt.textContent = item.label;
            if (item.value === value) opt.selected = true;
            s.appendChild(opt);
        });
        wrap.appendChild(t);
        wrap.appendChild(s);
        return wrap;
    }

    function svgChart(cfg) {
        const width = 520;
        const height = 210;
        const padL = 34;
        const padR = 18;
        const padT = 18;
        const padB = 34;
        const values = cfg.data.map(function (r) { return Number(r.value || 0) || 0; });
        const max = Math.max(1, Math.max.apply(null, values));
        const min = Math.min(0, Math.min.apply(null, values));
        const plotW = width - padL - padR;
        const plotH = height - padT - padB;
        function x(i) { return padL + (cfg.data.length <= 1 ? plotW / 2 : (plotW * i / (cfg.data.length - 1))); }
        function y(v) { return padT + plotH - ((v - min) / (max - min || 1)) * plotH; }
        const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("viewBox", "0 0 " + width + " " + height);
        svg.setAttribute("class", "aiwk-chart-svg");
        const grid = document.createElementNS(svg.namespaceURI, "g");
        [0, 0.25, 0.5, 0.75, 1].forEach(function (p) {
            const yy = padT + plotH * p;
            const line = document.createElementNS(svg.namespaceURI, "line");
            line.setAttribute("x1", padL);
            line.setAttribute("x2", width - padR);
            line.setAttribute("y1", yy);
            line.setAttribute("y2", yy);
            line.setAttribute("class", "aiwk-chart-grid");
            grid.appendChild(line);
        });
        svg.appendChild(grid);
        if (cfg.chartType === "bar") {
            const gap = 8;
            const bw = Math.max(12, (plotW - gap * (cfg.data.length - 1)) / cfg.data.length);
            cfg.data.forEach(function (r, i) {
                const bar = document.createElementNS(svg.namespaceURI, "rect");
                const xx = padL + i * (bw + gap);
                const yy = y(r.value);
                bar.setAttribute("x", xx);
                bar.setAttribute("y", yy);
                bar.setAttribute("width", bw);
                bar.setAttribute("height", Math.max(2, padT + plotH - yy));
                bar.setAttribute("rx", 6);
                bar.setAttribute("class", "aiwk-chart-bar");
                svg.appendChild(bar);
            });
        } else {
            const points = cfg.data.map(function (r, i) { return x(i) + "," + y(r.value); }).join(" ");
            const poly = document.createElementNS(svg.namespaceURI, "polyline");
            poly.setAttribute("points", points);
            poly.setAttribute("class", "aiwk-chart-line");
            svg.appendChild(poly);
            cfg.data.forEach(function (r, i) {
                const c = document.createElementNS(svg.namespaceURI, "circle");
                c.setAttribute("cx", x(i));
                c.setAttribute("cy", y(r.value));
                c.setAttribute("r", 4);
                c.setAttribute("class", "aiwk-chart-dot");
                svg.appendChild(c);
            });
        }
        cfg.data.forEach(function (r, i) {
            const tx = document.createElementNS(svg.namespaceURI, "text");
            tx.setAttribute("x", cfg.chartType === "bar" ? (padL + i * (plotW / cfg.data.length) + plotW / cfg.data.length / 2) : x(i));
            tx.setAttribute("y", height - 10);
            tx.setAttribute("text-anchor", "middle");
            tx.setAttribute("class", "aiwk-chart-label");
            tx.textContent = r.label;
            svg.appendChild(tx);
        });
        return svg;
    }

    function applySkin(box, skin) {
        box.classList.remove("aiwk-chart-skin-nssb-dark", "aiwk-chart-skin-nssb-light", "aiwk-chart-skin-dark", "aiwk-chart-skin-light", "aiwk-chart-skin-purple", "aiwk-chart-skin-clean");
        box.classList.add("aiwk-chart-skin-" + skin);
    }

    function renderChart(box, cfg) {
        box.innerHTML = "";
        applySkin(box, cfg.skin);
        const header = el("div", "aiwk-chart-head select-text");
        const title = el("div", "aiwk-chart-title select-text", cfg.title);
        const meta = el("div", "aiwk-chart-meta select-text", "template=" + cfg.template + " / skin=" + cfg.skin + " / source=" + cfg.dataSource + " / action=" + cfg.actionMode);
        header.appendChild(title);
        header.appendChild(meta);
        box.appendChild(header);
        box.appendChild(svgChart(cfg));
    }

    function readDevForm(root, cfg) {
        const next = clone(cfg);
        root.querySelectorAll("[data-chart-key]").forEach(function (node) {
            const key = node.dataset.chartKey;
            if (key === "data") return;
            next[key] = node.value;
        });
        const dataText = root.querySelector("[data-chart-key='data']");
        if (dataText) {
            try {
                next.data = JSON.parse(dataText.value || "[]");
            } catch (err) {
                throw new Error("CHART_DATA_JSON_INVALID: " + err.message);
            }
        }
        return normalizeConfig(next);
    }

    function mountDev(ctx, cfg) {
        const root = el("div", "aiwk-chart-demo aiwk-chart-dev select-text");
        const note = el("div", "aiwk-chart-note select-text", "개발용 template: 차트 종류, 스킨, 데이터, 외부연동 키, 액션모드, JSON 설정을 수정합니다. 완료 후 운영용으로 전환합니다.");
        const form = el("div", "aiwk-chart-form");
        form.appendChild(input("제목", cfg.title, "title"));
        form.appendChild(select("템플릿", cfg.template, "template", [{ value:"dev", label:"개발용" }, { value:"viewer", label:"운영용" }]));
        form.appendChild(select("스킨", cfg.skin, "skin", [{ value:"nssb-dark", label:"nssb-dark" }, { value:"nssb-light", label:"nssb-light" }, { value:"purple", label:"purple" }, { value:"dark", label:"dark" }, { value:"light", label:"light" }, { value:"clean", label:"clean" }]));
        form.appendChild(select("차트", cfg.chartType, "chartType", [{ value:"line", label:"line" }, { value:"bar", label:"bar" }]));
        form.appendChild(input("데이터 소스", cfg.dataSource, "dataSource"));
        form.appendChild(input("액션 모드", cfg.actionMode, "actionMode"));
        const data = el("label", "aiwk-chart-field aiwk-chart-field-wide select-text");
        data.appendChild(el("span", "select-text", "데이터 JSON"));
        const ta = document.createElement("textarea");
        ta.className = "aiwk-textarea aiwk-chart-data";
        ta.rows = 5;
        ta.dataset.chartKey = "data";
        ta.value = JSON.stringify(cfg.data, null, 2);
        data.appendChild(ta);
        form.appendChild(data);
        const actions = el("div", "aiwk-chart-actions");
        actions.appendChild(button("적용", "apply"));
        actions.appendChild(button("저장", "save"));
        actions.appendChild(button("운영용 전환", "viewer"));
        actions.appendChild(button("샘플복원", "sample"));
        const chartBox = el("div", "aiwk-chart-box");
        const msg = el("div", "aiwk-chart-message select-text", "");
        root.appendChild(note);
        root.appendChild(form);
        root.appendChild(actions);
        root.appendChild(msg);
        root.appendChild(chartBox);
        ctx.body.appendChild(root);
        renderChart(chartBox, cfg);
        actions.addEventListener("click", function (ev) {
            const b = ev.target.closest("button[data-chart-action]");
            if (!b) return;
            try {
                let next = readDevForm(root, cfg);
                if (b.dataset.chartAction === "sample") next = clone(DEFAULT_CONFIG);
                if (b.dataset.chartAction === "viewer") next.template = "viewer";
                if (b.dataset.chartAction === "save" || b.dataset.chartAction === "viewer" || b.dataset.chartAction === "sample") next = saveConfig(next);
                cfg = normalizeConfig(next);
                if (cfg.template === "viewer") {
                    ctx.body.innerHTML = "";
                    mountViewer(ctx, cfg);
                    ctx.status.textContent = "운영용 template 적용 완료";
                    return;
                }
                renderChart(chartBox, cfg);
                msg.textContent = "OK: " + b.textContent + " / " + new Date().toLocaleTimeString();
                ctx.status.textContent = "chart dev updated";
            } catch (err) {
                msg.textContent = "ERROR: " + err.message;
                ctx.status.textContent = "chart dev stopped";
            }
        });
    }

    function mountViewer(ctx, cfg) {
        const root = el("div", "aiwk-chart-demo aiwk-chart-viewer select-text");
        const chartBox = el("div", "aiwk-chart-box");
        const actions = el("div", "aiwk-chart-actions");
        actions.appendChild(button("개발용 전환", "dev"));
        root.appendChild(chartBox);
        root.appendChild(actions);
        ctx.body.appendChild(root);
        renderChart(chartBox, cfg);
        actions.addEventListener("click", function (ev) {
            const b = ev.target.closest("button[data-chart-action]");
            if (!b) return;
            if (b.dataset.chartAction === "dev") {
                const next = saveConfig(Object.assign({}, cfg, { template: "dev" }));
                ctx.body.innerHTML = "";
                mountDev(ctx, next);
                ctx.status.textContent = "개발용 template 적용 완료";
            }
        });
        ctx.status.textContent = "chart viewer ready";
    }

    function injectStyleOnce() {
        if (document.getElementById("aiwk-chart-demo-style-v077")) return;
        const st = document.createElement("style");
        st.id = "aiwk-chart-demo-style-v077";
        st.textContent = [
            "#aiwk-ext4-root .aiwk-chart-demo{font-size:12px;line-height:1.35;user-select:text;-webkit-user-select:text;}",
            "#aiwk-ext4-root .aiwk-chart-note{border:1px dashed currentColor;border-radius:8px;padding:6px 8px;margin-bottom:6px;opacity:.86;}",
            "#aiwk-ext4-root .aiwk-chart-form{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:6px;}",
            "#aiwk-ext4-root .aiwk-chart-field{display:flex;flex-direction:column;gap:2px;}",
            "#aiwk-ext4-root .aiwk-chart-field-wide{grid-column:1 / -1;}",
            "#aiwk-ext4-root .aiwk-chart-input{border:1px solid rgba(148,163,184,.55);border-radius:7px;padding:4px 6px;background:rgba(15,23,42,.10);color:inherit;user-select:text;}",
            "#aiwk-ext4-root .aiwk-chart-actions{display:flex;flex-wrap:wrap;gap:5px;margin:5px 0;}",
            "#aiwk-ext4-root .aiwk-chart-box{border:1px solid rgba(148,163,184,.35);border-radius:12px;padding:8px;margin-top:6px;overflow:hidden;}",
            "#aiwk-ext4-root .aiwk-chart-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:4px;}",
            "#aiwk-ext4-root .aiwk-chart-title{font-weight:900;font-size:14px;}",
            "#aiwk-ext4-root .aiwk-chart-meta{font-size:10px;opacity:.74;text-align:right;}",
            "#aiwk-ext4-root .aiwk-chart-svg{width:100%;height:auto;display:block;}",
            "#aiwk-ext4-root .aiwk-chart-grid{stroke:currentColor;stroke-opacity:.16;stroke-width:1;}",
            "#aiwk-ext4-root .aiwk-chart-line{fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;}",
            "#aiwk-ext4-root .aiwk-chart-dot{fill:currentColor;}",
            "#aiwk-ext4-root .aiwk-chart-bar{fill:currentColor;opacity:.82;}",
            "#aiwk-ext4-root .aiwk-chart-label{fill:currentColor;font-size:10px;opacity:.72;}",
            "#aiwk-ext4-root .aiwk-chart-skin-purple{color:#d8b4fe;background:linear-gradient(135deg,rgba(88,28,135,.32),rgba(15,23,42,.18));}",
            "#aiwk-ext4-root .aiwk-chart-skin-dark{color:#e5e7eb;background:rgba(15,23,42,.45);}",
            "#aiwk-ext4-root .aiwk-chart-skin-light{color:#0f172a;background:rgba(255,255,255,.72);}",
            "#aiwk-ext4-root .aiwk-chart-skin-clean{color:#111827;background:rgba(250,250,250,.72);box-shadow:none;}",
            "#aiwk-ext4-root .aiwk-chart-message{min-height:16px;font-size:11px;opacity:.88;}"
        ].join("\n");
        document.documentElement.appendChild(st);
    }

    AIWK.modules.register("chart.demo", {
        name: "chart.demo",
        meta: {
            title: "차트 template/skin MVP",
            version: "v078-stage2.5-chart-lab-apex-3d-d3",
            templates: ["dev", "viewer"],
            skins: ["nssb-dark", "nssb-light", "cyan", "purple", "dark", "light", "clean"],
            permissions: ["read_config", "write_config"],
            node_ready: true
        },
        run: async function (ctx) {
            const cfg = loadConfig();
            return { ok: 1, module: "chart.demo", win_id: ctx.win.id, template: cfg.template, skin: cfg.skin, chartType: cfg.chartType, data_count: cfg.data.length };
        },
        mount: function (ctx) {
            injectStyleOnce();
            let cfg = loadConfig();
            if (ctx.win && ctx.win.id === "chart-viewer-win") cfg.template = "viewer";
            if (ctx.win && ctx.win.id === "chart-dev-win") cfg.template = "dev";
            if (cfg.template === "viewer") mountViewer(ctx, cfg);
            else mountDev(ctx, cfg);
        }
    });
}());
