import { useState, useCallback, useRef, useEffect } from 'react';
import { useEditorStore } from '../../store/useEditorStore';
import { useSimulatorStore } from '../../store/useSimulatorStore';
import type { BoardKind } from '../../types/board';
import { BOARD_KIND_FQBN, BOARD_KIND_LABELS } from '../../types/board';
import { compileCode } from '../../services/compilation';
import { CompileAllProgress } from './CompileAllProgress';
import type { BoardCompileStatus } from './CompileAllProgress';
import { LibraryManagerModal } from '../simulator/LibraryManagerModal';
import { InstallLibrariesModal } from '../simulator/InstallLibrariesModal';
import { parseCompileResult } from '../../utils/compilationLogger';
import type { CompilationLog } from '../../utils/compilationLogger';
import { exportToWokwiZip, importFromWokwiZip } from '../../utils/wokwiZip';
import './EditorToolbar.css';

interface EditorToolbarProps {
  consoleOpen: boolean;
  setConsoleOpen: (open: boolean | ((v: boolean) => boolean)) => void;
  compileLogs: CompilationLog[];
  setCompileLogs: (logs: CompilationLog[] | ((prev: CompilationLog[]) => CompilationLog[])) => void;
}

const BOARD_PILL_ICON: Record<BoardKind, string> = {
  'arduino-uno':       '⬤',
  'arduino-nano':      '▪',
  'arduino-mega':      '▬',
  'raspberry-pi-pico': '◆',
  'raspberry-pi-3':    '⬛',
  'esp32':    '⬡',
  'esp32-s3': '⬡',
  'esp32-c3': '⬡',
};

const BOARD_PILL_COLOR: Record<BoardKind, string> = {
  'arduino-uno':       '#4fc3f7',
  'arduino-nano':      '#4fc3f7',
  'arduino-mega':      '#4fc3f7',
  'raspberry-pi-pico': '#ce93d8',
  'raspberry-pi-3':    '#ef9a9a',
  'esp32':    '#a5d6a7',
  'esp32-s3': '#a5d6a7',
  'esp32-c3': '#a5d6a7',
};

export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compileLogs, setCompileLogs }: EditorToolbarProps) => {
  const { files } = useEditorStore();
  const {
    boards,
    activeBoardId,
    compileBoardProgram,
    startBoard,
    stopBoard,
    resetBoard,
    // legacy compat
    startSimulation,
    stopSimulation,
    resetSimulation,
    running,
    compiledHex,
  } = useSimulatorStore();

  const activeBoard = boards.find((b) => b.id === activeBoardId) ?? boards[0];
  const [compiling, setCompiling] = useState(false);
  const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [libManagerOpen, setLibManagerOpen] = useState(false);
  const [pendingLibraries, setPendingLibraries] = useState<string[]>([]);
  const [installModalOpen, setInstallModalOpen] = useState(false);
  const importInputRef = useRef<HTMLInputElement>(null);
  const toolbarRef = useRef<HTMLDivElement>(null);
  const [overflowCollapsed, setOverflowCollapsed] = useState(false);
  const [overflowOpen, setOverflowOpen] = useState(false);
  const overflowMenuRef = useRef<HTMLDivElement>(null);

  // Collapse secondary buttons when toolbar is too narrow
  useEffect(() => {
    const el = toolbarRef.current;
    if (!el) return;
    const ro = new ResizeObserver(([entry]) => {
      setOverflowCollapsed(entry.contentRect.width < 500);
    });
    ro.observe(el);
    return () => ro.disconnect();
  }, []);

  // Close overflow dropdown on outside click
  useEffect(() => {
    if (!overflowOpen) return;
    const handler = (e: MouseEvent) => {
      if (overflowMenuRef.current && !overflowMenuRef.current.contains(e.target as Node)) {
        setOverflowOpen(false);
      }
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [overflowOpen]);

  // Compile All state
  const [compileAllOpen, setCompileAllOpen] = useState(false);
  const [compileAllRunning, setCompileAllRunning] = useState(false);
  const [compileAllStatuses, setCompileAllStatuses] = useState<BoardCompileStatus[]>([]);

  const addLog = useCallback((log: CompilationLog) => {
    setCompileLogs((prev: CompilationLog[]) => [...prev, log]);
  }, [setCompileLogs]);

  const handleCompile = async () => {
    setCompiling(true);
    setMessage(null);
    setConsoleOpen(true);

    const kind = activeBoard?.boardKind;

    // Raspberry Pi 3B doesn't need arduino-cli compilation
    if (kind === 'raspberry-pi-3') {
      addLog({ timestamp: new Date(), type: 'info', message: 'Raspberry Pi 3B: no compilation needed — run Python scripts directly.' });
      setMessage({ type: 'success', text: 'Ready (no compilation needed)' });
      setCompiling(false);
      return;
    }

    const fqbn = kind ? BOARD_KIND_FQBN[kind] : null;
    const boardLabel = kind ? BOARD_KIND_LABELS[kind] : 'Unknown';

    if (!fqbn) {
      addLog({ timestamp: new Date(), type: 'error', message: `No FQBN for board kind: ${kind}` });
      setMessage({ type: 'error', text: 'Unknown board' });
      setCompiling(false);
      return;
    }

    addLog({ timestamp: new Date(), type: 'info', message: `Starting compilation for ${boardLabel} (${fqbn})...` });

    try {
      const sketchFiles = files.map((f) => ({ name: f.name, content: f.content }));
      const result = await compileCode(sketchFiles, fqbn);

      const resultLogs = parseCompileResult(result, boardLabel);
      setCompileLogs((prev: CompilationLog[]) => [...prev, ...resultLogs]);

      if (result.success) {
        const program = result.hex_content ?? result.binary_content ?? null;
        if (program && activeBoardId) {
          compileBoardProgram(activeBoardId, program);
        }
        setMessage({ type: 'success', text: 'Compiled successfully' });
      } else {
        setMessage({ type: 'error', text: result.error || result.stderr || 'Compile failed' });
      }
    } catch (err) {
      const errMsg = err instanceof Error ? err.message : 'Compile failed';
      addLog({ timestamp: new Date(), type: 'error', message: errMsg });
      setMessage({ type: 'error', text: errMsg });
    } finally {
      setCompiling(false);
    }
  };

  const handleRun = () => {
    if (activeBoardId) {
      const board = boards.find((b) => b.id === activeBoardId);
      const isQemuBoard = board?.boardKind === 'raspberry-pi-3' || board?.boardKind === 'esp32' || board?.boardKind === 'esp32-s3';
      if (isQemuBoard || board?.compiledProgram) {
        startBoard(activeBoardId);
        setMessage(null);
        return;
      }
    }
    // legacy fallback
    if (compiledHex) {
      startSimulation();
      setMessage(null);
    } else {
      setMessage({ type: 'error', text: 'Compile first' });
    }
  };

  const handleStop = () => {
    if (activeBoardId) stopBoard(activeBoardId);
    else stopSimulation();
    setMessage(null);
  };

  const handleReset = () => {
    if (activeBoardId) resetBoard(activeBoardId);
    else resetSimulation();
    setMessage(null);
  };

  const handleCompileAll = async () => {
    const boardsList = useSimulatorStore.getState().boards;
    const initialStatuses: BoardCompileStatus[] = boardsList.map((b) => ({
      boardId: b.id,
      boardKind: b.boardKind,
      state: 'pending',
    }));
    setCompileAllStatuses(initialStatuses);
    setCompileAllOpen(true);
    setCompileAllRunning(true);

    for (const board of boardsList) {
      const updateStatus = (patch: Partial<BoardCompileStatus>) =>
        setCompileAllStatuses((prev) => prev.map((s) => s.boardId === board.id ? { ...s, ...patch } : s));

      // Pi 3 doesn't need compilation
      if (board.boardKind === 'raspberry-pi-3') {
        updateStatus({ state: 'skipped' });
        continue;
      }

      const fqbn = BOARD_KIND_FQBN[board.boardKind];
      if (!fqbn) {
        updateStatus({ state: 'error', error: `No FQBN configured for ${board.boardKind}` });
        continue;
      }

      updateStatus({ state: 'compiling' });

      try {
        const groupFiles = useEditorStore.getState().getGroupFiles(board.activeFileGroupId);
        const sketchFiles = groupFiles.map((f) => ({ name: f.name, content: f.content }));
        const result = await compileCode(sketchFiles, fqbn);

        if (result.success) {
          const program = result.hex_content ?? result.binary_content ?? null;
          if (program) compileBoardProgram(board.id, program);
          updateStatus({ state: 'success' });
        } else {
          updateStatus({ state: 'error', error: result.stderr || result.error || 'Compilation failed' });
        }
      } catch (err) {
        updateStatus({ state: 'error', error: err instanceof Error ? err.message : String(err) });
      }
      // Always continue to next board
    }

    setCompileAllRunning(false);
  };

  const handleRunAll = () => {
    const boardsList = useSimulatorStore.getState().boards;
    for (const board of boardsList) {
      const isQemu = board.boardKind === 'raspberry-pi-3' ||
        board.boardKind === 'esp32' || board.boardKind === 'esp32-s3';
      if (!board.running && (isQemu || board.compiledProgram)) {
        startBoard(board.id);
      }
    }
    setCompileAllOpen(false);
  };

  const handleExport = async () => {
    try {
      const { components, wires, boardPosition, boardType: legacyBoardType } = useSimulatorStore.getState();
      const projectName = files.find((f) => f.name.endsWith('.ino'))?.name.replace('.ino', '') || 'velxio-project';
      await exportToWokwiZip(files, components, wires, legacyBoardType, projectName, boardPosition);
    } catch (err) {
      setMessage({ type: 'error', text: 'Export failed.' });
    }
  };

  const handleImportFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!importInputRef.current) return;
    importInputRef.current.value = '';
    if (!file) return;
    try {
      const result = await importFromWokwiZip(file);
      const { loadFiles } = useEditorStore.getState();
      const { setComponents, setWires, setBoardType, setBoardPosition, stopSimulation } = useSimulatorStore.getState();
      stopSimulation();
      if (result.boardType) setBoardType(result.boardType);
      setBoardPosition(result.boardPosition);
      setComponents(result.components);
      setWires(result.wires);
      if (result.files.length > 0) loadFiles(result.files);
      setMessage({ type: 'success', text: `Imported ${file.name}` });
      if (result.libraries.length > 0) {
        setPendingLibraries(result.libraries);
        setInstallModalOpen(true);
      }
    } catch (err: any) {
      setMessage({ type: 'error', text: err?.message || 'Import failed.' });
    }
  };

  return (
    <>
      <div className="editor-toolbar-wrapper" style={{ position: 'relative' }}>
        {/* Compile All progress panel — floats above the toolbar */}
        {compileAllOpen && (
          <CompileAllProgress
            statuses={compileAllStatuses}
            isRunning={compileAllRunning}
            onRunAll={handleRunAll}
            onClose={() => setCompileAllOpen(false)}
          />
        )}
      <div className="editor-toolbar" ref={toolbarRef}>
        {/* Active board context pill */}
        {activeBoard && (
          <div
            className="tb-board-pill"
            style={{ borderColor: BOARD_PILL_COLOR[activeBoard.boardKind], color: BOARD_PILL_COLOR[activeBoard.boardKind] }}
            title={`Editing: ${BOARD_KIND_LABELS[activeBoard.boardKind]}`}
          >
            <span className="tb-board-pill-icon">{BOARD_PILL_ICON[activeBoard.boardKind]}</span>
            <span className="tb-board-pill-label">{BOARD_KIND_LABELS[activeBoard.boardKind]}</span>
            {activeBoard.running && <span className="tb-board-pill-running" title="Running" />}
          </div>
        )}

        <div className="toolbar-group">
          {/* Compile */}
          <button
            onClick={handleCompile}
            disabled={compiling}
            className="tb-btn tb-btn-compile"
            title={compiling ? 'Compiling…' : 'Compile (Ctrl+B)'}
          >
            {compiling ? (
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="spin">
                <path d="M21 12a9 9 0 1 1-6.219-8.56" />
              </svg>
            ) : (
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
              </svg>
            )}
          </button>

          <div className="tb-divider" />

          {/* Run */}
          <button
            onClick={handleRun}
            disabled={running || (!['raspberry-pi-3','esp32','esp32-s3'].includes(activeBoard?.boardKind ?? '') && !compiledHex && !activeBoard?.compiledProgram)}
            className="tb-btn tb-btn-run"
            title="Run"
          >
            <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor" stroke="none">
              <polygon points="5,3 19,12 5,21" />
            </svg>
          </button>

          {/* Stop */}
          <button
            onClick={handleStop}
            disabled={!running}
            className="tb-btn tb-btn-stop"
            title="Stop"
          >
            <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor" stroke="none">
              <rect x="3" y="3" width="18" height="18" rx="2" />
            </svg>
          </button>

          {/* Reset */}
          <button
            onClick={handleReset}
            disabled={!compiledHex}
            className="tb-btn tb-btn-reset"
            title="Reset"
          >
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
              <path d="M3 3v5h5" />
            </svg>
          </button>

          {boards.length > 1 && (
            <>
              <div className="tb-divider" />

              {/* Compile All */}
              <button
                onClick={handleCompileAll}
                disabled={compileAllRunning}
                className="tb-btn tb-btn-compile-all"
                title="Compile all boards"
              >
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
                  <path d="M6 20h4M14 4l4 4" strokeDasharray="2 2" />
                </svg>
              </button>

              {/* Run All */}
              <button
                onClick={handleRunAll}
                disabled={running}
                className="tb-btn tb-btn-run-all"
                title="Run all boards"
              >
                <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor" stroke="none">
                  <polygon points="3,3 11,12 3,21" />
                  <polygon points="13,3 21,12 13,21" />
                </svg>
              </button>
            </>
          )}
        </div>

        <div className="toolbar-group toolbar-group-right">
          {/* Status message */}
          {message && (
            <span className={`tb-status tb-status-${message.type}`} title={message.text}>
              {message.type === 'success' ? (
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                  <polyline points="20 6 9 17 4 12" />
                </svg>
              ) : (
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                  <circle cx="12" cy="12" r="10" />
                  <line x1="12" y1="8" x2="12" y2="12" />
                  <line x1="12" y1="16" x2="12.01" y2="16" />
                </svg>
              )}
              <span className="tb-status-text">{message.text}</span>
            </span>
          )}

          {/* Hidden file input for import (always present) */}
          <input
            ref={importInputRef}
            type="file"
            accept=".zip"
            style={{ display: 'none' }}
            onChange={handleImportFile}
          />

          {/* Secondary buttons — hidden when toolbar is narrow */}
          {!overflowCollapsed && (
            <>
              {/* Import Wokwi zip */}
              <button
                onClick={() => importInputRef.current?.click()}
                className="tb-btn tb-btn-lib"
                title="Import Wokwi zip"
              >
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                  <polyline points="7 10 12 15 17 10" />
                  <line x1="12" y1="15" x2="12" y2="3" />
                </svg>
              </button>

              {/* Export Wokwi zip */}
              <button
                onClick={handleExport}
                className="tb-btn tb-btn-lib"
                title="Export as Wokwi zip"
              >
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                  <polyline points="17 8 12 3 7 8" />
                  <line x1="12" y1="3" x2="12" y2="15" />
                </svg>
              </button>

              {/* Libraries */}
              <button
                onClick={() => setLibManagerOpen(true)}
                className="tb-btn tb-btn-lib"
                title="Library Manager"
              >
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z" />
                  <path d="m3.3 7 8.7 5 8.7-5" />
                  <path d="M12 22V12" />
                </svg>
              </button>
            </>
          )}

          {/* Overflow (…) button — shown when toolbar is narrow */}
          {overflowCollapsed && (
            <div className="tb-overflow-wrap" ref={overflowMenuRef}>
              <button
                onClick={() => setOverflowOpen((v) => !v)}
                className={`tb-btn tb-btn-overflow${overflowOpen ? ' tb-btn-overflow-active' : ''}`}
                title="More actions"
              >
                <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none">
                  <circle cx="5"  cy="12" r="2" />
                  <circle cx="12" cy="12" r="2" />
                  <circle cx="19" cy="12" r="2" />
                </svg>
              </button>

              {overflowOpen && (
                <div className="tb-overflow-menu">
                  <button
                    className="tb-overflow-item"
                    onClick={() => { importInputRef.current?.click(); setOverflowOpen(false); }}
                  >
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                      <polyline points="7 10 12 15 17 10" />
                      <line x1="12" y1="15" x2="12" y2="3" />
                    </svg>
                    Import Wokwi zip
                  </button>
                  <button
                    className="tb-overflow-item"
                    onClick={() => { handleExport(); setOverflowOpen(false); }}
                  >
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                      <polyline points="17 8 12 3 7 8" />
                      <line x1="12" y1="3" x2="12" y2="15" />
                    </svg>
                    Export as Wokwi zip
                  </button>
                  <button
                    className="tb-overflow-item"
                    onClick={() => { setLibManagerOpen(true); setOverflowOpen(false); }}
                  >
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z" />
                      <path d="m3.3 7 8.7 5 8.7-5" />
                      <path d="M12 22V12" />
                    </svg>
                    Library Manager
                  </button>
                </div>
              )}
            </div>
          )}

          <div className="tb-divider" />

          {/* Output Console toggle */}
          <button
            onClick={() => setConsoleOpen((v) => !v)}
            className={`tb-btn tb-btn-output${consoleOpen ? ' tb-btn-output-active' : ''}`}
            title="Toggle Output Console"
          >
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="4 17 10 11 4 5" />
              <line x1="12" y1="19" x2="20" y2="19" />
            </svg>
          </button>
        </div>
      </div>
      </div>

      {/* Error detail bar */}
      {message?.type === 'error' && message.text.length > 40 && !consoleOpen && (
        <div className="toolbar-error-detail">{message.text}</div>
      )}

      <LibraryManagerModal isOpen={libManagerOpen} onClose={() => setLibManagerOpen(false)} />
      <InstallLibrariesModal
        isOpen={installModalOpen}
        onClose={() => setInstallModalOpen(false)}
        libraries={pendingLibraries}
      />
    </>
  );
};
