'use client';

import { useState, useCallback, useRef, useMemo, useEffect } from 'react';
import { createPortal } from 'react-dom';
import {
  ElectronicsContent,
  ElectronicCircuitState,
  ElectronicComponent,
  ElectronicWire,
  ElectronicComponentType,
  getTerminals,
  componentLabel,
} from '@/types/electronics';
import { simulateElectronics } from './simulateElectronics';
import { ComponentSVG, COMP_W, COMP_H, getTerminalPositions } from './ComponentSVG';
import { Trash2, RotateCw, Play, Pause, Maximize2, Minimize2, X } from 'lucide-react';
import { Button } from '@/components/ui/button';

interface ElectronicsLabProps {
  content: ElectronicsContent;
  onCircuitChange: (state: ElectronicCircuitState) => void;
  disabled?: boolean;
}

const CANVAS_W = 700;
const CANVAS_H = 500;

interface TermPos { id: string; x: number; y: number }

let nextCompId = 1;

export function ElectronicsLab({ content, onCircuitChange, disabled }: ElectronicsLabProps) {
  const [components, setComponents] = useState<ElectronicComponent[]>(content.preplacedComponents ?? []);
  const [wires, setWires] = useState<ElectronicWire[]>(content.preplacedWires ?? []);
  const [placing, setPlacing] = useState<ElectronicComponentType | null>(null);
  const [wiringFrom, setWiringFrom] = useState<TermPos | null>(null);
  const [mousePos, setMousePos] = useState<{ x: number; y: number } | null>(null);
  const [dragging, setDragging] = useState<{ id: string; ox: number; oy: number } | null>(null);
  const [selected, setSelected] = useState<string | null>(null);
  const [running, setRunning] = useState(false);
  const [fullscreen, setFullscreen] = useState(false);
  const didDrag = useRef(false);
  const svgRef = useRef<SVGSVGElement>(null);

  // Escape exits fullscreen
  useEffect(() => {
    if (!fullscreen) return;
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); setFullscreen(false); }
    };
    window.addEventListener('keydown', handleKey, true);
    return () => window.removeEventListener('keydown', handleKey, true);
  }, [fullscreen]);

  const circuit: ElectronicCircuitState = useMemo(() => ({ components, wires }), [components, wires]);
  const simResult = useMemo(() => {
    if (!running) return null;
    return simulateElectronics(circuit);
  }, [circuit, running]);

  const sync = useCallback((c: ElectronicComponent[], w: ElectronicWire[]) => {
    onCircuitChange({ components: c, wires: w });
  }, [onCircuitChange]);

  const getSvgPoint = useCallback((e: React.MouseEvent) => {
    const svg = svgRef.current;
    if (!svg) return { x: 0, y: 0 };
    const ctm = svg.getScreenCTM();
    if (ctm) {
      return {
        x: (e.clientX - ctm.e) / ctm.a,
        y: (e.clientY - ctm.f) / ctm.d,
      };
    }
    // Fallback
    const rect = svg.getBoundingClientRect();
    return {
      x: ((e.clientX - rect.left) / rect.width) * CANVAS_W,
      y: ((e.clientY - rect.top) / rect.height) * CANVAS_H,
    };
  }, []);

  // Get all terminal world positions
  const allTerminals = useMemo(() => {
    const map = new Map<string, { x: number; y: number }>();
    for (const comp of components) {
      const terminals = getTerminalPositions(comp.type, comp.x, comp.y, comp.rotation);
      for (const [name, pos] of Object.entries(terminals)) {
        map.set(`${comp.id}:${name}`, pos);
      }
    }
    return map;
  }, [components]);

  const handleCanvasClick = useCallback((e: React.MouseEvent) => {
    if (disabled) return;
    const pos = getSvgPoint(e);

    if (placing) {
      const newComp: ElectronicComponent = {
        id: `comp-${nextCompId++}`,
        type: placing,
        x: pos.x - COMP_W / 2,
        y: pos.y - COMP_H / 2,
        rotation: 0,
        value: placing === 'voltage-source' ? 5 : placing === 'resistor' ? 1000 : placing === 'capacitor' ? 100 : undefined,
      };
      const nc = [...components, newComp];
      setComponents(nc);
      sync(nc, wires);
      setPlacing(null);
      return;
    }

    // Don't deselect if we just finished dragging a component
    if (!didDrag.current) {
      setSelected(null);
    }
    didDrag.current = false;
    setWiringFrom(null);
  }, [disabled, placing, components, wires, getSvgPoint, sync]);

  const handleTerminalDragStart = useCallback((termId: string, pos: { x: number; y: number }) => {
    if (disabled) return;
    setWiringFrom({ id: termId, ...pos });
  }, [disabled]);

  const handleTerminalDragEnd = useCallback((termId: string) => {
    if (disabled || !wiringFrom) return;
    if (termId === wiringFrom.id) { setWiringFrom(null); return; }

    const existing = wires.find((w) =>
      (w.from === wiringFrom.id && w.to === termId) ||
      (w.from === termId && w.to === wiringFrom.id)
    );
    if (!existing) {
      const newWire: ElectronicWire = { id: `ew-${Date.now()}`, from: wiringFrom.id, to: termId };
      const nw = [...wires, newWire];
      setWires(nw);
      sync(components, nw);
    }
    setWiringFrom(null);
  }, [disabled, wiringFrom, wires, components, sync]);

  const handleMouseMove = useCallback((e: React.MouseEvent) => {
    const pos = getSvgPoint(e);
    setMousePos(pos);
    if (dragging) {
      didDrag.current = true;
      const nc = components.map((c) =>
        c.id === dragging.id ? { ...c, x: pos.x - dragging.ox, y: pos.y - dragging.oy } : c
      );
      setComponents(nc);
      sync(nc, wires);
    }
  }, [dragging, components, wires, getSvgPoint, sync]);

  const handleMouseUp = useCallback(() => {
    setDragging(null);
    if (wiringFrom) setWiringFrom(null);
  }, [wiringFrom]);

  const handleCompMouseDown = useCallback((id: string, e: React.MouseEvent) => {
    if (disabled) return;
    // Mark as interacted so canvas click doesn't deselect
    didDrag.current = true;
    setSelected(id);
    const comp = components.find((c) => c.id === id);
    if (!comp) return;
    const pos = getSvgPoint(e);
    setDragging({ id, ox: pos.x - comp.x, oy: pos.y - comp.y });
  }, [disabled, components, getSvgPoint]);

  const deleteComp = useCallback((id: string) => {
    if (disabled) return;
    const nc = components.filter((c) => c.id !== id);
    const nw = wires.filter((w) => !w.from.startsWith(id) && !w.to.startsWith(id));
    setComponents(nc);
    setWires(nw);
    sync(nc, nw);
    if (selected === id) setSelected(null);
  }, [disabled, components, wires, selected, sync]);

  const rotateComp = useCallback((id: string) => {
    if (disabled) return;
    const nc = components.map((c) =>
      c.id === id ? { ...c, rotation: ((c.rotation + 90) % 360) as 0 | 90 | 180 | 270 } : c
    );
    setComponents(nc);
    sync(nc, wires);
  }, [disabled, components, wires, sync]);

  const changeValue = useCallback((id: string, value: number) => {
    const nc = components.map((c) => c.id === id ? { ...c, value } : c);
    setComponents(nc);
    sync(nc, wires);
  }, [components, wires, sync]);

  const clearAll = useCallback(() => {
    const preplaced = content.preplacedComponents ?? [];
    const preWires = content.preplacedWires ?? [];
    setComponents(preplaced);
    setWires(preWires);
    setSelected(null);
    setWiringFrom(null);
    sync(preplaced, preWires);
  }, [content, sync]);

  function renderWire(from: { x: number; y: number }, to: { x: number; y: number }, color: string, key: string, dashed = false) {
    const dx = Math.max(Math.abs(to.x - from.x) * 0.4, 20);
    const d = `M${from.x},${from.y} C${from.x + dx},${from.y} ${to.x - dx},${to.y} ${to.x},${to.y}`;
    return <path key={key} d={d} fill="none" stroke={color} strokeWidth="2" strokeDasharray={dashed ? '6 3' : undefined} pointerEvents="none" />;
  }

  // Color wire by voltage difference
  function wireColor(wireObj: ElectronicWire): string {
    if (!simResult?.success) return '#555';
    const vFrom = simResult.nodeVoltages.get(wireObj.from) ?? 0;
    const vTo = simResult.nodeVoltages.get(wireObj.to) ?? 0;
    const avg = (vFrom + vTo) / 2;
    if (avg > 3) return '#ef4444';   // high voltage = red
    if (avg > 0.5) return '#f59e0b'; // medium = amber
    return '#555';                    // low/ground = gray
  }

  // Shared palette content
  const paletteContent = (
    <>
      {content.availableComponents.map((type) => (
        <button
          key={type}
          onClick={() => !disabled && setPlacing(placing === type ? null : type)}
          className={`px-2 py-1.5 text-[11px] font-medium rounded border transition-colors text-left ${
            placing === type
              ? 'bg-primary/20 border-primary text-primary'
              : 'bg-muted border-border text-foreground hover:border-primary/50'
          } ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`}
        >
          {componentLabel(type)}
        </button>
      ))}
      <div className="border-t border-border my-1" />
      {selected && (
        <div className="space-y-1">
          <Button variant="ghost" size="sm" onClick={() => rotateComp(selected)} disabled={disabled} className="w-full text-xs justify-start">
            <RotateCw className="w-3 h-3 mr-1" /> Rotar
          </Button>
          {components.find((c) => c.id === selected)?.type === 'resistor' && (
            <div className="px-1">
              <label className="text-[10px] text-muted-foreground">Ω</label>
              <input type="number" className="w-full px-2 py-1 text-xs bg-muted border border-border rounded"
                value={components.find((c) => c.id === selected)?.value ?? 1000}
                onChange={(e) => changeValue(selected, parseFloat(e.target.value) || 1000)}
                onKeyDown={(e) => e.stopPropagation()} />
            </div>
          )}
          {components.find((c) => c.id === selected)?.type === 'voltage-source' && (
            <div className="px-1">
              <label className="text-[10px] text-muted-foreground">Voltios</label>
              <input type="number" className="w-full px-2 py-1 text-xs bg-muted border border-border rounded"
                value={components.find((c) => c.id === selected)?.value ?? 5}
                onChange={(e) => changeValue(selected, parseFloat(e.target.value) || 5)}
                onKeyDown={(e) => e.stopPropagation()} />
            </div>
          )}
          {components.find((c) => c.id === selected)?.type === 'capacitor' && (
            <div className="px-1">
              <label className="text-[10px] text-muted-foreground">µF</label>
              <input type="number" className="w-full px-2 py-1 text-xs bg-muted border border-border rounded"
                value={components.find((c) => c.id === selected)?.value ?? 100}
                onChange={(e) => changeValue(selected, parseFloat(e.target.value) || 100)}
                onKeyDown={(e) => e.stopPropagation()} />
            </div>
          )}
          <Button variant="ghost" size="sm" onClick={() => deleteComp(selected)} disabled={disabled}
            className="w-full text-xs justify-start text-destructive hover:text-destructive">
            <Trash2 className="w-3 h-3 mr-1" /> Eliminar
          </Button>
        </div>
      )}
      <div className="flex-1" />
      <Button variant="ghost" size="sm" onClick={clearAll} disabled={disabled}
        className="text-xs text-destructive hover:text-destructive">
        <Trash2 className="w-3 h-3 mr-1" /> Limpiar
      </Button>
    </>
  );

  // Shared SVG canvas
  const svgCanvas = (fs: boolean) => (
    <svg
      ref={svgRef}
      viewBox={`0 0 ${CANVAS_W} ${CANVAS_H}`}
      className={fs ? 'w-full h-full' : 'w-full'}
      preserveAspectRatio={fs ? 'xMidYMid meet' : undefined}
      style={{ minHeight: fs ? undefined : 350, cursor: placing ? 'crosshair' : wiringFrom ? 'crosshair' : 'default', userSelect: 'none' }}
      onClick={handleCanvasClick}
      onMouseMove={handleMouseMove}
      onMouseUp={handleMouseUp}
    >
      <defs>
        <pattern id="egrid" width="20" height="20" patternUnits="userSpaceOnUse">
          <circle cx="10" cy="10" r="0.5" fill="#333" />
        </pattern>
      </defs>
      <rect width={CANVAS_W} height={CANVAS_H} fill="url(#egrid)" />
      {wires.map((wire) => {
        const from = allTerminals.get(wire.from);
        const to = allTerminals.get(wire.to);
        if (!from || !to) return null;
        return renderWire(from, to, wireColor(wire), wire.id);
      })}
      {wiringFrom && mousePos && renderWire(wiringFrom, mousePos, '#6366f1', 'wire-preview', true)}
      {placing && mousePos && (
        <rect x={mousePos.x - COMP_W / 2} y={mousePos.y - COMP_H / 2}
          width={COMP_W} height={COMP_H}
          fill="none" stroke="#6366f1" strokeWidth="2" strokeDasharray="4" rx="4" pointerEvents="none" />
      )}
      {components.map((comp) => (
        <ComponentSVG key={comp.id} component={comp} selected={selected === comp.id}
          voltage={simResult?.success ? simResult.nodeVoltages : undefined}
          meterReading={simResult?.success ? simResult.meterReadings.get(comp.id) : undefined}
          onMouseDown={handleCompMouseDown} onDelete={deleteComp}
          onTerminalDragStart={handleTerminalDragStart} onTerminalDragEnd={handleTerminalDragEnd} />
      ))}
    </svg>
  );

  // Shared probe table
  const probeTable = content.probes.length > 0 && (
    <div className="border border-border rounded-lg overflow-hidden shrink-0">
      <table className="w-full text-xs font-mono">
        <thead>
          <tr className="bg-muted/50">
            <th className="px-3 py-1.5 text-left text-muted-foreground">Medición</th>
            <th className="px-3 py-1.5 text-center text-muted-foreground">Esperado</th>
            <th className="px-3 py-1.5 text-center text-muted-foreground">Tu resultado</th>
            <th className="w-8" />
          </tr>
        </thead>
        <tbody>
          {content.probes.map((probe, i) => {
            // Find meter readings of the matching type
            const readings: number[] = [];
            if (simResult?.success) {
              for (const [, reading] of simResult.meterReadings) {
                if ((probe.type === 'voltmeter' && reading.unit === 'V') ||
                    (probe.type === 'ammeter' && reading.unit === 'mA')) {
                  readings.push(reading.value);
                }
              }
            }
            const match = readings.find((r) => Math.abs(r - probe.expected) <= probe.tolerance);
            const hasReading = readings.length > 0;
            const pass = match !== undefined;
            const instrumentName = probe.type === 'voltmeter' ? 'Voltímetro' : 'Amperímetro';
            return (
              <tr key={i} className={`border-t border-border ${pass ? 'bg-green-500/5' : ''}`}>
                <td className="px-3 py-1.5">
                  <span className="text-muted-foreground text-[10px]">{instrumentName}:</span>{' '}
                  {probe.label}
                </td>
                <td className="px-3 py-1.5 text-center font-bold">{probe.expected}{probe.unit}</td>
                <td className="px-3 py-1.5 text-center">
                  {hasReading
                    ? readings.map((r) => r.toFixed(1) + probe.unit).join(', ')
                    : <span className="text-muted-foreground">Coloca un {instrumentName.toLowerCase()}</span>
                  }
                </td>
                <td className="px-2 text-center">{hasReading && (pass ? '✓' : '✗')}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );

  // Play/pause + fullscreen toolbar
  const toolbar = (fs: boolean) => (
    <div className="flex items-center gap-2 shrink-0">
      <Button variant={running ? 'default' : 'outline'} size="sm"
        onClick={() => setRunning((r) => !r)}
        className={running ? 'bg-green-600 hover:bg-green-700 text-white' : ''}>
        {running ? <Pause className="w-3.5 h-3.5 mr-1.5" /> : <Play className="w-3.5 h-3.5 mr-1.5" />}
        {running ? 'Pausar' : 'Simular'}
      </Button>
      <span className={`text-xs flex-1 ${running ? 'text-green-400' : 'text-muted-foreground'}`}>
        {running ? '● Simulación activa' : '○ Pausada'}
      </span>
      <Button variant="ghost" size="sm" onClick={() => setFullscreen(!fs)} title={fs ? 'Salir (Esc)' : 'Pantalla completa'}>
        {fs ? <Minimize2 className="w-3.5 h-3.5" /> : <Maximize2 className="w-3.5 h-3.5" />}
      </Button>
    </div>
  );

  // === FULLSCREEN PORTAL ===
  const fullscreenOverlay = fullscreen && createPortal(
    <div className="fixed inset-0 z-[500] bg-[#050510] flex animate-fade-in">
      {/* Sidebar palette */}
      <div className="w-32 shrink-0 flex flex-col gap-1.5 p-3 bg-card/30 border-r border-border overflow-y-auto">
        <div className="flex items-center justify-between mb-1">
          <p className="text-xs text-muted-foreground font-medium">Componentes</p>
        </div>
        {paletteContent}
      </div>

      {/* Main area */}
      <div className="flex-1 flex flex-col min-h-0">
        <div className="px-3 py-2 border-b border-border bg-card/30">
          {toolbar(true)}
        </div>
        <div className="flex-1 min-h-0 bg-[#0a0a0a]">
          {svgCanvas(true)}
        </div>
        <div className="px-3 py-2 border-t border-border bg-card/30">
          {probeTable}
          {simResult && !simResult.success && simResult.error && components.length > 0 && (
            <p className="text-xs text-amber-500 mt-1">{simResult.error}</p>
          )}
        </div>
      </div>
    </div>,
    document.body
  );

  // === INLINE (normal) ===
  return (
    <div className="space-y-4">
      <div className="flex gap-3">
        <div className="flex flex-col gap-1.5 shrink-0 min-w-[90px]">
          <p className="text-xs text-muted-foreground font-medium mb-1">Componentes</p>
          {paletteContent}
        </div>
        <div className="flex-1 flex flex-col gap-2">
          {toolbar(false)}
          <div className="flex-1 border border-border rounded-lg overflow-hidden bg-[#0a0a0a]">
            {svgCanvas(false)}
          </div>
        </div>
      </div>
      {probeTable}
      {simResult && !simResult.success && simResult.error && components.length > 0 && (
        <p className="text-xs text-amber-500">{simResult.error}</p>
      )}
      <div className="text-xs text-muted-foreground space-y-1">
        <p>Arrastra desde un terminal (●) a otro para conectar. Clic derecho para eliminar.</p>
        <p>Selecciona un componente para rotarlo o cambiar su valor.</p>
      </div>
      {fullscreenOverlay}
    </div>
  );
}
