/* ============================================================
   twin.js — Protein Twin 탭 (라이브 ODE + Chart.js)
   ============================================================ */
(function () {
  'use strict';

  const DISEASE_INTERVENTIONS = {
    "Healthy": [],
    "Androgenetic Alopecia": ["finasteride", "dutasteride", "AR_antagonist", "minoxidil", "anti_DKK1", "wnt_agonist", "exosome_MSC"],
    "Alopecia Areata": ["JAK_inhibitor", "corticosteroid", "exosome_MSC"],
    "Chemotherapy-induced Alopecia": ["CDK46_inhibitor", "scalp_cooling", "PTH_CBD"],
  };
  const KEY_PROTEINS = ["β-catenin (CTNNB1)", "AR/DHT (AR)", "JAK-STAT (STAT1)", "p53/apoptosis (TP53)", "VEGFA (DP)"];
  const PCOLORS = ["#2f63c8", "#c8401f", "#b07a12", "#7c3aed", "#1f8a5b", "#0e7490", "#c2367f", "#5b6470", "#c0561f"];

  let state = { disease: "Androgenetic Alopecia", interventions: [], live: {} };
  let charts = { hair: null, prot: null, compare: null };

  function el(id) { return document.getElementById(id); }

  function init() {
    buildDiseaseSeg();
    buildInterventionChips();
    bindSliders();
    el('protein-trace-mode').addEventListener('change', render);
    el('btn-reset-live').addEventListener('click', () => {
      state.live = {}; syncSliders(); render();
    });
    render();
  }

  function buildDiseaseSeg() {
    const seg = el('disease-seg');
    const diseases = Store.scenarios.diseases || {};
    seg.innerHTML = '';
    Object.keys(DISEASE_INTERVENTIONS).forEach(dis => {
      const meta = diseases[dis] || {};
      const b = document.createElement('button');
      b.className = 'seg-btn' + (dis === state.disease ? ' active' : '');
      b.innerHTML = `${meta.label || dis}<span class="seg-sub">${meta.desc || ''}</span>`;
      b.onclick = () => {
        state.disease = dis; state.interventions = []; state.live = {};
        document.querySelectorAll('#disease-seg .seg-btn').forEach(x => x.classList.remove('active'));
        b.classList.add('active');
        buildInterventionChips(); syncSliders(); render();
      };
      seg.appendChild(b);
    });
  }

  function buildInterventionChips() {
    const list = el('intervention-list');
    const ivs = DISEASE_INTERVENTIONS[state.disease] || [];
    const meta = Store.scenarios.interventions || {};
    list.innerHTML = '';
    if (!ivs.length) { list.innerHTML = '<span class="panel-subtitle">이 상태에는 개입이 없습니다 (기준선).</span>'; return; }
    ivs.forEach(iv => {
      const m = meta[iv] || { label: iv };
      const c = document.createElement('div');
      c.className = 'chip' + (state.interventions.includes(iv) ? ' active' : '');
      c.textContent = m.label || iv;
      c.onclick = () => {
        const i = state.interventions.indexOf(iv);
        if (i >= 0) state.interventions.splice(i, 1); else state.interventions.push(iv);
        c.classList.toggle('active');
        render();
      };
      list.appendChild(c);
    });
  }

  function bindSliders() {
    [['slider-and', 'AND', 'val-and'], ['slider-inf', 'INF', 'val-inf'],
     ['slider-wnt', 'uWnt', 'val-wnt'], ['slider-dp', 'uDP', 'val-dp']].forEach(([sid, key, vid]) => {
      el(sid).addEventListener('input', e => {
        state.live[key] = parseFloat(e.target.value);
        el(vid).textContent = (+e.target.value).toFixed(2);
        render(true);
      });
    });
  }

  // 현재 질환+개입의 baseline drive 로 슬라이더 동기화
  function syncSliders() {
    const d = TwinEngine.buildDrive(state.disease, state.interventions);
    const map = { 'slider-and': ['AND', 'val-and'], 'slider-inf': ['INF', 'val-inf'],
                  'slider-wnt': ['uWnt', 'val-wnt'], 'slider-dp': ['uDP', 'val-dp'] };
    Object.entries(map).forEach(([sid, [k, vid]]) => {
      const v = state.live[k] !== undefined ? state.live[k] : d[k];
      el(sid).value = v; el(vid).textContent = (+v).toFixed(2);
    });
  }

  function render(fromSlider) {
    if (!fromSlider) syncSliders();
    const overrides = Object.keys(state.live).length ? state.live : null;
    const r = TwinEngine.run(state.disease, state.interventions, { overrides });

    renderHairChart(r);
    renderProteinChart(r);
    renderMetrics(r);
    renderTracked();
    renderCompare();
    el('disease-desc').textContent = (Store.scenarios.diseases[state.disease] || {}).desc || '';
  }

  function renderHairChart(r) {
    const ctx = el('chart-hair');
    const data = {
      labels: r.t,
      datasets: [{
        label: '모발 밀도 (%)', data: r.states.HairDensity,
        borderColor: '#c8401f', backgroundColor: 'rgba(200,64,31,.10)',
        fill: true, tension: .25, pointRadius: 0, borderWidth: 2.5,
      }],
    };
    const opts = {
      responsive: true, maintainAspectRatio: false,
      scales: {
        y: { min: 0, max: 105, ticks: { color: '#6b655a', callback: v => v + '%' }, grid: { color: 'rgba(0,0,0,.08)' } },
        x: { ticks: { color: '#6b655a', maxTicksLimit: 8, callback: (v, i) => r.t[i] + 'd' }, grid: { display: false } },
      },
      plugins: { legend: { display: false } },
    };
    if (charts.hair) { charts.hair.data = data; charts.hair.update('none'); }
    else charts.hair = new Chart(ctx, { type: 'line', data, options: opts });
  }

  function renderProteinChart(r) {
    const ctx = el('chart-proteins');
    const mode = el('protein-trace-mode').value;
    const keys = mode === 'all' ? Object.keys(r.proteins) : KEY_PROTEINS;
    const datasets = keys.map((k, i) => ({
      label: k, data: r.proteins[k],
      borderColor: PCOLORS[i % PCOLORS.length], borderWidth: 2,
      pointRadius: 0, tension: .25, fill: false,
    }));
    const data = { labels: r.t, datasets };
    const opts = {
      responsive: true, maintainAspectRatio: false,
      scales: {
        y: { ticks: { color: '#6b655a' }, grid: { color: 'rgba(0,0,0,.08)' }, title: { display: true, text: '상대 활성', color: '#6b655a' } },
        x: { ticks: { color: '#6b655a', maxTicksLimit: 8, callback: (v, i) => r.t[i] + 'd' }, grid: { display: false } },
      },
      plugins: { legend: { labels: { color: '#4a463d', boxWidth: 12, font: { size: 11 } } } },
    };
    if (charts.prot) { charts.prot.data = data; charts.prot.options = opts; charts.prot.update('none'); }
    else charts.prot = new Chart(ctx, { type: 'line', data, options: opts });
  }

  function renderMetrics(r) {
    const m = r.metrics;
    const cls = v => v >= 70 ? 'good' : v >= 40 ? 'warn' : 'bad';
    const cards = [
      { v: m.final_hair_density_pct + '%', l: '최종 모발 밀도', c: cls(m.final_hair_density_pct) },
      { v: m.min_hair_density_pct + '%', l: '최저 밀도', c: cls(m.min_hair_density_pct) },
      { v: (m.anagen_fraction * 100).toFixed(0) + '%', l: 'Anagen 비율', c: cls(m.anagen_fraction * 100) },
      { v: m.AND_load.toFixed(2) + '/' + m.INF_load.toFixed(2), l: '안드로겐/염증 부하', c: '' },
    ];
    el('twin-metrics').innerHTML = cards.map(c =>
      `<div class="metric-card ${c.c}"><div class="mv">${c.v}</div><div class="ml">${c.l}</div></div>`).join('');
  }

  function renderTracked() {
    const meta = Store.scenarios.interventions || {};
    const genes = new Set();
    state.interventions.forEach(iv => (meta[iv] && meta[iv].genes || []).forEach(g => genes.add(g)));
    const box = el('tracked-genes-list');
    if (!genes.size) { box.innerHTML = '<span class="panel-subtitle">개입을 선택하면 표적 단백질이 표시됩니다.</span>'; return; }
    box.innerHTML = [...genes].map(g => `<span class="gene-pill" data-gene="${g}">${g}</span>`).join('');
    box.querySelectorAll('.gene-pill').forEach(p => p.onclick = () => window.openProtein && window.openProtein(p.dataset.gene));
  }

  function renderCompare() {
    const ivsList = [[]].concat((DISEASE_INTERVENTIONS[state.disease] || []).map(iv => [iv]));
    if (state.disease === "Androgenetic Alopecia") ivsList.push(["finasteride", "minoxidil"]);
    if (state.disease === "Alopecia Areata") ivsList.push(["JAK_inhibitor", "corticosteroid"]);
    const meta = Store.scenarios.interventions || {};
    const labels = [], vals = [], colors = [];
    ivsList.forEach(ivs => {
      const r = TwinEngine.run(state.disease, ivs, { days: 240 });
      const v = r.metrics.final_hair_density_pct;
      labels.push(ivs.length ? ivs.map(i => (meta[i] || {}).label || i).join('+').replace(/\(.*?\)/g, '').slice(0, 16) : '무처치');
      vals.push(v);
      colors.push(v >= 70 ? '#1f6d3a' : v >= 40 ? '#b07a12' : '#b3361b');
    });
    const ctx = el('chart-compare');
    const data = { labels, datasets: [{ data: vals, backgroundColor: colors, borderRadius: 5 }] };
    const opts = {
      indexAxis: 'y', responsive: true, maintainAspectRatio: false,
      scales: { x: { min: 0, max: 105, ticks: { color: '#6b655a', callback: v => v + '%' }, grid: { color: 'rgba(0,0,0,.08)' } },
                y: { ticks: { color: '#4a463d', font: { size: 10 } }, grid: { display: false } } },
      plugins: { legend: { display: false } },
    };
    if (charts.compare) { charts.compare.data = data; charts.compare.update('none'); }
    else charts.compare = new Chart(ctx, { type: 'bar', data, options: opts });
  }

  window.TwinTab = { init };
})();
