"use client";

import { createContext, useContext, ReactNode, useState, useEffect } from "react";
import { useRouter } from "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';
import useFCM from "@/utils/useFCM";
import { Bell } from "lucide-react";
import { useDispatch } from "react-redux";
import { cartReset, updateAddress } from "@/store/actions/user/userAction";
import { AppDispatch } from "@/store/store";

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

interface GlobalContextType {
  setUserInfo: React.Dispatch<React.SetStateAction<any | null>>;
  setOrderInfo: React.Dispatch<React.SetStateAction<any | null>>;
  userInfo: AuthInterface | null;
  orderInfo: 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
  getCategory: any
  categoryList: any
  setCategoryList: 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);

  useEffect(() => {
    setUserInfo(initialUserInfo || null);
  }, [initialUserInfo]);

  const [categoryList, setCategoryList] = useState<any>([])
  const [loacte, setLoacte] = useState<any>({ lat: null, lng: null })
  const [orderInfo, setOrderInfo] = useState<any | null>(null);
  const [notificationData, setNotificationData] = useState<any | null>(null);
  const [exportLoading, setExportLoading] = useState(false)
  const [locationData, setLocationData] = useState<any>(null)
  const access_token = parseCookies()[COOKIES_USER_ACCESS_TOKEN]

  const {
    messages: pushMessages,
  } = useFCM(userInfo?.access_token || "");
  if (userInfo?.access_token) {
    apis.setToken(userInfo?.access_token || "");
  }


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

  useEffect(() => {
    if (pushMessages) {
      const notificationTitle = pushMessages?.notification?.title || 'New Notification';
      const notificationBody = pushMessages?.notification?.body || '';
      const notificationType = pushMessages?.data?.type || '';

      sonnerToast(notificationTitle, {
        icon: (
          <span className="w-5 h-5">
            <Bell />
          </span>
        ),
        description: notificationBody,
        duration: 5000,
        position: "top-right",
        action: notificationType === 'admin_push' ? {
          label: "View",
          onClick: () => {
            // Handle notification click action
            // console.log('Notification clicked');
          },
        } : undefined,
      });
    }
  }, [pushMessages]);

  useEffect(() => {
    if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js')
        .then((registration) => {
        })
        .catch((error) => {
          console.error('Service Worker registration failed:', error);
        });
      navigator.serviceWorker.addEventListener('message', (event) => {
        if (event.data?.isFirebaseMessaging || event.data?.messageType === 'push-received') {
          const notificationTitle = event.data?.notification?.title || 'New Notification';
          const notificationBody = event.data?.notification?.body || '';

          sonnerToast(notificationTitle, {
            icon: (
              <span className="w-5 h-5">
                <Bell />
              </span>
            ),
            description: notificationBody,
            duration: 3000,
            position: "top-right",
          });
        } else if (event.data?.type === 'NOTIFICATION_CLICKED') {
          const { title, body, data } = event.data.payload;
          sonnerToast(title, {
            icon: (
              <span className="w-5 h-5">
                <Bell />
              </span>
            ),
            description: body,
            duration: 3000,
            position: "top-right",
          });
        }
      });
    }
  }, []);


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

    }
  }, [access_token]);

  useEffect(() => {
    const fetchUserProfile = async () => {
      if (access_token && !userInfo) {
        try {
          apis.setToken(access_token);
          const apiRes = await apis.Profile.getProfile();
          const { data, appConfiguration, loyalty_wallet } = apiRes;
          setUserInfo({
            ...data,
            appConfiguration,
            loyalty_wallet,
            access_token: access_token,
          });
        } catch (error) {
          console.error("Error auto-fetching user profile:", error);
          destroyCookie(null, COOKIES_USER_ACCESS_TOKEN, {
            path: "/",
          });
          setUserInfo(null);
          apis.setToken("");
          dispatch(cartReset());
          dispatch(updateAddress(null));
          localStorage.clear();
          sessionStorage.clear();
        }
      }
    };

    fetchUserProfile();
  }, [access_token]);



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


  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("")

      localStorage.clear();
      sessionStorage.clear();

      const cookies = document.cookie.split(";");
      for (let i = 0; i < cookies.length; i++) {
        const cookie = cookies[i];
        const eqPos = cookie.indexOf("=");
        const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
        document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
      }

      router.replace(`/home`);
    } catch (error) {
      Toast.error(error)
    }
  }


  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,) => {
    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({
          ...apiRes?.data,
          appConfiguration: apiRes?.appConfiguration,
          loyalty_wallet: apiRes?.loyalty_wallet,
          access_token: accessToken,
        });
        router.replace("/dashboard")
      } catch (error: any) {
        Toast.error(error);
      } finally {
        // setLoading(false)
      }
  };



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


  const getCategory = async () => {
    try {
      const apiRes = await apis.category.get();
      const { data } = apiRes
      setCategoryList(data);
      return data
    } catch (error) { }
  }
  const getLocation = async () => {
    try {
      navigator.geolocation.getCurrentPosition(
        async (position) => {
          const { latitude, longitude } = position.coords;
          setLoacte({ lat: latitude, lng: longitude })
        },
        (error) => {
          console.error("Location error:", error);
        }
      );
    } catch (error) { }
  }
  useEffect(() => {
    getLocation();
    // let token:any = sessionStorage.getItem('token');
    // setUserInfo((prev) => ({
    //   ...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 message =
      typeof err === "string"
        ? err
        : err?.response?.data?.message ||
        err?.response?.body?.message ||
        err?.message || err?.response?.body ||
        "Something went wrong";
    toast.error(message, {
      duration: 2000,
      style: {
        fontSize: "13px",
        backgroundColor: "#fff",
      },
    });
  };

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

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



  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;
