import { useState, useMemo, useCallback } from 'react';
import { Handle, Position } from '@xyflow/react';
import morphData from 'virtual:morph-data';
import FlowGraph from '../components/FlowGraph.jsx';
import DetailPanel from '../components/DetailPanel.jsx';
import SearchFilter from '../components/SearchFilter.jsx';
import { useDetailPanel } from '../hooks/useDetailPanel.js';

// ─── Category Color Palette ───────────────────────────────────────────────────

const CATEGORY_COLORS = {
  'ai-agents':      '#34d399',
  'architecture':   '#f97316',
  'backend':        '#3b82f6',
  'data':           '#8b5cf6',
  'frontend':       '#f472b6',
  'infrastructure': '#fbbf24',
  'integration':    '#06b6d4',
};

const CATEGORY_BG = {
  'ai-agents':      '#064e3b',
  'architecture':   '#431407',
  'backend':        '#1e3a5f',
  'data':           '#2e1065',
  'frontend':       '#500724',
  'infrastructure': '#451a03',
  'integration':    '#083344',
};

function getCategoryColor(category) {
  return CATEGORY_COLORS[category] || '#94a3b8';
}
function getCategoryBg(category) {
  return CATEGORY_BG[category] || '#1e293b';
}

// ─── Node Components ──────────────────────────────────────────────────────────

function StandardNode({ data }) {
  const color = getCategoryColor(data.category);
  const bg = getCategoryBg(data.category);
  return (
    <div
      className="rounded-lg px-3 py-2 min-w-[160px] max-w-[190px] cursor-pointer select-none"
      style={{
        background: bg,
        border: `1.5px solid ${data.dimmed ? bg : color}`,
        boxShadow: data.dimmed ? 'none' : `0 0 8px ${color}33`,
        opacity: data.dimmed ? 0.25 : 1,
      }}
    >
      <Handle type="target" position={Position.Left} style={{ background: color, width: 7, height: 7 }} />
      <Handle type="source" position={Position.Right} style={{ background: color, width: 7, height: 7 }} />
      <div className="text-white text-xs font-semibold leading-tight truncate" title={data.label}>
        {data.label}
      </div>
      <div className="text-[10px] mt-0.5 font-mono truncate" style={{ color }}>
        {data.category}
        {data.subcategory ? ` / ${data.subcategory}` : ''}
      </div>
    </div>
  );
}

function AgentRefNode({ data }) {
  return (
    <div
      className="rounded px-2 py-1 select-none cursor-default"
      style={{
        background: '#1e293b',
        border: '1px solid #334155',
        opacity: data.dimmed ? 0.2 : 1,
      }}
    >
      <Handle type="source" position={Position.Right} style={{ background: '#475569', width: 6, height: 6 }} />
      <div className="text-gray-400 text-[10px] font-mono truncate max-w-[110px]" title={data.label}>
        {data.label}
      </div>
    </div>
  );
}

const nodeTypes = { standardNode: StandardNode, agentRefNode: AgentRefNode };

// ─── Graph Builder ────────────────────────────────────────────────────────────

function buildGraph(standards, search, categoryFilter) {
  const nodes = [];
  const edges = [];

  const filtered = standards.filter((s) => {
    const q = search.toLowerCase();
    const matchSearch = !q || s.name.toLowerCase().includes(q) || s.id.toLowerCase().includes(q) || s.category.toLowerCase().includes(q);
    const matchCat = !categoryFilter || s.category === categoryFilter;
    return matchSearch && matchCat;
  });
  const filteredIds = new Set(filtered.map((s) => s.id));
  const hasFilter = search || categoryFilter;

  // Group by category
  const byCategory = {};
  for (const std of standards) {
    if (!byCategory[std.category]) byCategory[std.category] = [];
    byCategory[std.category].push(std);
  }

  const STD_X = 180;
  const AGENT_X = 0;
  const ROW_H = 75;
  const CAT_GAP = 40;

  let globalY = 0;

  // Track all agent refs that need separate nodes
  const agentNodeMap = {}; // agentId → { x, y }
  const agentYTracker = {};

  for (const [cat, catStandards] of Object.entries(byCategory)) {
    catStandards.forEach((std, i) => {
      const isDimmed = hasFilter && !filteredIds.has(std.id);
      nodes.push({
        id: `std-${std.id}`,
        type: 'standardNode',
        position: { x: STD_X, y: globalY + i * ROW_H },
        data: {
          label: std.name,
          category: std.category,
          subcategory: std.subcategory,
          stdRef: std,
          dimmed: isDimmed,
        },
      });

      // Agent ref nodes on the left
      std.referencedBy.forEach((ref, j) => {
        const agentNodeId = `agent-${ref.agentId}`;
        if (!agentNodeMap[agentNodeId]) {
          const ay = agentYTracker[ref.agentId] ?? globalY + i * ROW_H;
          agentYTracker[ref.agentId] = ay + 55;
          agentNodeMap[agentNodeId] = { x: AGENT_X, y: ay };
          nodes.push({
            id: agentNodeId,
            type: 'agentRefNode',
            position: { x: AGENT_X, y: ay },
            data: { label: ref.agentId, dimmed: isDimmed },
          });
        }
        const edgeLabel = [ref.scope, ref.priority].filter(Boolean).join('/');
        edges.push({
          id: `edge-${ref.agentId}-${std.id}-${j}`,
          source: agentNodeId,
          target: `std-${std.id}`,
          type: 'smoothstep',
          label: edgeLabel || undefined,
          labelStyle: { fill: '#64748b', fontSize: 9 },
          labelBgStyle: { fill: '#0f172a', fillOpacity: 0.85 },
          style: {
            stroke: isDimmed ? '#1e293b' : getCategoryColor(std.category),
            strokeWidth: 1,
            opacity: isDimmed ? 0.15 : 0.4,
          },
        });
      });
    });

    globalY += catStandards.length * ROW_H + CAT_GAP;
  }

  return { nodes, edges };
}

// ─── Detail Content ───────────────────────────────────────────────────────────

function StandardDetail({ std }) {
  const [showContent, setShowContent] = useState(false);
  const color = getCategoryColor(std.category);

  return (
    <div className="text-sm text-gray-200 space-y-4">
      <div>
        <p className="text-gray-400 text-xs">ID: <span className="font-mono text-gray-300">{std.id}</span></p>
        <p className="text-gray-400 text-xs mt-0.5">Path: <span className="font-mono text-gray-300">{std.path}</span></p>
      </div>

      <div className="flex flex-wrap gap-1">
        <span className="px-2 py-0.5 rounded text-xs font-bold" style={{ background: getCategoryBg(std.category), color, border: `1px solid ${color}` }}>
          {std.category}
        </span>
        {std.subcategory && (
          <span className="px-2 py-0.5 rounded text-xs bg-gray-800 border border-gray-700 text-gray-400">
            {std.subcategory}
          </span>
        )}
      </div>

      {std.digest && (
        <div>
          <p className="text-gray-500 text-xs uppercase tracking-wide mb-1.5">Digest</p>
          <p className="text-gray-300 text-xs leading-relaxed">{std.digest}</p>
        </div>
      )}

      {std.tags?.length > 0 && (
        <div>
          <p className="text-gray-500 text-xs uppercase tracking-wide mb-1.5">Tags</p>
          <div className="flex flex-wrap gap-1">
            {std.tags.map((t) => (
              <span key={t} className="px-1.5 py-0.5 bg-gray-800 border border-gray-700 rounded text-xs text-gray-400">{t}</span>
            ))}
          </div>
        </div>
      )}

      {std.stacks?.length > 0 && (
        <div>
          <p className="text-gray-500 text-xs uppercase tracking-wide mb-1.5">Stacks</p>
          <div className="flex flex-wrap gap-1">
            {std.stacks.map((s) => (
              <span key={s} className="px-2 py-0.5 bg-green-900/50 border border-green-700 rounded text-xs text-green-300">{s}</span>
            ))}
          </div>
        </div>
      )}

      {std.referencedBy?.length > 0 && (
        <div>
          <p className="text-gray-500 text-xs uppercase tracking-wide mb-1.5">Referenced By ({std.referencedBy.length})</p>
          <div className="space-y-1">
            {std.referencedBy.map((ref, i) => (
              <div key={i} className="flex items-center justify-between text-xs px-2 py-1 bg-gray-800 rounded">
                <span className="font-mono text-gray-300 truncate">{ref.agentId}</span>
                <div className="flex gap-1 ml-2 flex-shrink-0">
                  {ref.scope && <span className="px-1.5 py-0.5 bg-gray-700 rounded text-gray-400">{ref.scope}</span>}
                  {ref.priority && <span className="px-1.5 py-0.5 bg-gray-700 rounded text-gray-400">{ref.priority}</span>}
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      <div>
        <button
          onClick={() => setShowContent((v) => !v)}
          className="w-full text-left px-3 py-1.5 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded text-xs text-gray-300 transition-colors"
        >
          {showContent ? 'Hide Content' : 'Show Full Content'}
        </button>
        {showContent && (
          <pre className="mt-2 p-3 bg-gray-950 border border-gray-800 rounded text-[9px] text-gray-400 overflow-x-auto whitespace-pre-wrap font-mono leading-relaxed max-h-64 overflow-y-auto">
            {std.content}
          </pre>
        )}
      </div>
    </div>
  );
}

// ─── Main Page ────────────────────────────────────────────────────────────────

export default function Standards() {
  const { standards } = morphData;
  const [search, setSearch] = useState('');
  const [categoryFilter, setCategoryFilter] = useState('');
  const { panel, openPanel, closePanel } = useDetailPanel();

  const allCategories = useMemo(
    () => [...new Set(standards.list.map((s) => s.category))].sort(),
    [standards.list]
  );

  const { nodes, edges } = useMemo(
    () => buildGraph(standards.list, search, categoryFilter),
    [standards.list, search, categoryFilter]
  );

  const handleNodeClick = useCallback(
    (_event, node) => {
      if (node.type === 'standardNode') {
        const std = node.data.stdRef;
        if (std) openPanel(std.name, <StandardDetail std={std} />);
      }
    },
    [openPanel]
  );

  const filterConfig = [
    { name: 'category', label: 'Category', options: allCategories, value: categoryFilter },
  ];

  return (
    <div className="flex flex-col h-full">
      <SearchFilter
        placeholder="Search standards by name, ID, or category..."
        filters={filterConfig}
        onSearchChange={setSearch}
        onFilterChange={(name, value) => {
          if (name === 'category') setCategoryFilter(value);
        }}
      />

      <div className="flex-1 relative">
        <FlowGraph
          nodes={nodes}
          edges={edges}
          nodeTypes={nodeTypes}
          onNodeClick={handleNodeClick}
          fitView
        />

        <div className="absolute top-3 left-3 bg-gray-900/90 border border-gray-700 rounded-lg p-3 text-xs space-y-1.5 z-10">
          <p className="text-gray-400 font-semibold uppercase tracking-wide text-[10px] mb-2">Categories</p>
          {Object.entries(CATEGORY_COLORS).map(([cat, color]) => (
            <div key={cat} className="flex items-center gap-2">
              <span className="inline-block w-3 h-3 rounded-sm flex-shrink-0" style={{ background: getCategoryBg(cat), border: `1px solid ${color}` }} />
              <span className="text-gray-300">{cat}</span>
            </div>
          ))}
        </div>

        <div className="absolute top-3 right-3 bg-gray-900/90 border border-gray-700 rounded-lg px-3 py-1.5 text-xs text-gray-400 z-10">
          {standards.list.length} standards · v{standards.version}
        </div>
      </div>

      <DetailPanel open={panel.open} title={panel.title} onClose={closePanel}>
        {panel.content}
      </DetailPanel>
    </div>
  );
}
