<!-- Pipeline Lineage Tab: 3-layer DAG visualization (server-rendered SVG) -->

<div class="card">
  <p class="card-header">Data Lineage
    <span class="text-xs font-normal text-slate ml-2">
      {{ node_count }} models &mdash; staging &rarr; foundation &rarr; serving
    </span>
    <span class="text-xs font-normal text-slate" style="margin-left:auto">
      hover to preview &middot; click to inspect
    </span>
  </p>
  <div style="overflow-x:auto;padding:1rem 0.5rem 0.5rem">
    {{ lineage_svg | safe }}
  </div>
</div>

<!-- Detail panel: fixed right, slides in on node click -->
<div id="ln-panel" style="
  position:fixed;top:0;right:0;bottom:0;width:320px;
  background:#fff;border-left:1px solid #E2E8F0;
  display:flex;flex-direction:column;
  transform:translateX(100%);
  transition:transform 0.2s cubic-bezier(0.4,0,0.2,1);
  z-index:200;overflow:hidden;
  box-shadow:-4px 0 24px rgba(0,0,0,0.06);
">
  <div style="padding:0.75rem 1rem;border-bottom:1px solid #F1F5F9;flex-shrink:0">
    <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.375rem">
      <span id="ln-model-name" style="
        font-family:'Commit Mono',ui-monospace,monospace;
        font-size:0.8125rem;font-weight:500;color:#1E293B;
        flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
      ">—</span>
      <button id="ln-close" style="
        background:none;border:none;cursor:pointer;color:#94A3B8;
        font-size:1rem;padding:2px 4px;border-radius:4px;line-height:1;
        transition:color 0.1s,background 0.1s;
      " title="Close (Esc)">✕</button>
    </div>
    <div style="display:flex;align-items:center;gap:0.5rem">
      <span id="ln-layer-chip" style="
        font-size:0.625rem;font-weight:700;letter-spacing:0.06em;
        text-transform:uppercase;padding:2px 7px;border-radius:99px;
      ">—</span>
      <span id="ln-mat" style="font-size:0.6875rem;color:#64748B"></span>
    </div>
  </div>
  <div id="ln-body" style="flex:1;overflow-y:auto"></div>
</div>

<!-- Hover tooltip -->
<div id="ln-tooltip" style="
  position:fixed;z-index:300;pointer-events:none;
  opacity:0;transition:opacity 0.08s;
  filter:drop-shadow(0 4px 14px rgba(0,0,0,0.14));
">
  <div id="ln-tt-inner" style="
    background:#0F172A;color:#fff;border-radius:8px;
    padding:10px 12px;min-width:190px;max-width:250px;
  "></div>
</div>

<style>
  .lineage-node { cursor: pointer; }
  .lineage-node rect:first-of-type { transition: filter 0.1s; }
  .lineage-node:hover rect:first-of-type { filter: brightness(0.92); }
  .lineage-node.ln-selected rect:first-of-type { filter: brightness(0.86) !important; }
  .lineage-edge { transition: stroke 0.12s, stroke-width 0.12s, opacity 0.12s; }
  .lineage-edge.hi { stroke: #1D4ED8 !important; stroke-width: 2 !important; marker-end: url(#arr-hi) !important; }
  .lineage-edge.dim { opacity: 0.1; }

  .ln-section { border-bottom: 1px solid #F1F5F9; padding: 0.75rem 1rem; }
  .ln-section:last-child { border-bottom: none; }
  .ln-label {
    font-size: 0.5875rem; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: #94A3B8; margin-bottom: 0.5rem;
  }
  .ln-schema-table { width: 100%; border-collapse: collapse; font-size: 0.6875rem; }
  .ln-schema-table th {
    text-align: left; font-weight: 600; color: #64748B;
    padding: 0 0 0.375rem; font-size: 0.5875rem; letter-spacing: 0.04em; text-transform: uppercase;
  }
  .ln-schema-table td { padding: 3px 4px 3px 0; vertical-align: middle; }
  .ln-schema-table tr + tr td { border-top: 1px solid #F1F5F9; }
  .ln-col-name { font-family: 'Commit Mono', ui-monospace, monospace; color: #1E293B; font-weight: 500; }
  .ln-col-type { font-family: 'Commit Mono', ui-monospace, monospace; color: #94A3B8; font-size: 0.625rem; }
  .ln-col-null { font-size: 0.5625rem; color: #CBD5E1; text-align: right; }
  .ln-col-null.yes { color: #D97706; }

  .ln-dep-item {
    display: flex; align-items: center; gap: 6px; padding: 4px 6px;
    border-radius: 5px; cursor: pointer;
    font-family: 'Commit Mono', ui-monospace, monospace;
    font-size: 0.6875rem; color: #334155; transition: background 0.1s;
  }
  .ln-dep-item:hover { background: #F8FAFC; }
  .ln-dep-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
  .ln-dep-dot.staging    { background: #16A34A; }
  .ln-dep-dot.foundation { background: #1D4ED8; }
  .ln-dep-dot.serving    { background: #D97706; }

  .ln-chip-staging    { background: #DCFCE7; color: #14532D; border: 1px solid #BBF7D0; }
  .ln-chip-foundation { background: #DBEAFE; color: #1E3A8A; border: 1px solid #BFDBFE; }
  .ln-chip-serving    { background: #FEF3C7; color: #78350F; border: 1px solid #FDE68A; }
</style>

<script>
(function () {
  var SCHEMA_BASE = "{{ url_for('pipeline.pipeline_lineage_schema', model='MODEL') }}".replace('/MODEL', '/');
  var svg = document.querySelector('.lineage-svg');
  if (!svg) return;
  var nodes = svg.querySelectorAll('.lineage-node');
  var edges = svg.querySelectorAll('.lineage-edge');
  var panel = document.getElementById('ln-panel');
  var panelBody = document.getElementById('ln-body');
  var tooltip = document.getElementById('ln-tooltip');
  var ttInner = document.getElementById('ln-tt-inner');
  var activeModel = null;
  var cache = {};

  // ── Helpers ────────────────────────────────────────────────────────────
  function layer(model) {
    if (model.startsWith('stg_')) return 'staging';
    if (model.startsWith('dim_') || model.startsWith('fct_')) return 'foundation';
    return 'serving';
  }

  function fmt(n) {
    return n == null ? '—' : Number(n).toLocaleString();
  }

  // ── Edge highlight ─────────────────────────────────────────────────────
  function highlightEdges(model) {
    edges.forEach(function (e) {
      if (e.dataset.from === model || e.dataset.to === model) {
        e.classList.add('hi'); e.classList.remove('dim');
      } else {
        e.classList.add('dim'); e.classList.remove('hi');
      }
    });
  }

  function clearEdges() {
    edges.forEach(function (e) { e.classList.remove('hi', 'dim'); });
  }

  // ── Schema fetch (cached) ──────────────────────────────────────────────
  function fetchSchema(model, cb) {
    if (cache[model]) { cb(cache[model]); return; }
    fetch(SCHEMA_BASE + encodeURIComponent(model))
      .then(function (r) { return r.json(); })
      .then(function (d) { cache[model] = d; cb(d); })
      .catch(function () {
        var fallback = { model: model, layer: layer(model), columns: [], upstream: [], downstream: [], row_count: null };
        cache[model] = fallback;
        cb(fallback);
      });
  }

  // ── Tooltip ────────────────────────────────────────────────────────────
  function showTooltip(data, x, y) {
    var cols = data.columns || [];
    var preview = cols.slice(0, 4);
    var extra = cols.length - 4;
    var lc = layer(data.model);
    var badge = lc === 'staging'
      ? 'background:rgba(22,163,74,0.25);color:#86EFAC'
      : lc === 'foundation'
        ? 'background:rgba(29,78,216,0.3);color:#93C5FD'
        : 'background:rgba(217,119,6,0.25);color:#FCD34D';

    ttInner.innerHTML =
      '<div style="display:flex;align-items:center;gap:6px;margin-bottom:8px;padding-bottom:7px;border-bottom:1px solid rgba(255,255,255,0.08)">' +
        '<span style="font-family:\'Commit Mono\',monospace;font-size:0.6875rem;font-weight:500;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + data.model + '</span>' +
        '<span style="font-size:0.5625rem;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;padding:2px 5px;border-radius:3px;flex-shrink:0;' + badge + '">' + lc + '</span>' +
      '</div>' +
      (cols.length === 0
        ? '<div style="font-size:0.6875rem;color:#475569;font-style:italic">schema in lakehouse only</div>'
        : preview.map(function (c) {
            return '<div style="display:flex;align-items:baseline;gap:6px;padding:2px 0">' +
              '<span style="font-family:\'Commit Mono\',monospace;font-size:0.6875rem;color:#CBD5E1;flex:1;overflow:hidden;text-overflow:ellipsis">' + c.name + '</span>' +
              '<span style="font-family:\'Commit Mono\',monospace;font-size:0.625rem;color:#475569;flex-shrink:0">' + c.type + '</span>' +
            '</div>';
          }).join('') +
          (extra > 0
            ? '<div style="font-size:0.625rem;color:#475569;margin-top:5px;padding-top:5px;border-top:1px solid rgba(255,255,255,0.06)">+' + extra + ' more &mdash; click to view all</div>'
            : '<div style="font-size:0.625rem;color:#334155;margin-top:5px;padding-top:5px;border-top:1px solid rgba(255,255,255,0.06);font-style:italic">click to inspect</div>')
      );

    var vw = window.innerWidth, vh = window.innerHeight;
    var left = x + 14, top = y - 10;
    if (left + 252 > vw - 12) left = x - 252 - 14;
    if (top + 160 > vh - 12) top = vh - 160 - 12;
    tooltip.style.left = left + 'px';
    tooltip.style.top = top + 'px';
    tooltip.style.opacity = '1';
  }

  function hideTooltip() { tooltip.style.opacity = '0'; }

  // ── Panel ──────────────────────────────────────────────────────────────
  function depItems(list) {
    if (!list.length) return '<div style="font-size:0.6875rem;color:#94A3B8;font-style:italic">none</div>';
    return list.map(function (d) {
      return '<div class="ln-dep-item" data-model="' + d + '"><span class="ln-dep-dot ' + layer(d) + '"></span>' + d + '</div>';
    }).join('');
  }

  function renderPanel(data) {
    var cols = data.columns || [];
    var lc = data.layer || layer(data.model);

    document.getElementById('ln-mat').textContent =
      cols.length > 0 ? 'table' : (lc === 'serving' ? '' : '');

    panelBody.innerHTML =
      '<div class="ln-section">' +
        '<div class="ln-label">Row count</div>' +
        (data.row_count != null
          ? '<div style="font-family:\'Commit Mono\',monospace;font-size:1rem;font-weight:500;color:#1E293B">' + fmt(data.row_count) +
            ' <span style="font-size:0.6875rem;font-weight:400;color:#64748B">rows</span></div>'
          : '<div style="font-size:0.6875rem;color:#94A3B8;font-style:italic">' +
            (lc !== 'serving' ? 'staging/foundation — in lakehouse.duckdb' : 'not yet built') + '</div>') +
      '</div>' +

      '<div class="ln-section">' +
        '<div class="ln-label">Schema &middot; ' + cols.length + ' columns</div>' +
        (cols.length > 0
          ? '<table class="ln-schema-table"><thead><tr><th>column</th><th>type</th><th style="text-align:right">null?</th></tr></thead><tbody>' +
            cols.map(function (c) {
              return '<tr><td class="ln-col-name">' + c.name + '</td><td class="ln-col-type">' + c.type + '</td>' +
                '<td class="ln-col-null' + (c.nullable ? ' yes' : '') + '">' + (c.nullable ? 'null' : '—') + '</td></tr>';
            }).join('') + '</tbody></table>'
          : '<div style="font-size:0.6875rem;color:#94A3B8;font-style:italic">schema available in lakehouse.duckdb only</div>') +
      '</div>' +

      '<div class="ln-section"><div class="ln-label">Upstream &middot; ' + (data.upstream || []).length + '</div>' + depItems(data.upstream || []) + '</div>' +
      '<div class="ln-section"><div class="ln-label">Downstream &middot; ' + (data.downstream || []).length + '</div>' + depItems(data.downstream || []) + '</div>';

    panelBody.querySelectorAll('.ln-dep-item').forEach(function (el) {
      el.addEventListener('click', function () { openPanel(el.dataset.model); });
    });
  }

  function openPanel(model) {
    activeModel = model;
    document.getElementById('ln-model-name').textContent = model;
    var chip = document.getElementById('ln-layer-chip');
    var lc = layer(model);
    chip.textContent = lc;
    chip.className = 'ln-chip-' + lc;
    chip.setAttribute('style',
      'font-size:0.625rem;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;padding:2px 7px;border-radius:99px;');
    document.getElementById('ln-mat').textContent = '';
    panelBody.innerHTML = '<div style="padding:2rem 1rem;font-size:0.75rem;color:#94A3B8">Loading\u2026</div>';
    panel.style.transform = 'translateX(0)';

    nodes.forEach(function (n) { n.classList.toggle('ln-selected', n.dataset.model === model); });
    highlightEdges(model);

    fetchSchema(model, renderPanel);
  }

  function closePanel() {
    panel.style.transform = 'translateX(100%)';
    clearEdges();
    nodes.forEach(function (n) { n.classList.remove('ln-selected'); });
    activeModel = null;
  }

  document.getElementById('ln-close').addEventListener('click', closePanel);
  document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closePanel(); });

  // ── Node wiring ────────────────────────────────────────────────────────
  nodes.forEach(function (g) {
    var model = g.dataset.model;

    g.addEventListener('mouseenter', function (e) {
      if (activeModel === null) highlightEdges(model);
      // prefetch so tooltip has data on arrive
      fetchSchema(model, function (data) { showTooltip(data, e.clientX, e.clientY); });
    });

    g.addEventListener('mousemove', function (e) {
      if (cache[model]) showTooltip(cache[model], e.clientX, e.clientY);
    });

    g.addEventListener('mouseleave', function () {
      hideTooltip();
      if (activeModel === null) clearEdges();
      else highlightEdges(activeModel);
    });

    g.addEventListener('click', function () {
      hideTooltip();
      if (activeModel === model) closePanel();
      else openPanel(model);
    });
  });
})();
</script>
