/* eslint-disable react-refresh/only-export-components */
/* eslint-disable react-hooks/exhaustive-deps */
import React, { createContext, useContext, useReducer, useEffect } from 'react';
import { readDirectoryTree, readMarkdownFile, NODE_TYPES } from '../utils/fileUtils';

const initialState = {
  directoryTree: [],
  currentFile: null,
  currentContent: '',
  isLoading: false,
  error: null,
  sidebarOpen: true,
};

export const ACTIONS = {
  SET_DIRECTORY_TREE: 'SET_DIRECTORY_TREE',
  SET_CURRENT_FILE: 'SET_CURRENT_FILE',
  SET_CURRENT_CONTENT: 'SET_CURRENT_CONTENT',
  SET_LOADING: 'SET_LOADING',
  SET_ERROR: 'SET_ERROR',
  TOGGLE_SIDEBAR: 'TOGGLE_SIDEBAR',
  TOGGLE_NODE_EXPANSION: 'TOGGLE_NODE_EXPANSION',
};

function appReducer(state, action) {
  switch (action.type) {
    case ACTIONS.SET_DIRECTORY_TREE:
      return {
        ...state,
        directoryTree: action.payload,
        isLoading: false,
      };

    case ACTIONS.SET_CURRENT_FILE:
      return {
        ...state,
        currentFile: action.payload,
      };

    case ACTIONS.SET_CURRENT_CONTENT:
      return {
        ...state,
        currentContent: action.payload,
        isLoading: false,
      };

    case ACTIONS.SET_LOADING:
      return {
        ...state,
        isLoading: action.payload,
      };

    case ACTIONS.SET_ERROR:
      return {
        ...state,
        error: action.payload,
        isLoading: false,
      };

    case ACTIONS.TOGGLE_SIDEBAR:
      return {
        ...state,
        sidebarOpen: !state.sidebarOpen,
      };

    case ACTIONS.TOGGLE_NODE_EXPANSION:
      return {
        ...state,
        directoryTree: toggleNodeExpansion(state.directoryTree, action.payload),
      };

    default:
      return state;
  }
}

function toggleNodeExpansion(nodes, targetPath) {
  return nodes.map((node) => {
    if (node.path === targetPath) {
      return { ...node, isExpanded: !node.isExpanded };
    }
    if (node.children && node.children.length > 0) {
      return {
        ...node,
        children: toggleNodeExpansion(node.children, targetPath),
      };
    }
    return node;
  });
}

function findDefaultFilePath(nodes) {
  let homepagePath = null;
  let firstFilePath = null;

  const traverse = (list) => {
    for (const node of list) {
      if (node.type === NODE_TYPES.FILE) {
        if (!firstFilePath) {
          firstFilePath = node.path;
        }
        if (!homepagePath && node.name === '首页.md') {
          homepagePath = node.path;
        }
      }
      if (node.children && node.children.length > 0) {
        traverse(node.children);
      }
    }
  };

  traverse(nodes);
  return homepagePath || firstFilePath || null;
}

function expandTreeForPath(nodes, targetPath) {
  if (!targetPath) {
    return nodes;
  }

  const pathSegments = targetPath.split('/');
  pathSegments.pop();

  if (pathSegments.length === 0) {
    return nodes;
  }

  const prefixSet = new Set();
  pathSegments.reduce((acc, segment) => {
    const next = acc ? `${acc}/${segment}` : segment;
    prefixSet.add(next);
    return next;
  }, '');

  const expand = (list) =>
    list.map((node) => {
      const shouldExpand = prefixSet.has(node.path);
      const children = node.children ? expand(node.children) : [];
      return {
        ...node,
        isExpanded: shouldExpand,
        children,
      };
    });

  return expand(nodes);
}

const AppContext = createContext();

export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, initialState);

  const selectFile = async (filePath) => {
    try {
      dispatch({ type: ACTIONS.SET_LOADING, payload: true });
      dispatch({ type: ACTIONS.SET_CURRENT_FILE, payload: filePath });

      const content = await readMarkdownFile(filePath);
      dispatch({ type: ACTIONS.SET_CURRENT_CONTENT, payload: content });
    } catch (error) {
      dispatch({ type: ACTIONS.SET_ERROR, payload: error.message });
    }
  };

  const loadDirectoryTree = async () => {
    try {
      dispatch({ type: ACTIONS.SET_LOADING, payload: true });
      const tree = await readDirectoryTree();
      const defaultPath = findDefaultFilePath(tree);
      const enhancedTree = expandTreeForPath(tree, defaultPath);

      dispatch({ type: ACTIONS.SET_DIRECTORY_TREE, payload: enhancedTree });

      if (!state.currentFile && defaultPath) {
        await selectFile(defaultPath);
      }
    } catch (error) {
      dispatch({ type: ACTIONS.SET_ERROR, payload: error.message });
    }
  };

  const toggleSidebar = () => {
    dispatch({ type: ACTIONS.TOGGLE_SIDEBAR });
  };

  const toggleNodeExpansion = (nodePath) => {
    dispatch({ type: ACTIONS.TOGGLE_NODE_EXPANSION, payload: nodePath });
  };

  useEffect(() => {
    loadDirectoryTree();
  }, []);

  const value = {
    ...state,
    loadDirectoryTree,
    selectFile,
    toggleSidebar,
    toggleNodeExpansion,
  };

  return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
}

export function useApp() {
  const context = useContext(AppContext);
  if (!context) {
    throw new Error('useApp must be used within an AppProvider');
  }
  return context;
}

