/* Deep pipeline flow explorer */

const FLOW_TABS = ['Uitleg', 'Code', 'Data', 'Artefacten', 'Runtime'];

function nodeById(catalog, id) {
  return (catalog.nodes || []).find(n => n.id === id) || null;
}

function nodeVisibleInMode(node, flowMode) {
  const modes = node.modes || ['pand_scan'];
  return modes.includes(flowMode);
}

function groupNodes(catalog, groupId, flowMode) {
  return (catalog.nodes || []).filter(n => n.group === groupId && nodeVisibleInMode(n, flowMode));
}

function FlowNode({ node, selected, traceRows, onClick }) {
  const trace = traceRows.find(r => r.node_id === node.id);
  const status = trace ? trace.status : null;
  const cls = [
    'bd-flow-node',
    selected ? 'is-selected' : '',
    status ? 'has-trace' : '',
    status ? `is-${status}` : '',
  ].filter(Boolean).join(' ');
  return (
    <button type="button" className={cls} onClick={() => onClick(node.id)}>
      <span className="bd-flow-node-kind">{node.kind}</span>
      <strong>{node.title}</strong>
      <span>{node.function || node.module}</span>
      {trace && <em>{trace.duration_ms || 0} ms</em>}
    </button>
  );
}

function FlowDetail({ node, activeTab, setActiveTab, traceRows }) {
  if (!node) return <Empty icon="workflow" title="Selecteer een pipeline-stap" />;
  const rows = traceRows.filter(r => r.node_id === node.id);
  const latest = rows[rows.length - 1] || null;
  return (
    <aside className="bd-flow-detail">
      <div className="bd-flow-detail-head">
        <span>{node.group}</span>
        <h2>{node.title}</h2>
        <p>{node.module}{node.function ? ` - ${node.function}()` : ''}</p>
      </div>
      <div className="bd-flow-tabs">
        {FLOW_TABS.map(tab => (
          <button key={tab} type="button" className={activeTab === tab ? 'is-active' : ''} onClick={() => setActiveTab(tab)}>
            {tab}
          </button>
        ))}
      </div>
      <div className="bd-flow-detail-body">
        {activeTab === 'Uitleg' && (
          <>
            <h3>Wat gebeurt hier?</h3>
            <p>{node.description}</p>
            <h3>Beslissingen</h3>
            {(node.decisions || []).length ? <ul>{node.decisions.map(x => <li key={x}>{x}</li>)}</ul> : <p>Geen aparte beslissingen.</p>}
            <h3>Foutpaden</h3>
            {(node.failure_modes || []).length ? <ul>{node.failure_modes.map(x => <li key={x}>{x}</li>)}</ul> : <p>Geen specifiek foutpad beschreven.</p>}
          </>
        )}
        {activeTab === 'Code' && (
          <>
            <h3>Codepad</h3>
            <dl className="bd-flow-kv">
              <dt>Module</dt><dd>{node.module}</dd>
              <dt>Functie</dt><dd>{node.function || '-'}</dd>
              <dt>Caller</dt><dd>{node.caller || '-'}</dd>
            </dl>
          </>
        )}
        {activeTab === 'Data' && (
          <div className="bd-flow-data-grid">
            <section><h3>Input</h3><ul>{(node.inputs || []).map(x => <li key={x}>{x}</li>)}</ul></section>
            <section><h3>Output</h3><ul>{(node.outputs || []).map(x => <li key={x}>{x}</li>)}</ul></section>
          </div>
        )}
        {activeTab === 'Artefacten' && (
          latest && latest.artifact_path
            ? <p className="bd-flow-artifact">{latest.artifact_path}</p>
            : <p>Geen artifact voor deze node geselecteerd of trace ontbreekt.</p>
        )}
        {activeTab === 'Runtime' && (
          rows.length ? (
            <div className="bd-flow-runtime">
              {rows.map(r => (
                <div key={r.id} className="bd-flow-runtime-row">
                  <Badge kind={r.status === 'fout' ? 'error' : r.status === 'bezig' ? 'info' : 'success'}>{r.status}</Badge>
                  <span>{r.duration_ms || 0} ms</span>
                  {r.fout_melding && <strong>{r.fout_melding}</strong>}
                </div>
              ))}
            </div>
          ) : <p>Geen trace voor deze run.</p>
        )}
      </div>
    </aside>
  );
}

function SchermFlow() {
  const [catalog, setCatalog] = useState({groups: [], nodes: [], edges: []});
  const [flowMode, setFlowMode] = useState('pand_scan');
  const [selectedNodeId, setSelectedNodeId] = useState(null);
  const [activeGroup, setActiveGroup] = useState('foto');
  const [activeTab, setActiveTab] = useState('Uitleg');
  const [traceRows, setTraceRows] = useState([]);
  const [selectedTaakId, setSelectedTaakId] = useState('');
  const [selectedPandId, setSelectedPandId] = useState('');
  const [traceLaden, setTraceLaden] = useState(false);
  const [fout, setFout] = useState(null);

  useEffect(() => {
    fetch(`${API}/pipeline/flow-catalog`)
      .then(r => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`)))
      .then(data => {
        setCatalog(data);
        const first = (data.nodes || []).find(n => n.id === 'foto.haal_luchtfoto') || (data.nodes || [])[0];
        if (first) setSelectedNodeId(first.id);
      })
      .catch(e => setFout(e.message || 'Flow-catalogus laden mislukt'));
  }, []);

  const selectedNode = nodeById(catalog, selectedNodeId);
  const visibleGroups = (catalog.groups || []).filter(g => groupNodes(catalog, g.id, flowMode).length > 0);
  const visibleNodes = groupNodes(catalog, activeGroup, flowMode);

  useEffect(() => {
    const firstGroup = visibleGroups[0];
    if (firstGroup && !visibleGroups.some(g => g.id === activeGroup)) {
      setActiveGroup(firstGroup.id);
      return;
    }
    if (!selectedNode || !nodeVisibleInMode(selectedNode, flowMode)) {
      const firstNode = (catalog.nodes || []).find(n => nodeVisibleInMode(n, flowMode));
      if (firstNode) setSelectedNodeId(firstNode.id);
    }
  }, [flowMode, catalog, activeGroup, selectedNodeId]);

  async function laadTrace() {
    if (!selectedTaakId) {
      setTraceRows([]);
      return;
    }
    setTraceLaden(true);
    setFout(null);
    try {
      const params = new URLSearchParams();
      if (selectedPandId.trim()) params.set('pand_id', selectedPandId.trim());
      const qs = params.toString();
      const data = await fetch(`${API}/pipeline/${selectedTaakId}/trace${qs ? `?${qs}` : ''}`)
        .then(r => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`)));
      setTraceRows(data || []);
    } catch (e) {
      setFout(e.message || 'Trace laden mislukt');
      setTraceRows([]);
    } finally {
      setTraceLaden(false);
    }
  }

  return (
    <div className="bd-page bd-flow-page">
      <div className="bd-page-head">
        <div><h1>Flow</h1><p>Bekijk wat de pipeline per stap doet, van BAG-pand tot AI-resultaat.</p></div>
        <div className="bd-page-head-actions bd-flow-trace-controls">
          <Field label="Scanmodus">
            <div className="bd-row">
              {[
                ['pand_scan', 'Pand scan'],
                ['perceel_scan', 'Perceel scan'],
              ].map(([id, label]) => (
                <button key={id} type="button" className={'bd-pill-tab' + (flowMode === id ? ' is-active' : '')} onClick={() => setFlowMode(id)}>
                  {label}
                </button>
              ))}
            </div>
          </Field>
          <Field label="Trace taak">
            <input className="bd-input" value={selectedTaakId} placeholder="taak id" onChange={e => setSelectedTaakId(e.target.value)} />
          </Field>
          <Field label="Pand ID">
            <input className="bd-input" value={selectedPandId} placeholder="optioneel" onChange={e => setSelectedPandId(e.target.value)} />
          </Field>
          <Btn kind="secondary" icon={traceLaden ? 'loader' : 'activity'} onClick={laadTrace}>Trace laden</Btn>
        </div>
      </div>
      {fout && <Alert kind="error">{fout}</Alert>}
      <div className="bd-flow-shell">
        <nav className="bd-flow-groups">
          {visibleGroups.map(g => (
            <button key={g.id} type="button" className={activeGroup === g.id ? 'is-active' : ''} onClick={() => setActiveGroup(g.id)}>
              {g.title}
            </button>
          ))}
        </nav>
        <main className="bd-flow-canvas">
          {visibleNodes.map(node => (
            <FlowNode
              key={node.id}
              node={node}
              selected={node.id === selectedNodeId}
              traceRows={traceRows}
              onClick={setSelectedNodeId}
            />
          ))}
        </main>
        <FlowDetail node={selectedNode} activeTab={activeTab} setActiveTab={setActiveTab} traceRows={traceRows} />
      </div>
    </div>
  );
}

window.SchermFlow = SchermFlow;
