"use client";

import { createContext, useContext, ReactNode, useState, useEffect } from "react";
import { useRouter } from "next/navigation"; // Updated to next/navigation
import { destroyCookie, parseCookies, setCookie } from "nookies";
import { COOKIES_USER_ACCESS_TOKEN } from "./actionTypes";
import toast from "react-hot-toast";
import apis from "@/utils/apis";
import { AuthInterface } from "./interfaces";
import { getFirebaseMessageToken, onMessageListener } from "@/utils/firebase";
import { isSupported } from "firebase/messaging";
import dayjs from "dayjs";
import { toast as sonnerToast } from 'sonner';


type ToastFunction = (msg: any) => void;

interface GlobalContextType {
  setUserInfo: React.Dispatch<React.SetStateAction<any | null>>;
  setOrderInfo: React.Dispatch<React.SetStateAction<any | null>>;
  setActiveModal: React.Dispatch<React.SetStateAction<any | null>>;
  userInfo: AuthInterface | null;
  orderInfo: any | null;
  activeModal: any | null;
  stopSpaceEnter: (event: React.KeyboardEvent) => boolean;
  logout: () => void;
  deleteAccount: () => void
  Toast: {
    error: ToastFunction;
    success: ToastFunction;
  };
  requestNotification: any,
  setNotificationData: any,
  notificationData: any,
  loginWithSocial: any,
  downloadCSV: any,
  setExportLoading: any,
  exportLoading: any,
  getProfile: any,
  setLocationData: any,
  locationData: any,
  loacte: any
}

export const GlobalContext = createContext<GlobalContextType | undefined>(undefined);

interface GlobalProviderProps {
  children: ReactNode;
  userInfo?: AuthInterface;
}

function GlobalProvider({ children, userInfo: initialUserInfo }: GlobalProviderProps) {
  const router = useRouter();
  const [userInfo, setUserInfo] = useState<AuthInterface | null>(initialUserInfo || null);
  const [orderInfo, setOrderInfo] = useState<any | null>(null);
  const [activeModal, setActiveModal] = useState<string | null>(null);
  const [notificationData, setNotificationData] = useState<any | null>(null);
  const [exportLoading, setExportLoading] = useState(false)
  const access_token = parseCookies()[COOKIES_USER_ACCESS_TOKEN]

  const [locationData, setLocationData] = useState<any>(null)
  const [loacte, setLoacte] = useState<any>({ lat: null, lng: null })

  useEffect(() => {
    if (userInfo?.access_token) {
      apis.setToken(userInfo.access_token);
    }
  }, [userInfo?.access_token]);

  const getNotificationListener = async () => {
    try {
      const supportedBrowser = await isSupported()
      if (supportedBrowser) {
        Promise.resolve(onMessageListener(setNotificationData))
      }
    } catch (error) {

    }
  }

  useEffect(() => {
    if (notificationData) {
      sonnerToast(notificationData?.data?.notification, {
        // icon: <span className='w-5 h-5'><Icons.NotiIcon /></span>,
        // icon: <span className='w-5 h-5'>:bell:</span>,
        description: notificationData?.notification?.body,
        duration: 2000,
        position: 'top-right',
      });
    }
  }, [notificationData]);

  useEffect(() => {
    try {
      if (typeof window !== "undefined" && access_token) {
        getNotificationListener()
      }
    } catch (error) {

    }
  }, [access_token]);


  const logout = async (): Promise<void> => {
    try {
      await apis.User.logout()
      setUserInfo(null);
      destroyCookie(null, COOKIES_USER_ACCESS_TOKEN, {
        maxAge: 0,
        path: "/",
      });
      apis.setToken("")
      router.replace(`/`);
    } catch (error) {
      console.error("Error during logout:", error);
      router.replace(`/`);
      setUserInfo(null);
      destroyCookie(null, COOKIES_USER_ACCESS_TOKEN, {
        maxAge: 0,
        path: "/",
      });
      apis.setToken("")
    }
  };


  const deleteAccount = async () => {
    try {
      const apiRes = await apis.User.delete()
      Toast.success(apiRes?.data?.message)
      setUserInfo(null);
      destroyCookie(null, COOKIES_USER_ACCESS_TOKEN, {
        maxAge: 0,
        path: "/",
      });
      apis.setToken("")
      router.replace(`/`);
    } catch (error) {
      Toast.error(error)
    }
  }


  //export function

  const convertArrayToCSV = (dataArray: any) => {
    if (dataArray.length === 0) {
      return '';
    }
    const headers = Object.keys(dataArray[0]);
    const csvRows = dataArray.map((obj: any) =>
      headers.map(header => {
        const value = obj[header] ?? '';
        const escapedValue = String(value).replace(/"/g, '""');
        return /[",\n]/.test(escapedValue) ? `"${escapedValue}"` : escapedValue;
      }).join(',')
    );

    return [headers.join(','), ...csvRows].join('\n');
  };



  const formatDate = (timestamp: number) => {
    return dayjs(timestamp).format('DD MMM, YYYY'); // Format as "06 Jan, 2025"
  };

  const filterDataByKeys = (dataArray: any, keys: any) => {
    return dataArray.map((item: any) =>
      keys.reduce((obj: any, key: any) => {
        if (key in item) {
          if (key === 'updated_at' || key === 'created_at') {
            obj[key] = formatDate(item[key]);
          } else {
            obj[key] = item[key];
          }
        }
        return obj;
      }, {})
    );
  };

  const downloadCSV = (data: any, keysToInclude: any, filename = 'data.csv') => {
    const filteredData = filterDataByKeys(data, keysToInclude);
    const csvContent = convertArrayToCSV(filteredData);
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    const url = URL.createObjectURL(blob);
    link.href = url;
    link.setAttribute('download', filename);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  };


  // social login...............................
  const loginWithSocial = async (social_type: string, social_token: string,) => {
    debugger
    if (!social_token) return;
    destroyCookie(null, COOKIES_USER_ACCESS_TOKEN, {
      maxAge: 0,
      path: "/",
    });
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    if (social_token)
      try {

        // setLoading(true)
        const items = {
          social_type,
          social_token,
          timezone,
        } as any;
        const fcm_token = await requestNotification()
        if (fcm_token) {
          items["fcm_token"] = fcm_token
        }
        let apiRes = await apis.Auth.socialLogin(items);
        const data = apiRes?.data;

        const accessToken = data?.access_token;
        apis.setToken(apiRes?.data?.access_token);
        if (accessToken) {
          setCookie(null, COOKIES_USER_ACCESS_TOKEN, accessToken, {
            path: `/`,
          });
        }
        setUserInfo(data);
        router.replace("/dashboard")
      } catch (error: any) {
        Toast.error(error);
      } finally {
        // setLoading(false)
      }
  };






  const getProfile = async () => {
    try {
      const apiRes = await apis.Profile.getProfile()
      const { data } = apiRes
      setUserInfo((prev) => ({
        ...prev,
        ...data,
      }));
      return data
    } catch (error) { }
  }

  useEffect(() => {
    if (typeof window !== "undefined") {
      const token = sessionStorage.getItem('token');
      if (token) {
        getProfile();
        setUserInfo((prev: any) => ({
          ...prev,
          access_token: token,
        }));
      }
    }
  }, []);


  // Prevent space or invalid key entry in inputs
  const stopSpaceEnter = (event: React.KeyboardEvent): boolean => {
    if (event.target instanceof HTMLInputElement) {
      if (event.target.value.length === 0 && event.key === " ") {
        event.preventDefault();
        return false;
      }
      if (!/^[a-zA-Z ]$/.test(event.key) && !event.ctrlKey && !event.metaKey) {
        event.preventDefault();
        return false;
      }
    }
    return true;
  };

  const requestNotification = async () => {
    if (!("Notification" in window)) {
      return "not"; // Notifications are not supported.
    }

    try {
      if (Notification.permission === "granted") {
        // If permission is already granted, fetch and return the token.
        return await getFirebaseMessageToken();
      }

      if (Notification.permission === "default") {
        // Request permission from the user.
        const permission = await Notification.requestPermission();
        if (permission === "granted") {
          return await getFirebaseMessageToken(); // Fetch and return the token.
        } else {
          return ""; // Permission denied or dismissed.
        }
      }

      // If permission is denied.
      return "";
    } catch (error) {
      console.error("Error requesting notification permission:", error);
      return ""; // Handle the error gracefully.
    }
  };


  // Success toast
  const success: ToastFunction = (message: string) => {
    toast.success(message, {
      duration: 2000,
      style: {
        fontSize: "13px",
        backgroundColor: "#fff",
      },
    });
  };


  // Error toast
  const error: ToastFunction = (err: any) => {
    const errorBody = err?.response?.body;
    const message =
      typeof err === "string" ? err : errorBody?.error_description || errorBody?.message || "An error occurred";
    toast.error(message, {
      duration: 2000,
      style: {
        fontSize: "13px",
        backgroundColor: "#fff",
      },
    });
  };

  // Toast object
  const Toast = {
    success,
    error,
  };

  // Context value
  const contextValue: GlobalContextType = {
    setUserInfo,
    setOrderInfo,
    setActiveModal,
    activeModal,
    orderInfo,
    userInfo,
    stopSpaceEnter,
    logout,
    deleteAccount,
    Toast,
    requestNotification,
    notificationData,
    setNotificationData,
    loginWithSocial,
    downloadCSV,
    setExportLoading,
    exportLoading,
    getProfile,
    setLocationData, locationData, loacte
  };



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

export function useGlobalContext(): GlobalContextType {
  const context = useContext(GlobalContext);
  if (context === undefined) {
    throw new Error("useGlobalContext must be used within a GlobalProvider");
  }
  return context;
}

export default GlobalProvider;
