import React, {
  createContext,
  useState,
  useContext,
  ReactNode,
  useEffect,
  useMemo,
  useCallback,
} from 'react';
import { Task } from '../types/task';
import {
  AppConfig,
  LocationOption,
  PayloadOption,
  RobotActionOption,
} from '../types/config';
import { getConfig, executeTask } from '../services/configService';

interface TasksContextData {
  tasks: Task[];
  locations: LocationOption[];
  locationsBays: LocationOption[];
  payloads: PayloadOption[];
  robotActions: RobotActionOption[];
  serverUrl: string | null;
  getTaskById: (id: string) => Task | undefined;
  updateTask: (updatedTask: Task) => void;
  runTask: (id: string) => void;
  refreshConfig: () => Promise<void>;
  isConfigLoaded: boolean;
  fetchTaskDetail: (taskId: string) => Promise<void>;
}

const TasksContext = createContext<TasksContextData>({} as TasksContextData);

export const TasksProvider: React.FC<{ children: ReactNode }> = ({
  children,
}) => {
  const [tasks, setTasks] = useState<Task[]>([]);
  const [locations, setLocations] = useState<LocationOption[]>([]);
  const [locationsBays, setLocationsBays] = useState<LocationOption[]>([]);
  const [payloads, setPayloads] = useState<PayloadOption[]>([]);
  const [robotActions, setRobotActions] = useState<RobotActionOption[]>([]);
  const [isConfigLoaded, setIsConfigLoaded] = useState(false);
  const [serverUrl, setServerUrl] = useState<string | null>(null);

  const fetchTasks = useCallback(async (baseUrl: string, endpoint: string) => {
    try {
      if (baseUrl && endpoint) {
        const fetchUrl = `${baseUrl}${endpoint}?pageNum=1&pageSize=100`;
        console.log('Fetching tasks from:', fetchUrl);
        const response = await fetch(fetchUrl);

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const responseData = await response.json();
        console.log('responseData', responseData);

        if (responseData && responseData.code === 200) {
          const fetchedTasks = responseData.data.list.map((task: any) => {
            let detail = task.detail;
            if (detail && typeof detail === 'string') {
              try {
                detail = JSON.parse(detail);
              } catch (e) {
                console.error('解析任务详情失败 (list):', e);
                detail = null;
              }
            }
            return {
              ...task,
              name: task.label,
              parameters: task.parameters || {},
              detail: detail,
            };
          });
          setTasks(fetchedTasks);
        } else {
          console.error('获取任务列表失败: responseData.code is not 200');
          setTasks([]);
        }
      }
    } catch (error) {
      console.error('获取任务列表失败:', error);
      if (error instanceof Error) {
        console.error('Error message:', error.message);
      }
      setTasks([]);
    }
  }, []); // Empty dependency array as it has no external dependencies from component scope

  useEffect(() => {
    const loadApp = async () => {
      try {
        const config = await getConfig();
        if (config) {
          applyConfig(config);
          setIsConfigLoaded(true);
          if (config.serverUrl && config.apiEndpoints) {
            await fetchTasks(config.serverUrl, config.apiEndpoints.getTasks);
          }
        } else {
          console.log('没有找到配置文件，使用空数据');
          setIsConfigLoaded(false);
        }
      } catch (error) {
        console.error('加载配置失败:', error);
        setIsConfigLoaded(false);
      }
    };

    loadApp();
  }, [fetchTasks]);

  const [apiEndpoints, setApiEndpoints] = useState<{
    getTasks: string;
    getTaskDetail: string;
    runTask: string;
  } | null>(null);

  const applyConfig = (config: AppConfig) => {
    setLocations(config.locations || []);
    setLocationsBays(config.locationsBays || []);
    setPayloads(config.payloads || []);
    setRobotActions(config.robotActions || []);
    if (config.serverUrl) {
      setServerUrl(config.serverUrl);
    }
    if (config.apiEndpoints) {
      setApiEndpoints(config.apiEndpoints);
    }
  };

  const refreshConfig = useCallback(async () => {
    try {
      // await clearCachedConfig(); // 通常刷新不需要清除缓存
      const config = await getConfig();
      if (config) {
        applyConfig(config);
        setIsConfigLoaded(true);
        if (config.serverUrl && config.apiEndpoints) {
          await fetchTasks(config.serverUrl, config.apiEndpoints.getTasks);
        }
      } else {
        console.log('刷新配置时没有找到配置文件');
        setIsConfigLoaded(false);
      }
    } catch (error) {
      console.error('刷新配置失败:', error);
      setIsConfigLoaded(false);
    }
  }, [fetchTasks]);

  const getTaskById = useCallback(
    (id: string) => {
      const task = tasks.find(t => t.id === id);
      if (task && !task.detail) {
        // fetchTaskDetail(id); // 详情在编辑页面获取
      }
      return task;
    },
    [tasks],
  );

  const fetchTaskDetail = useCallback(
    async (taskId: string) => {
      try {
        if (serverUrl && apiEndpoints) {
          const endpoint = apiEndpoints.getTaskDetail.replace(
            '{taskId}',
            taskId,
          );
          const url = `${serverUrl}${endpoint}`;
          console.log('Fetching task detail from:', url);
          const response = await fetch(url);

          if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
          }

          const responseData = await response.json();
          console.log('task detail responseData', responseData);

          if (responseData && responseData.code === 200) {
            let taskDetail = responseData.data.detail;
            if (taskDetail && typeof taskDetail === 'string') {
              try {
                taskDetail = JSON.parse(taskDetail);
              } catch (e) {
                console.error('解析任务详情失败 (detail):', e);
                taskDetail = null;
              }
            }
            setTasks(prevTasks =>
              prevTasks.map(task =>
                task.id === taskId ? { ...task, detail: taskDetail } : task,
              ),
            );
          } else {
            console.error('获取任务详情失败: responseData.code is not 200');
          }
        }
      } catch (error) {
        console.error('获取任务详情失败:', error);
      }
    },
    [serverUrl, apiEndpoints],
  );

  const updateTask = useCallback((updatedTask: Task) => {
    setTasks(prevTasks =>
      prevTasks.map(task => (task.id === updatedTask.id ? updatedTask : task)),
    );
  }, []);

  const runTask = useCallback(
    async (id: string) => {
      const task = tasks.find(t => t.id === id);
      if (!task || !serverUrl || !apiEndpoints) return;

      setTasks(prevTasks =>
        prevTasks.map(t => (t.id === id ? { ...t, status: 1 } : t)),
      );

      try {
        const parameters = Object.entries(task.parameters).reduce(
          (acc, [key, param]) => {
            if (param) {
              acc[key] = param.value;
            }
            return acc;
          },
          {} as { [key: string]: any },
        );

        const endpoint = apiEndpoints.runTask.replace('{taskId}', task.id);
        await executeTask(serverUrl, endpoint, {
          name: task.name,
          parameters: parameters,
        });

        setTimeout(() => {
          setTasks(prevTasks =>
            prevTasks.map(t => (t.id === id ? { ...t, status: 2 } : t)),
          );
        }, 5000);
      } catch (error) {
        console.error('任务执行失败:', error);
        setTasks(prevTasks =>
          prevTasks.map(t => (t.id === id ? { ...t, status: 3 } : t)),
        );
      }
    },
    [tasks, serverUrl, apiEndpoints],
  );

  const contextValue = useMemo(
    () => ({
      tasks,
      locations,
      locationsBays,
      payloads,
      robotActions,
      serverUrl,
      getTaskById,
      updateTask,
      runTask,
      refreshConfig,
      isConfigLoaded,
      fetchTaskDetail,
    }),
    [
      tasks,
      locations,
      locationsBays,
      payloads,
      robotActions,
      serverUrl,
      getTaskById,
      updateTask,
      runTask,
      refreshConfig,
      isConfigLoaded,
      fetchTaskDetail,
    ],
  );

  return (
    <TasksContext.Provider value={contextValue}>
      {children}
    </TasksContext.Provider>
  );
};

export function useTasks() {
  return useContext(TasksContext);
}
