"use client";

import {
  type ReactNode,
  createContext,
  use,
  useEffect,
  useRef,
  useState,
  useSyncExternalStore,
} from "react";
import { useStore } from "zustand";
import { privateInstance } from "@/configs/axiosConfig";
import {
  createWishlistStore,
  defaultInitState,
  STORAGE_KEY,
  WishlistItem,
} from "@/stores/wishlist";
import { useAuthStore } from "./AuthStoreProviders";
import { storage } from "@/configs/storage";

export type WishlistStoreApi = ReturnType<typeof createWishlistStore>;

export const WishlistStoreContext = createContext<WishlistStoreApi | undefined>(
  undefined,
);

export interface WishlistProviderProps {
  children: ReactNode;
}

export const WishlistProvider = ({ children }: WishlistProviderProps) => {
  const [store] = useState(() => createWishlistStore(defaultInitState));
  const { isAuthenticated } = useAuthStore((state) => state);
  const prevAuth = useRef<boolean | null>(null);

  const isMounted = useSyncExternalStore(
    () => () => {},
    () => true,
    () => false,
  );

  // Handle Initial Load and Auth Transitions
  useEffect(() => {
    if (!isMounted) return;

    // 1. First-time initialization
    if (prevAuth.current === null) {
      store.getState().loadFromStorage();
      store.getState().setLoggedIn(isAuthenticated);

      if (isAuthenticated) {
        store.getState().fetchFromServer();
      }
      prevAuth.current = isAuthenticated;
      return;
    }

    // 2. Detect change in Auth status
    if (prevAuth.current === isAuthenticated) return;

    const wasLoggedIn = prevAuth.current;
    prevAuth.current = isAuthenticated;
    store.getState().setLoggedIn(isAuthenticated);

    // SUCCESSFUL LOGIN: Sync guest items into the account
    if (!wasLoggedIn && isAuthenticated) {
      // Backup Guest wishlist so we can restore it on logout
      store.getState().backup();

      // Fetch Account items and merge with local Guest items
      store
        .getState()
        .fetchFromServer()
        .then(() => {
          const mergedItems = store.getState().getItems();
          const pIds = mergedItems.map((i) => i.project_id);

          if (pIds.length > 0) {
            privateInstance
              .post("/wishlist", { project_ids: pIds })
              .then(() => {
                // Final refresh to get Database IDs for the synced items
                store.getState().fetchFromServer();
              })
              .catch((err) => {
                console.warn("Wishlist: Sync POST failed", err);
              });
          }
        });
    }

    // LOGOUT: Restore pre-login state
    if (wasLoggedIn && !isAuthenticated) {
      store.getState().restore();
    }
  }, [isAuthenticated, isMounted, store]);

  return (
    <WishlistStoreContext.Provider value={store}>
      {children}
    </WishlistStoreContext.Provider>
  );
};

// Public hook for components
export const useWishlist = () => {
  const storeApi = use(WishlistStoreContext);
  if (!storeApi) {
    throw new Error("useWishlist must be within WishlistProvider");
  }

  const items = useStore(storeApi, (s) => s.items);
  const storeAdd = useStore(storeApi, (s) => s.addItem);
  const storeRemove = useStore(storeApi, (s) => s.removeItem);
  const isLoggedIn = useStore(storeApi, (s) => s.isLoggedIn);

  const isInWishlist = (projectId: number) =>
    items.some((item) => item.project_id === projectId);

  const addItem = async (item: WishlistItem) => {
    // Optimistically update UI
    storeAdd(item);

    if (isLoggedIn) {
      try {
        // Sync the full state to the server
        const currentItems = storeApi.getState().items;
        const pIds = currentItems.map((i: WishlistItem) => i.project_id);
        await privateInstance.post("/wishlist", { project_ids: pIds });

        // Refresh to get the real Database ID for future deletions
        await storeApi.getState().fetchFromServer();
      } catch {
        // Silently skip API errors to maintain local reactivity
      }
    }
  };

  const removeItem = async (idOrProjectId: number) => {
    // Identify item by either its DB PK or its Project Identifier
    const item = items.find(
      (i) => i.id === idOrProjectId || i.project_id === idOrProjectId,
    );

    if (!item) return;

    // Local removal
    storeRemove(item.id);

    // Server removal if the item is known to the database
    const isServerSync = item.id !== item.project_id && item.id > 0;

    if (isLoggedIn && isServerSync) {
      try {
        await privateInstance.delete(`/wishlist/${item.id}`);
      } catch {
        // ignore
      }
    }
  };

  const clearWishlist = async () => {
    // Optimistic clear from state
    storeApi.getState().setItems([]);

    // Clear from localStorage
    if (typeof window !== "undefined") {
      storage.remove(STORAGE_KEY);
      // localStorage.removeItem("investra_wishlist_backup");
    }

    // Server removal
    if (isLoggedIn) {
      try {
        await privateInstance.delete("/wishlist");
      } catch {
        // ignore
      }
    }
  };

  return {
    items,
    count: items.length,
    addItem,
    removeItem,
    clearWishlist,
    isInWishlist,
    isLoggedIn,
  };
};
