{% extends "base.html" %}
{% block title %}Ontology{% endblock %}
{% block nav_ontology %}btn-active{% endblock %}
{% block main_class %}p-0{% endblock %}

{% block head %}
<style>
  #graph-root {
    display: flex;
    height: calc(100vh - 64px - 40px);
    min-height: 500px;
  }
  #cy-wrapper {
    flex: 1 1 auto;
    min-width: 0;
    position: relative;
  }
  #cy { width: 100%; height: 100%; }
  #cy-controls {
    position: absolute;
    bottom: 14px;
    right: 14px;
    z-index: 10;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  #cy-controls button {
    width: 30px; height: 30px;
    border-radius: 6px;
    border: 1px solid rgba(255,255,255,0.1);
    background: rgba(0,0,0,0.6);
    color: #fff;
    font-size: 16px;
    cursor: pointer;
  }
  #cy-controls button:hover { background: rgba(80,80,80,0.8); }
  #sidebar {
    width: 280px;
    flex-shrink: 0;
    overflow-y: auto;
    background: oklch(var(--b2, 20% 0 0));
    border-left: 1px solid oklch(var(--b3, 15% 0 0));
    padding: 1rem;
    font-size: 0.75rem;
  }
</style>
{% endblock %}

{% block content %}
<div class="px-4 pt-4 pb-2 flex items-center gap-4">
  <h1 class="text-lg font-bold font-mono">Domain Ontology</h1>
  <div class="flex gap-2 text-xs">
    <label class="flex items-center gap-1 cursor-pointer">
      <input type="checkbox" id="show-axioms" checked class="checkbox checkbox-xs">
      <span class="badge badge-primary badge-xs">Axioms</span>
    </label>
    <label class="flex items-center gap-1 cursor-pointer">
      <input type="checkbox" id="show-practices" checked class="checkbox checkbox-xs">
      <span class="badge badge-success badge-xs">Practices</span>
    </label>
    <label class="flex items-center gap-1 cursor-pointer">
      <input type="checkbox" id="show-tensions" checked class="checkbox checkbox-xs">
      <span class="badge badge-warning badge-xs">Tensions</span>
    </label>
  </div>
  {% if not has_root %}
  <div class="alert alert-warning alert-xs py-1 px-3 text-xs">
    --project-root not set — graph will be empty
  </div>
  {% endif %}
</div>

<div id="graph-root">
  <div id="cy-wrapper">
    <div id="cy"></div>
    <div id="cy-controls">
      <button onclick="cy.fit()" title="Fit">⊡</button>
      <button onclick="cy.zoom(cy.zoom()*1.25)" title="Zoom in">+</button>
      <button onclick="cy.zoom(cy.zoom()*0.8)" title="Zoom out">−</button>
      <button onclick="resetLayout()" title="Re-layout">↺</button>
    </div>
  </div>
  <div id="sidebar">
    <p class="text-base-content/40 text-xs mb-3">Click a node to inspect.</p>
    <div id="node-detail"></div>
  </div>
</div>

<script>
const GRAPH = {{ graph_json | safe }};
let cy = null;

function levelColor(level) {
  if (level === 'Axiom')    return '#6366f1';
  if (level === 'Practice') return '#22c55e';
  if (level === 'Tension')  return '#f59e0b';
  return '#6b7280';
}

function buildElements() {
  const nodes = (GRAPH.nodes || []).map(n => ({
    data: {
      id: n.id,
      label: n.name || n.id,
      level: n.level,
      description: n.description || '',
      color: levelColor(n.level),
      invariant: n.invariant || false,
      artifact_paths: n.artifact_paths || [],
    }
  }));
  const edges = (GRAPH.edges || []).map((e, i) => ({
    data: {
      id: 'e' + i,
      source: e.from,
      target: e.to,
      kind: e.kind,
      note: e.note || '',
      weight: e.weight,
    }
  }));
  return [...nodes, ...edges];
}

function initCytoscape() {
cy = cytoscape({
  container: document.getElementById('cy'),
  elements: buildElements(),
  style: [
    {
      selector: 'node',
      style: {
        'background-color': 'data(color)',
        'label': 'data(label)',
        'color': '#f1f5f9',
        'font-size': '8px',
        'font-family': 'ui-monospace, monospace',
        'text-valign': 'center',
        'text-halign': 'center',
        'text-wrap': 'wrap',
        'text-max-width': '56px',
        'text-overflow-wrap': 'anywhere',
        'width': 72,
        'height': 72,
        'border-width': 2,
        'border-color': 'rgba(255,255,255,0.15)',
      }
    },
    {
      selector: 'node[?invariant]',
      style: {
        'border-width': 3,
        'border-color': '#a5b4fc',
        'border-style': 'double',
      }
    },
    {
      selector: 'edge',
      style: {
        'width': 1.5,
        'line-color': 'rgba(156,163,175,0.4)',
        'target-arrow-color': 'rgba(156,163,175,0.6)',
        'target-arrow-shape': 'triangle',
        'curve-style': 'bezier',
        'arrow-scale': 0.8,
      }
    },
    {
      selector: 'node:selected',
      style: {
        'border-color': '#818cf8',
        'border-width': 3,
      }
    },
  ],
  layout: {
    name: 'cose',
    animate: false,
    nodeRepulsion: 12000,
    idealEdgeLength: 140,
    gravity: 0.15,
    numIter: 1000,
    fit: true,
    padding: 30,
  },
});

cy.on('tap', 'node', function(evt) {
  const d = evt.target.data();
  const paths = d.artifact_paths.length
    ? d.artifact_paths.map(p => `<code class="font-mono">${p}</code>`).join('<br>')
    : '<span class="text-base-content/30">—</span>';
  document.getElementById('node-detail').innerHTML = `
    <div class="mb-2">
      <span class="badge badge-xs" style="background:${d.color}">${d.level}</span>
      <span class="font-mono font-semibold ml-1">${d.id}</span>
    </div>
    <p class="font-semibold text-sm mb-1">${d.label}</p>
    <p class="text-base-content/60 mb-3">${d.description}</p>
    <div class="text-base-content/40 text-xs">${paths}</div>
  `;
});

cy.on('tap', function(evt) {
  if (evt.target === cy) document.getElementById('node-detail').innerHTML = '';
});
} // end initCytoscape

function resetLayout() {
  if (cy) cy.layout({ name: 'cose', animate: true, nodeRepulsion: 12000, idealEdgeLength: 140, gravity: 0.15, numIter: 1000 }).run();
}

// Filter checkboxes
function applyFilters() {
  if (!cy) return;
  const showAxioms    = document.getElementById('show-axioms').checked;
  const showPractices = document.getElementById('show-practices').checked;
  const showTensions  = document.getElementById('show-tensions').checked;
  cy.nodes().forEach(n => {
    const l = n.data('level');
    const vis = (l === 'Axiom' && showAxioms)
             || (l === 'Practice' && showPractices)
             || (l === 'Tension' && showTensions)
             || (!['Axiom','Practice','Tension'].includes(l));
    n.style('display', vis ? 'element' : 'none');
  });
  cy.edges().forEach(e => {
    const srcVis = e.source().style('display') !== 'none';
    const tgtVis = e.target().style('display') !== 'none';
    e.style('display', srcVis && tgtVis ? 'element' : 'none');
  });
}

['show-axioms','show-practices','show-tensions'].forEach(id => {
  document.getElementById(id).addEventListener('change', applyFilters);
});

if (typeof cytoscape !== 'undefined') {
  initCytoscape();
} else {
  const s = document.createElement('script');
  s.src = 'https://cdn.jsdelivr.net/npm/cytoscape@3.30.2/dist/cytoscape.min.js';
  s.onload = initCytoscape;
  document.head.appendChild(s);
}
</script>
{% endblock %}
