import React, { useState, useEffect, useRef, createContext, useContext } from 'react';
import { HashRouter, Routes, Route } from 'react-router-dom';
import { Layout } from './components/layout/Layout';
import { HomePage } from './pages/HomePage';
import { IOMonitorPage } from './pages/IOMonitorPage';
import { RecipePage } from './pages/RecipePage';
import { HistoryPage } from './pages/HistoryPage';
import { SystemState, Recipe, IOPoint, LogEntry, RobotTarget, ConfigItem } from './types';
import { comms } from './communication';
import { AlertProvider, useAlert } from './contexts/AlertContext';
import { ThemeProvider } from './contexts/ThemeContext';
import { PickerMoveDialog } from './components/PickerMoveDialog';

// PickerMoveDialog 전역 상태 Context
interface PickerMoveContextType {
  isPickerMoveOpen: boolean;
  openPickerMove: () => Promise<boolean>;
  closePickerMove: () => void;
}

const PickerMoveContext = createContext<PickerMoveContextType | null>(null);

export const usePickerMove = () => {
  const context = useContext(PickerMoveContext);
  if (!context) {
    throw new Error('usePickerMove must be used within PickerMoveProvider');
  }
  return context;
};

// --- MOCK DATA ---


const INITIAL_IO: IOPoint[] = [
  ...Array.from({ length: 32 }, (_, i) => {
    let name = `DOUT_${i.toString().padStart(2, '0')}`;
    if (i === 0) name = "Tower Lamp Red";
    if (i === 1) name = "Tower Lamp Yel";
    if (i === 2) name = "Tower Lamp Grn";
    return { id: i, name, type: 'output' as const, state: false };
  }),
  ...Array.from({ length: 32 }, (_, i) => {
    let name = `DIN_${i.toString().padStart(2, '0')}`;
    let initialState = false;
    if (i === 0) name = "Front Door Sensor";
    if (i === 1) name = "Right Door Sensor";
    if (i === 2) name = "Left Door Sensor";
    if (i === 3) name = "Back Door Sensor";
    if (i === 4) { name = "Main Air Pressure"; initialState = true; }
    if (i === 5) { name = "Vacuum Generator"; initialState = true; }
    if (i === 6) { name = "Emergency Stop Loop"; initialState = true; }
    return { id: i, name, type: 'input' as const, state: initialState };
  })
];

// --- MAIN APP ---

// 내부 App 컴포넌트 (AlertContext 내부에서 사용)
function AppContent() {
  const [activeTab, setActiveTab] = useState<'recipe' | 'motion' | 'camera' | 'setting' | 'initialize' | null>(null);
  const [systemState, setSystemState] = useState<SystemState>(SystemState.IDLE);
  const [currentRecipe, setCurrentRecipe] = useState<Recipe>({ id: '0', name: 'No Recipe', lastModified: '-' });
  const [robotTarget, setRobotTarget] = useState<RobotTarget>({ x: 0, y: 0, z: 0 });
  const [logs, setLogs] = useState<LogEntry[]>([]);
  const [ioPoints, setIoPoints] = useState<IOPoint[]>([]);
  const [currentTime, setCurrentTime] = useState(new Date());
  const [isLoading, setIsLoading] = useState(true);
  const [isHostConnected, setIsHostConnected] = useState(false);
  const [isPickerMoveOpen, setIsPickerMoveOpen] = useState(false);
  const videoRef = useRef<HTMLVideoElement>(null);
  const { showAlert } = useAlert();

  // PickerMoveDialog 열기 함수 (백엔드에서 openManage 호출)
  const openPickerMove = async (): Promise<boolean> => {
    try {
      const result = await comms.openManage();
      if (!result.success) {
        showAlert({
          type: 'error',
          title: 'Cannot Open',
          message: result.message
        });
        return false;
      }
      setIsPickerMoveOpen(true);
      return true;
    } catch (error: any) {
      showAlert({
        type: 'error',
        title: 'Error',
        message: error.message || 'Failed to open manage dialog'
      });
      return false;
    }
  };

  // PickerMoveDialog 닫기 함수
  const closePickerMove = async () => {
    setIsPickerMoveOpen(false);
    try {
      const result = await comms.closeManage();
      if (result.shouldAutoInit) {
        const initResult = await comms.initializeDevice();
        if (!initResult.success) {
          console.error('[App] Auto-init failed:', initResult.message);
        }
      }
    } catch (error) {
      console.error('[App] closeManage error:', error);
    }
  };

  // -- COMMUNICATION LAYER --
  useEffect(() => {
    const unsubscribe = comms.subscribe((msg: any) => {
      if (!msg) return;

      if (msg.type === 'CONNECTION_STATE') {
        setIsHostConnected(msg.connected);
        addLog(msg.connected ? "HOST CONNECTED" : "HOST DISCONNECTED", msg.connected ? "info" : "warning");
      }

      // AUTO_OPEN_MANAGE 이벤트 처리 - 백엔드에서 IDLE 상태 진입 시 피커 이동 필요할 때 전송
      if (msg.type === 'AUTO_OPEN_MANAGE') {
        console.log('[App] AUTO_OPEN_MANAGE event received:', msg.data?.reason);
        addLog(`AUTO MANAGE: ${msg.data?.reason || 'Picker move required'}`, 'warning');
        // 이미 열려있지 않은 경우에만 열기
        if (!isPickerMoveOpen) {
          openPickerMove();
        }
      }

      if (msg.type === 'STATUS_UPDATE') {
        if (msg.position) {
          setRobotTarget({ x: msg.position.x, y: msg.position.y, z: msg.position.z });
        }
        if (msg.ioState) {
          setIoPoints(prev => {
            const newIO = [...prev];
            msg.ioState.forEach((update: { id: number, type: string, state: boolean }) => {
              const idx = newIO.findIndex(p => p.id === update.id && p.type === update.type);
              if (idx >= 0) newIO[idx] = { ...newIO[idx], state: update.state };
            });
            return newIO;
          });
        }
        if (msg.sysState) {
          setSystemState(msg.sysState as SystemState);
        }
      }
    });

    addLog("COMMUNICATION CHANNEL OPEN", "info");
    setIsHostConnected(comms.getConnectionState());

    const timer = setInterval(() => setCurrentTime(new Date()), 1000);
    return () => {
      clearInterval(timer);
      unsubscribe();
    };
  }, [isPickerMoveOpen]);

  // -- INITIALIZATION --
  useEffect(() => {
    const initSystem = async () => {
      addLog("SYSTEM STARTED", "info");
      // Initial IO data will be loaded by HomePage when it mounts
      try {
        const ioStr = await comms.getIOList();
        const ioData = JSON.parse(ioStr);

        // Handle new structured format: { inputs: [...], outputs: [...], interlocks: [...] }
        let flatIoList: IOPoint[] = [];
        if (ioData.inputs && ioData.outputs) {
          // New format - flatten inputs and outputs
          flatIoList = [
            ...ioData.outputs.map((io: any) => ({ id: io.id, name: io.name, type: 'output' as const, state: io.state })),
            ...ioData.inputs.map((io: any) => ({ id: io.id, name: io.name, type: 'input' as const, state: io.state }))
          ];
        } else if (Array.isArray(ioData)) {
          // Old format - already flat array
          flatIoList = ioData;
        }

        setIoPoints(flatIoList);
        addLog("IO LIST LOADED", "info");
      } catch (e) {
        addLog("FAILED TO LOAD IO DATA", "error");
      }
      setIsLoading(false);
    };
    initSystem();
  }, []);

  const addLog = (msg: string, type: 'info' | 'warning' | 'error' = 'info') => {
    setLogs(prev => [{ id: Date.now() + Math.random(), timestamp: new Date().toLocaleTimeString(), message: msg, type }, ...prev].slice(0, 50));
  };

  // Logic Helpers
  const doorStates = {
    front: ioPoints.find(p => p.id === 0 && p.type === 'input')?.state || false,
    right: ioPoints.find(p => p.id === 1 && p.type === 'input')?.state || false,
    left: ioPoints.find(p => p.id === 2 && p.type === 'input')?.state || false,
    back: ioPoints.find(p => p.id === 3 && p.type === 'input')?.state || false,
  };
  const isLowPressure = !(ioPoints.find(p => p.id === 4 && p.type === 'input')?.state ?? true);
  const isEmergencyStop = !(ioPoints.find(p => p.id === 6 && p.type === 'input')?.state ?? true);

  // -- COMMAND HANDLERS --

  const handleControl = async (action: 'start' | 'stop' | 'reset') => {
    if (isEmergencyStop && action === 'start') return addLog('EMERGENCY STOP ACTIVE', 'error');

    try {
      await comms.sendControl(action.toUpperCase());
      addLog(`CMD SENT: ${action.toUpperCase()}`, 'info');
    } catch (e) {
      addLog('COMM ERROR', 'error');
    }
  };

  const toggleIO = async (id: number, type: 'input' | 'output', forceState?: boolean) => {
    if (type === 'output') {
      const current = ioPoints.find(p => p.id === id && p.type === type)?.state;
      const nextState = forceState !== undefined ? forceState : !current;
      await comms.setIO(id, nextState);
    }
  };

  const moveAxis = async (axis: 'X' | 'Y' | 'Z', value: number) => {
    if (isEmergencyStop) return;
    await comms.moveAxis(axis, value);
    addLog(`CMD MOVE ${axis}: ${value}`, 'info');
  };

  const handleSaveConfig = async (newConfig: ConfigItem[]) => {
    try {
      await comms.saveConfig(JSON.stringify(newConfig));
      addLog("CONFIGURATION SAVED", "info");
    } catch (e) {
      console.error(e);
      addLog("FAILED TO SAVE CONFIG", "error");
    }
  };

  const handleSelectRecipe = async (r: Recipe) => {
    try {
      addLog(`LOADING: ${r.name}`, 'info');
      const result = await comms.selectRecipe(r.id);

      if (result.success) {
        setCurrentRecipe(r);
        addLog(`RECIPE LOADED: ${r.name}`, 'info');
      } else {
        addLog(`RECIPE LOAD FAILED: ${result.message}`, 'error');
      }
    } catch (error: any) {
      addLog(`RECIPE LOAD ERROR: ${error.message || 'Unknown error'}`, 'error');
      console.error('Recipe selection error:', error);
    }
  };

  const pickerMoveContextValue: PickerMoveContextType = {
    isPickerMoveOpen,
    openPickerMove,
    closePickerMove
  };

  return (
    <PickerMoveContext.Provider value={pickerMoveContextValue}>
      <HashRouter>
        <Layout
          currentTime={currentTime}
          isHostConnected={isHostConnected}
          robotTarget={robotTarget}
          onTabChange={setActiveTab}
          activeTab={activeTab}
          isLoading={isLoading}
        >
          <Routes>
            <Route
              path="/"
              element={
                <HomePage
                  systemState={systemState}
                  currentRecipe={currentRecipe}
                  robotTarget={robotTarget}
                  logs={logs}
                  ioPoints={ioPoints}
                  doorStates={doorStates}
                  isLowPressure={isLowPressure}
                  isEmergencyStop={isEmergencyStop}
                  isHostConnected={isHostConnected}
                  activeTab={activeTab}
                  onSelectRecipe={handleSelectRecipe}
                  onMove={moveAxis}
                  onControl={handleControl}
                  onSaveConfig={handleSaveConfig}
                  onCloseTab={() => setActiveTab(null)}
                  videoRef={videoRef}
                />
              }
            />
            <Route
              path="/io-monitor"
              element={
                <IOMonitorPage
                  onToggle={toggleIO}
                />
              }
            />
            <Route
              path="/recipe"
              element={<RecipePage />}
            />
            <Route
              path="/history"
              element={<HistoryPage />}
            />
          </Routes>
        </Layout>
      </HashRouter>

      {/* PickerMoveDialog - 전역에서 관리 */}
      <PickerMoveDialog
        isOpen={isPickerMoveOpen}
        onClose={closePickerMove}
      />
    </PickerMoveContext.Provider>
  );
}

// 외부 App 컴포넌트 - ThemeProvider + AlertProvider로 감싸기
export default function App() {
  return (
    <ThemeProvider>
      <AlertProvider>
        <AppContent />
      </AlertProvider>
    </ThemeProvider>
  );
}
