/* ─────────────────────────────────────────────────────────────
    06  HC900 태그 관리
───────────────────────────────────────────────────────────── */

let _pbSearchTimer;

const _PB_PARAM_CLASS = {
  PV:'p-PV', SP:'p-SP', OP:'p-OP', RSP:'p-PV', LSP1:'p-SP', LSP2:'p-SP',
  DEV:'p-OP', MODE:'p-MODE', STATUS:'p-STATUS', SIG:'p-SIG', VAR:'p-VAR',
};

async function pbApi(url, method='GET', body) {
  const opt = { method, headers:{'Content-Type':'application/json'} };
  if (body !== undefined) opt.body = JSON.stringify(body);
  return (await fetch(url, opt)).json();
}

async function pbLoadSummary() {
  const d = await pbApi('/api/hc900/tags/summary');
  document.getElementById('s-total').textContent    = d.total.toLocaleString();
  document.getElementById('s-active').textContent   = d.active.toLocaleString();
  document.getElementById('s-inactive').textContent = d.inactive.toLocaleString();
  document.getElementById('s-live').textContent     = d.liveCount.toLocaleString();
}

async function pbInitFilters() {
  const types = await pbApi('/api/hc900/tags/param-types');
  const ps = document.getElementById('f-param');
  if (!ps) return;
  types.forEach(t => {
    const o = document.createElement('option');
    o.value = o.textContent = t;
    ps.appendChild(o);
  });
  const ls = document.getElementById('f-loop');
  for (let i = 1; i <= 32; i++) {
    const o = document.createElement('option');
    o.value = i; o.textContent = `Loop #${i}`;
    ls.appendChild(o);
  }
  const ctrls = await pbApi('/api/hc900/tags/controller-ids');
  const cs = document.getElementById('f-ctrl');
  if (cs) {
    ctrls.forEach(id => {
      const o = document.createElement('option');
      o.value = o.textContent = id;
      cs.appendChild(o);
    });
  }
}

function pbBuildUrl() {
  const s = document.getElementById('f-search')?.value.trim() || '';
  const p = document.getElementById('f-param')?.value || '';
  const l = document.getElementById('f-loop')?.value || '';
  const c = document.getElementById('f-ctrl')?.value || '';
  const a = document.getElementById('f-active')?.value || '';
  let url = '/api/hc900/tags?';
  if (s) url += `search=${encodeURIComponent(s)}&`;
  if (p) url += `paramType=${encodeURIComponent(p)}&`;
  if (l) url += `loopNo=${l}&`;
  if (c) url += `controllerId=${encodeURIComponent(c)}&`;
  if (a) url += `active=${a}&`;
  return url;
}

async function pbReload() {
  const tbody = document.getElementById('pb-tbody');
  if (!tbody) return;
  tbody.innerHTML = '<tr><td colspan="11" style="text-align:center;padding:30px;color:#555">조회 중...</td></tr>';

  const data = await pbApi(pbBuildUrl());
  pbRenderTable(data);
  pbUpdateBulkBar();
}

function pbRenderTable(data) {
  const tbody = document.getElementById('pb-tbody');
  if (!tbody) return;
  if (!data.length) {
    tbody.innerHTML = '<tr><td colspan="11" style="text-align:center;padding:30px;color:#555">결과 없음</td></tr>';
    return;
  }
  const now = Date.now();
  tbody.innerHTML = data.map(r => {
    const pc = _PB_PARAM_CLASS[r.ParamType] || 'p-other';
    const val = r.LiveValue ?? '—';
    const ts = r.Timestamp ? new Date(r.Timestamp) : null;
    const fresh = ts && (now - ts.getTime()) < 30000;
    const tsStr = ts ? ts.toLocaleTimeString('ko-KR') : '—';
    const shortVal = val.length > 20 ? val.slice(0, 20) + '…' : val;
    return `<tr>
      <td><input type="checkbox" class="pb-rc" data-id="${r.Id}" onchange="pbUpdateBulkBar()"></td>
      <td style="color:#8cf;font-weight:bold">${r.TagName}</td>
      <td style="color:#aaa">${r.Hc900Tag}</td>
      <td><span class="pb-ctrl" data-id="${r.Id}" data-ctrl="${r.ControllerId}"
            style="cursor:pointer;color:#fa3;font-size:11px"
            onclick="pbEditCtrl(this)" title="클릭하여 컨트롤러 ID 변경">${r.ControllerId}</span></td>
      <td style="color:#888;font-size:11px">${r.ModbusAddrHex}</td>
      <td style="color:#666;font-size:11px">${r.DataType}</td>
      <td style="color:#666">${r.LoopNo ?? '—'}</td>
      <td><span class="param-badge ${pc}">${r.ParamType ?? '—'}</span></td>
      <td style="cursor:pointer;font-size:16px;color:${r.IsActive ? '#3c3' : '#444'}"
          onclick="pbToggleOne(${r.Id}, ${!r.IsActive})"
          title="${r.IsActive ? '클릭하면 비활성화' : '클릭하면 활성화'}">
        ${r.IsActive ? '●' : '○'}
      </td>
      <td style="color:${fresh ? '#eee' : '#444'};max-width:130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"
          title="${val}">${shortVal}</td>
      <td style="color:#666;font-size:11px">${tsStr}</td>
    </tr>`;
  }).join('');
}

async function pbToggleOne(id, active) {
  await pbApi(`/api/hc900/tags/${id}/active`, 'PUT', active);
  pbReload(); pbLoadSummary();
}

async function pbEditCtrl(el) {
  const id = +el.dataset.id;
  const old = el.dataset.ctrl;
  const inp = document.createElement('input');
  inp.type = 'text';
  inp.value = old;
  inp.style.cssText = 'width:50px;background:#111;border:1px solid #4af;color:#fa3;font-size:11px;padding:1px 4px;border-radius:2px;outline:none';
  el.replaceWith(inp);
  inp.focus();
  inp.select();

  const done = async (save) => {
    const val = inp.value.trim();
    if (save && val && val !== old) {
      await pbApi(`/api/hc900/tags/${id}/controller`, 'PUT', val);
      pbReload(); pbLoadSummary();
    } else {
      const span = document.createElement('span');
      span.className = 'pb-ctrl';
      span.dataset.id = id;
      span.dataset.ctrl = old;
      span.style.cssText = 'cursor:pointer;color:#fa3;font-size:11px';
      span.textContent = old;
      span.onclick = () => pbEditCtrl(span);
      inp.replaceWith(span);
    }
  };

  inp.addEventListener('blur', () => done(true));
  inp.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') { e.preventDefault(); inp.blur(); }
    if (e.key === 'Escape') { e.preventDefault(); done(false); }
  });
}

function pbToggleAll(chk) {
  document.querySelectorAll('.pb-rc').forEach(c => c.checked = chk.checked);
  pbUpdateBulkBar();
}

function pbUpdateBulkBar() {
  const n = document.querySelectorAll('.pb-rc:checked').length;
  const el = document.getElementById('pb-bulk-count');
  if (el) el.textContent = `${n}개 선택`;
  const bar = document.getElementById('pb-bulk-bar');
  if (bar) bar.style.display = n > 0 ? 'flex' : 'none';
}

function pbSelectedIds() {
  return [...document.querySelectorAll('.pb-rc:checked')].map(c => +c.dataset.id);
}

async function pbBulkSelected(active) {
  const ids = pbSelectedIds();
  if (!ids.length) return;
  await pbApi('/api/hc900/tags/bulk-active', 'POST', { active, ids });
  pbReload(); pbLoadSummary();
}

async function pbBulkFilter(active) {
  const p = document.getElementById('f-param')?.value || '';
  const l = document.getElementById('f-loop')?.value || '';
  if (!p && !l && !confirm(`필터 없이 전체 ${active ? '활성화' : '비활성화'}합니까?`)) return;
  await pbApi('/api/hc900/tags/bulk-active', 'POST',
    { active, paramType: p || null, loopNo: l ? +l : null });
  pbReload(); pbLoadSummary();
}

function pbScheduleReload() {
  clearTimeout(_pbSearchTimer);
  _pbSearchTimer = setTimeout(pbReload, 350);
}

// 탭 활성화 시 초기화
(function pbInit() {
  const pane = document.getElementById('pane-pb');
  if (!pane) return;

  const obs = new MutationObserver(() => {
    if (pane.classList.contains('active') && document.getElementById('pb-tbody')) {
      pbInitFilters().then(() => pbReload());
      pbLoadSummary();
      obs.disconnect();
    }
  });
  obs.observe(pane, { attributes: true, attributeFilter: ['class'] });

  // 이미 활성화된 경우
  if (pane.classList.contains('active') && document.getElementById('pb-tbody')) {
    pbInitFilters().then(() => pbReload());
    pbLoadSummary();
  }
})();
