// LoggerProvider.tsx
import React, {
  createContext,
  useContext,
  useState,
  useCallback,
  useMemo,
  useEffect,
} from "react";
import { MathUtils } from "three";

export type LogType = "log" | "info" | "warning" | "error" | "success";

export interface LogEntry {
  id: string;
  type: LogType;
  message: string;
  timestamp: Date;
}

interface LoggerContextValue {
  logs: LogEntry[];
  setLogs: React.Dispatch<React.SetStateAction<LogEntry[]>>;
  isLogListVisible: boolean;
  setIsLogListVisible: React.Dispatch<React.SetStateAction<boolean>>;
  selectedTab: LogType | "all";
  setSelectedTab: React.Dispatch<React.SetStateAction<LogType | "all">>;
  log: (message: string) => void;
  info: (message: string) => void;
  warn: (message: string) => void;
  error: (message: string) => void;
  success: (message: string) => void;
  clear: () => void;
}

const LoggerContext = createContext<LoggerContextValue | undefined>(undefined);

export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  const [logs, setLogs] = useState<LogEntry[]>([]);
  const [isLogListVisible, setIsLogListVisible] = useState<boolean>(false);
  const [selectedTab, setSelectedTab] = useState<LogType | "all">("all");

  const addLog = useCallback((type: LogType, message: string) => {
    const newLog: LogEntry = {
      id: MathUtils.generateUUID(),
      type,
      message,
      timestamp: new Date(),
    };
    setLogs((prevLogs) => [...prevLogs, newLog]);
  }, []);

  const loggerMethods: LoggerContextValue = useMemo(
    () => ({
      logs,
      setLogs,
      isLogListVisible,
      setIsLogListVisible,
      selectedTab,
      setSelectedTab,
      log: (message: string) => addLog("log", message),
      info: (message: string) => addLog("info", message),
      warn: (message: string) => addLog("warning", message),
      error: (message: string) => addLog("error", message),
      success: (message: string) => addLog("success", message),
      clear: () => {
        if (selectedTab !== "all") {
          setLogs((prevLogs) =>
            prevLogs.filter((log) => log.type !== selectedTab)
          );
        } else {
          setLogs([]);
        }
      },
    }),
    [
      logs,
      setLogs,
      isLogListVisible,
      setIsLogListVisible,
      selectedTab,
      setSelectedTab,
      addLog,
    ]
  );
  useEffect(() => {
    (window as any).echo = {
      log: loggerMethods.log,
      info: loggerMethods.info,
      warn: loggerMethods.warn,
      error: loggerMethods.error,
      success: loggerMethods.success,
      clear: loggerMethods.clear,
    };
  }, [loggerMethods]);

  return (
    <LoggerContext.Provider value={loggerMethods}>
      {children}
    </LoggerContext.Provider>
  );
};

export const useLogger = () => {
  const context = useContext(LoggerContext);
  if (!context) {
    throw new Error("useLogger must be used within a LoggerProvider");
  }
  return context;
};
