import { useState, useEffect, useCallback } from 'react'
import CytoscapeComponent from 'react-cytoscapejs'
import type { ElementDefinition } from 'cytoscape'
import { api } from '../api'
import type { GraphData, GraphEdge } from '../types'

interface Props { documentId: string }

const THEME_COLORS: Record<string, string> = {
  supply_chain: '#6366f1',
  finance: '#10b981',
  operations: '#f59e0b',
  general: '#8892a4',
}

function nodeColor(theme: string) {
  return THEME_COLORS[theme] || '#6366f1'
}

export function GraphView({ documentId }: Props) {
  const [data, setData] = useState<GraphData | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [selectedEdge, setSelectedEdge] = useState<GraphEdge | null>(null)
  const [selectedNode, setSelectedNode] = useState<string | null>(null)
  const [themeFilter, setThemeFilter] = useState('')
  const [cyRef, setCyRef] = useState<any>(null)

  const load = useCallback(() => {
    setLoading(true)
    api.getGraph(documentId)
      .then(setData)
      .catch(e => setError(String(e.message)))
      .finally(() => setLoading(false))
  }, [documentId])

  useEffect(() => { load() }, [load])

  const themes = data ? [...new Set(data.edges.map(e => e.theme))].filter(Boolean) : []

  const elements: ElementDefinition[] = data ? [
    ...data.nodes
      .filter(n => !themeFilter || data.edges.some(e => (e.source === n.id || e.target === n.id) && e.theme === themeFilter))
      .map(n => ({
        data: { id: n.id, label: n.label, theme: n.theme },
        classes: 'event-node',
      })),
    ...data.edges
      .filter(e => !themeFilter || e.theme === themeFilter)
      .map(e => ({
        data: {
          id: e.id, source: e.source, target: e.target,
          label: `${e.label} (${e.confidence.toFixed(2)})`,
          confidence: e.confidence, evidence: e.evidence, theme: e.theme,
          edgeData: e,
        },
        classes: 'causal-edge',
      })),
  ] : []

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const stylesheet: any[] = [
    {
      selector: 'node',
      style: {
        label: 'data(label)',
        'background-color': (ele: any) => nodeColor(ele.data('theme') || 'general'),
        color: '#fff',
        'font-size': 11,
        'text-valign': 'center',
        'text-halign': 'center',
        'text-wrap': 'wrap',
        'text-max-width': 100,
        width: 'label',
        height: 'label',
        padding: 10,
        shape: 'round-rectangle',
        'border-width': 2,
        'border-color': 'transparent',
      },
    },
    {
      selector: 'node:selected',
      style: { 'border-color': '#fff', 'border-width': 2 },
    },
    {
      selector: 'edge',
      style: {
        'line-color': '#4f5880',
        'target-arrow-color': '#4f5880',
        'target-arrow-shape': 'triangle',
        'curve-style': 'bezier',
        label: 'data(label)',
        'font-size': 9,
        color: '#8892a4',
        'text-rotation': 'autorotate',
        width: (ele: any) => Math.max(1, ele.data('confidence') * 3),
      },
    },
    {
      selector: 'edge:selected',
      style: { 'line-color': '#6366f1', 'target-arrow-color': '#6366f1' },
    },
  ]

  if (loading) return <div className="spinner" />
  if (error) return <div className="error-msg">{error}</div>
  if (!data || data.nodes.length === 0) return (
    <div className="empty-state"><p>No graph data. Build graph first.</p></div>
  )

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', gap: 12 }}>
      <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
        {themes.length > 0 && (
          <div>
            <select value={themeFilter} onChange={e => setThemeFilter(e.target.value)} style={{ width: 160 }}>
              <option value="">All themes</option>
              {themes.map(t => <option key={t} value={t}>{t}</option>)}
            </select>
          </div>
        )}
        <button className="btn-secondary" onClick={load} style={{ fontSize: 12 }}>Reload</button>
        <button className="btn-secondary" onClick={() => cyRef?.fit()} style={{ fontSize: 12 }}>Fit</button>
        <span style={{ fontSize: 12, color: 'var(--muted)' }}>
          {data.nodes.length} nodes · {data.edges.length} edges
        </span>
      </div>

      <div style={{ display: 'flex', gap: 12, flex: 1, minHeight: 0 }}>
        <div style={{
          flex: 1, background: 'var(--bg2)', border: '1px solid var(--border)',
          borderRadius: 'var(--radius)', overflow: 'hidden',
        }}>
          <CytoscapeComponent
            elements={elements}
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            stylesheet={stylesheet as any}
            layout={{ name: 'cose', idealEdgeLength: 120, animate: false }}
            style={{ width: '100%', height: '100%', minHeight: 400 }}
            cy={(cy: any) => {
              setCyRef(cy)
              cy.on('tap', 'edge', (evt: any) => {
                setSelectedEdge(evt.target.data('edgeData'))
                setSelectedNode(null)
              })
              cy.on('tap', 'node', (evt: any) => {
                setSelectedNode(evt.target.data('label'))
                setSelectedEdge(null)
              })
              cy.on('tap', (evt: any) => {
                if (evt.target === cy) { setSelectedEdge(null); setSelectedNode(null) }
              })
            }}
          />
        </div>

        {(selectedEdge || selectedNode) && (
          <div className="card" style={{ width: 260, flexShrink: 0, fontSize: 13, overflowY: 'auto' }}>
            {selectedNode && (
              <>
                <div className="label">Node</div>
                <div style={{ fontWeight: 600, marginBottom: 8 }}>{selectedNode}</div>
              </>
            )}
            {selectedEdge && (
              <>
                <div className="label">Edge</div>
                <div style={{ marginBottom: 8 }}>
                  <span style={{ color: '#f87171' }}>{selectedEdge.source}</span>
                  <span style={{ color: 'var(--muted)', margin: '0 6px' }}>→</span>
                  <span style={{ color: '#60a5fa' }}>{selectedEdge.target}</span>
                </div>
                <div style={{ marginBottom: 4 }}>
                  <span className={`badge ${selectedEdge.label}`}>{selectedEdge.label}</span>
                </div>
                <div style={{ color: 'var(--muted)', marginBottom: 8 }}>
                  Confidence: <strong>{selectedEdge.confidence.toFixed(2)}</strong>
                </div>
                {selectedEdge.evidence && (
                  <>
                    <div className="label">Evidence</div>
                    <div style={{ color: 'var(--muted)', fontStyle: 'italic' }}>"{selectedEdge.evidence}"</div>
                  </>
                )}
              </>
            )}
          </div>
        )}
      </div>
    </div>
  )
}
