"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, playNotificationSound } 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,
  playNotificationSound: () => void;
  statusCounts?: any;
  setStatusCounts?: React.Dispatch<React.SetStateAction<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 })
  const [statusCounts, setStatusCounts] = useState<any>(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(() => {
    const handleUnlock = () => {
      try {
        const audio = new Audio('/push.mp3');
        audio.volume = 0.01;
        const playPromise = audio.play();
        if (playPromise !== undefined) {
          playPromise.then(() => {
            audio.pause();
            audio.currentTime = 0;
            audio.volume = 1.0;
          }).catch(() => {});
        }
      } catch (e) {}
      window.removeEventListener('click', handleUnlock);
      window.removeEventListener('keydown', handleUnlock);
    };
    window.addEventListener('click', handleUnlock);
    window.addEventListener('keydown', handleUnlock);
    return () => {
      window.removeEventListener('click', handleUnlock);
      window.removeEventListener('keydown', handleUnlock);
    };
  }, []);

  useEffect(() => {
    if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
      const handleServiceWorkerMessage = (event: MessageEvent) => {
        if (event.data && event.data.type === 'PUSH_NOTIFICATION_RECEIVED') {
          try {
            playNotificationSound();
          } catch (err) {
            console.error('Error playing sound from SW message:', err);
          }
          if (event.data.payload) {
            setNotificationData(event.data.payload);
          }
        }
      };

      navigator.serviceWorker.addEventListener('message', handleServiceWorkerMessage);
      return () => {
        navigator.serviceWorker.removeEventListener('message', handleServiceWorkerMessage);
      };
    }
  }, []);

  useEffect(() => {
    if (notificationData) {
      try {
        playNotificationSound();
      } catch (err) {
        console.error("Error playing push notification sound:", err);
      }
      const title = notificationData?.data?.notification || notificationData?.notification?.title || notificationData?.data?.title || 'New Order Notification';
      const body = notificationData?.notification?.body || notificationData?.data?.body || notificationData?.data?.message || 'You have received a new notification.';
      sonnerToast(title, {
        description: body,
        duration: 3000,
        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 pendingToast = sessionStorage.getItem('pendingToast');
      if (pendingToast) {
        sessionStorage.removeItem('pendingToast');
        setTimeout(() => {
          toast.success(pendingToast, {
            duration: 3000,
            style: {
              fontSize: "13px",
              backgroundColor: "#fff",
            },
          });
        }, 300);
      }
      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 || err?.response?.data || err?.data;
    const message =
      typeof err === "string"
        ? err
        : errorBody?.message || errorBody?.error_description || err?.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,
    playNotificationSound,
    statusCounts,
    setStatusCounts
  };



  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;
