import React, { useState, useEffect } from 'react';
import { useEngine } from './hooks/useEngine';
import { Ladder } from './components/Ladder';
import { Toolbar } from './components/Toolbar';
import { ConfigPanel } from './components/ConfigPanel';
import { ProgramManager } from './components/ProgramManager';
import type { RungElement, Program } from '../engine/types';

const App: React.FC = () => {
  const { state, engine, program, loadProgram, start, stop, newProgram } = useEngine();

  // DEMO: Load a program with branching on mount
  useEffect(() => {
    if (!program) {
      const demoProgram: Program = {
        name: 'Branch Demo',
        cycleTime: 100,
        rungs: [
          // Rung 1: Simple series (comparison)
          {
            id: 'rung-demo-1',
            enabled: true,
            series: [
              { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/0' },
              { type: 'coil' as const, coilType: 'OTE' as const, address: 'Q:0/0' },
            ],
          },
          // Rung 2: OR branch (3 paths) — any path energized powers the coil
          {
            id: 'rung-demo-2',
            enabled: true,
            series: [
              { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/1' },
              {
                type: 'branch' as const,
                id: 'branch-or-1',
                logic: 'OR',
                paths: [
                  // Path 1: single contact → coil
                  [
                    { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/2' },
                    { type: 'coil' as const, coilType: 'OTE' as const, address: 'Q:0/1' },
                  ],
                  // Path 2: two contacts in series → coil
                  [
                    { type: 'contact' as const, contactType: 'NC' as const, address: 'I:0/3' },
                    { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/4' },
                    { type: 'coil' as const, coilType: 'OTE' as const, address: 'Q:0/2' },
                  ],
                  // Path 3: single NO contact → coil
                  [
                    { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/5' },
                    { type: 'coil' as const, coilType: 'OTE' as const, address: 'Q:0/3' },
                  ],
                ],
              },
            ],
          },
          // Rung 3: AND branch (2 paths) — both must be energized
          {
            id: 'rung-demo-3',
            enabled: true,
            series: [
              {
                type: 'branch' as const,
                id: 'branch-and-1',
                logic: 'AND',
                paths: [
                  [
                    { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/6' },
                    { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/7' },
                  ],
                  [
                    { type: 'contact' as const, contactType: 'NC' as const, address: 'I:0/8' },
                  ],
                ],
              },
              { type: 'coil' as const, coilType: 'OTE' as const, address: 'Q:0/4' },
            ],
          },
          // Rung 4: Branch with timer/counter (taller elements)
          {
            id: 'rung-demo-4',
            enabled: true,
            series: [
              { type: 'contact' as const, contactType: 'NO' as const, address: 'I:0/9' },
              {
                type: 'branch' as const,
                id: 'branch-or-2',
                logic: 'OR',
                paths: [
                  // Path 1: contact → timer
                  [
                    { type: 'contact' as const, contactType: 'NO' as const, address: 'I:1/0' },
                    { type: 'timer' as const, timerType: 'TON', instanceId: 'T4:0', preset: 500, accumulated: 0 },
                  ],
                  // Path 2: contact → counter
                  [
                    { type: 'contact' as const, contactType: 'NC' as const, address: 'I:1/1' },
                    { type: 'counter' as const, counterType: 'CTU', instanceId: 'C4:0', preset: 10, current: 0 },
                  ],
                ],
              },
              { type: 'coil' as const, coilType: 'OTE' as const, address: 'Q:0/5' },
            ],
          },
        ],
      };
      loadProgram(demoProgram);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  const [selectedElement, setSelectedElement] = useState<{ rungIdx: number; elIdx: number; element: RungElement } | null>(null);

  const handleElementClick = (rungIdx: number, elIdx: number, element: RungElement) => {
    setSelectedElement({ rungIdx, elIdx, element });
  };

  const handleAddRung = () => {
    const newRung = {
      id: `rung-${Date.now()}`,
      enabled: true,
      series: []
    };
    if (!program) {
      const freshProgram: any = {
        name: 'Untitled Program',
        rungs: [newRung],
        cycleTime: 100,
      };
      loadProgram(freshProgram);
    } else {
      loadProgram({ ...program, rungs: [...program.rungs, newRung] });
    }
  };

  const handleStart = () => {
    if (!program) {
      const newRung = {
        id: `rung-${Date.now()}`,
        enabled: true,
        series: []
      };
      const freshProgram: any = {
        name: 'Untitled Program',
        rungs: [newRung],
        cycleTime: 100,
      };
      loadProgram(freshProgram);
      start();
    } else {
      start();
    }
  };

  const handleDropElement = (tool: string, rungIdx: number) => {
    if (!program) return;
    let newElement: any;
    if (tool.startsWith('contact-')) {
      newElement = { type: 'contact', contactType: tool.endsWith('no') ? 'NO' : 'NC', address: 'I:0.0' };
    } else if (tool.startsWith('coil-')) {
      const coilSuffix = tool.replace('coil-', '');
      newElement = { type: 'coil', coilType: coilSuffix.toUpperCase(), address: 'Q:0.0' };
    } else if (tool.startsWith('timer-')) {
      const timerSuffix = tool.replace('timer-', '').toUpperCase();
      newElement = { type: 'timer', timerType: timerSuffix, instanceId: `timer-${Date.now()}`, preset: 1000, accumulated: 0 };
    } else if (tool.startsWith('counter-')) {
      const counterSuffix = tool.replace('counter-', '').toUpperCase();
      newElement = { type: 'counter', counterType: counterSuffix, instanceId: `counter-${Date.now()}`, preset: 10, current: 0 };
    } else if (tool.startsWith('gate-')) {
      const gateSuffix = tool.replace('gate-', '').toUpperCase();
      newElement = { type: 'gate', gateType: gateSuffix, inputs: [], outputAddress: 'Q:0.1' };
    } else if (tool.startsWith('math-')) {
      const mathSuffix = tool.replace('math-', '').toUpperCase();
      newElement = { type: 'math', operator: mathSuffix, inputA: 'I:0.0', inputB: 'I:0.1', outputAddress: 'Q:0.2' };
    } else if (tool.startsWith('branch-')) {
      const branchLogic = tool.replace('branch-', '').toUpperCase();
      newElement = { type: 'branch', id: `branch-${Date.now()}`, logic: branchLogic === 'AND' || branchLogic === 'OR' ? branchLogic : 'AND', paths: [[]] };
    } else if (tool === 'noop') {
      newElement = { type: 'noop' };
    } else if (tool === 'move') {
      newElement = { type: 'move', source: 'I:0.0', destination: 'Q:0.0' };
    } else if (tool === 'scale') {
      newElement = { type: 'scale', inputAddress: 'I:0.0', destination: 'Q:0.0', inMin: 0, inMax: 100, outMin: 0, outMax: 1000 };
    } else if (tool === 'compare') {
      newElement = { type: 'compare', op: '==', inputA: 'I:0.0', inputB: 'I:0.1', outputAddress: 'Q:0.0' };
    } else if (tool === 'oneshot-rising' || tool === 'oneshot-falling') {
      const edgeType = tool.endsWith('rising') ? 'RISING' : 'FALLING';
      newElement = { type: 'oneshot', address: 'I:0.0', edgeType };
    }

    if (newElement) {
      const newRungs = program.rungs.map((rung, i) => {
        if (i === rungIdx) {
          const updatedSeries = [...rung.series, newElement];
          
          // Ensure coil is last if it's the only coil
          const coilIdx = updatedSeries.findIndex(el => el.type === 'coil');
          if (coilIdx !== -1 && coilIdx !== updatedSeries.length - 1) {
            const newSeries = [...updatedSeries];
            const [coil] = newSeries.splice(coilIdx, 1);
            newSeries.push(coil);
            return { ...rung, series: newSeries };
          }
          
          return { ...rung, series: updatedSeries };
        }
        return rung;
      });

      loadProgram({ ...program, rungs: newRungs });
    }
  };

  const handleMoveElement = (fromRungIdx: number, fromElIdx: number, toRungIdx: number, toElIdx: number) => {
    if (!program) return;

    const newRungs = program.rungs.map((rung, i) => ({ ...rung, series: [...rung.series] }));
    const elementToMove = newRungs[fromRungIdx].series[fromElIdx];

    // Remove from old rung
    newRungs[fromRungIdx].series.splice(fromElIdx, 1);

    // Add to new rung at specific position
    newRungs[toRungIdx].series.splice(toElIdx, 0, elementToMove);

    loadProgram({ ...program, rungs: newRungs });
  };

  const handleUpdateElement = (updated: RungElement) => {
    if (!selectedElement || !program) return;
    const newRungs = program.rungs.map((rung, i) => {
      if (i === selectedElement.rungIdx) {
        const newSeries = [...rung.series];
        newSeries[selectedElement.elIdx] = updated;
        return { ...rung, series: newSeries };
      }
      return rung;
    });
    loadProgram({ ...program, rungs: newRungs });
  };

  const handleDeleteElement = () => {
    if (!selectedElement || !program) return;
    const newRungs = program.rungs.map((rung, i) => {
      if (i === selectedElement.rungIdx) {
        const newSeries = rung.series.filter((_, elIdx) => elIdx !== selectedElement.elIdx);
        return { ...rung, series: newSeries };
      }
      return rung;
    });
    loadProgram({ ...program, rungs: newRungs });
    setSelectedElement(null);
  };

  const isRunning = state.running;

  return (
    <div className="app-container">
      <header className="header">
        <h1>Lego Ladder</h1>
        <div className="header-controls">
          <ProgramManager />
          <button className="btn" onClick={handleAddRung}>+ Add Rung</button>
          {isRunning ? (
            <button className="btn btn-danger" onClick={stop}>■ Stop</button>
          ) : (
            <button className="btn btn-success" onClick={handleStart}>▶ Start</button>
          )}
        </div>
      </header>

      <main className="main">
        <Toolbar onToolClick={(tool) => handleDropElement(tool, selectedElement ? selectedElement.rungIdx : 0)} />
        
        <section className="canvas-container">
          {program ? (
            <Ladder 
              program={program} 
              engineState={state} 
              onElementClick={handleElementClick}
              onDropElement={handleDropElement}
              onMoveElement={handleMoveElement}
            />
          ) : (
            <div className="no-program">
              <div style={{ textAlign: 'center' }}>
                <div style={{ fontSize: '48px', marginBottom: '16px', opacity: 0.3 }}>⚡</div>
                <div>No program loaded</div>
                <div style={{ fontSize: '12px', marginTop: '8px', color: 'var(--text-muted)' }}>
                  Click "▶ Start" to create a new program or open an existing one
                </div>
              </div>
            </div>
          )}
        </section>
        <aside className="config-panel" style={{ display: selectedElement ? 'flex' : 'none' }}>
          {selectedElement && (
            <ConfigPanel 
              element={selectedElement.element} 
              onUpdate={handleUpdateElement}
              onDelete={handleDeleteElement}
              onClose={() => setSelectedElement(null)}
            />
          )}
        </aside>
      </main>

      <footer className="footer">
        <span className={`status ${isRunning ? 'running' : ''}`}>
          Status: {isRunning ? 'Running' : 'Stopped'}
        </span>
        <span className="cycle">Cycle: {state.cycle}</span>
      </footer>
    </div>
  );
};

export default App;