"use client";
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import {
  storeRecentlyViewedProduct,
  getRecentlyViewedProductsList,
} from "@/lib/actions/recentlyViewedProductActions";


interface RecentlyViewedState {
  productIds: string[];
}

const initialState: RecentlyViewedState = {
  productIds: [],
};

const loadFromStorage = (): string[] => {
  if (typeof window !== "undefined") {
    try {
      const stored = localStorage.getItem("recentlyViewedProductIds");
      return stored ? JSON.parse(stored) : [];
    } catch (error) {
      return [];
    }
  }
  return [];
};

// Update initial state with loaded data
const updatedInitialState: RecentlyViewedState = {
  ...initialState,
  productIds: loadFromStorage(),
};

const saveToStorage = (productIds: string[]): void => {
  try {
    if (productIds?.length) {
      const limited = productIds.slice(0, 20);
      localStorage.setItem("recentlyViewedProductIds", JSON.stringify(limited));
    }
  } catch (error) {
    // Silent fail
  }
};

const updateProductIds = (
  state: RecentlyViewedState,
  productId: string
): void => {
  if (!state.productIds) {
    state.productIds = [];
  }

  const existingIndex = state.productIds.indexOf(productId);
  if (existingIndex !== -1) {
    state.productIds.splice(existingIndex, 1);
  }

  state.productIds.unshift(productId);

  if (state.productIds.length > 20) {
    state.productIds = state.productIds.slice(0, 20);
  }

  saveToStorage(state.productIds);
};

export const addToRecentlyViewedThunk = createAsyncThunk<
  string,
  { productId: string; token: string | null; locale: string }
>("recentlyViewed/add", async ({ productId, token, locale }) => {
  if (token) {
    await storeRecentlyViewedProduct(productId, token, locale);
  }
  return productId;
});

export const syncLocalRecentlyViewedThunk = createAsyncThunk<
  void,
  { token: string; locale: string }
>("recentlyViewed/syncLocal", async ({ token, locale }) => {
  const localProductIds = loadFromStorage();
  if (localProductIds.length === 0) return;

  try {
    const serverProducts = await getRecentlyViewedProductsList(
      token,
      locale,
      20
    );
    const serverIds = new Set(serverProducts.map((p : any) => p.productId));
    const newProductIds = localProductIds.filter((id) => !serverIds.has(id));

    if (newProductIds.length > 0) {
      const syncPromises = newProductIds.map((id) =>
        storeRecentlyViewedProduct(id, token, locale)
      );
      await Promise.allSettled(syncPromises);
    }
  } catch (error) {
    const syncPromises = localProductIds.map((id) =>
      storeRecentlyViewedProduct(id, token, locale)
    );
    await Promise.allSettled(syncPromises);
  }
});

export const fetchRecentlyViewedProductsThunk = createAsyncThunk<
  string[],
  { token: string | null; limit?: number; productIds?: string[]; locale: string }
>("recentlyViewed/fetchProducts", async ({ token, limit = 20, productIds, locale }) => {
  try {
    const products = await getRecentlyViewedProductsList(
      token,
      locale,
      limit,
      productIds
    );
    return products.map((p : any) => p.productId);
  } catch (error) {
    return [];
  }
});

const recentlyViewedSlice = createSlice({
  name: "recentlyViewed",
  initialState: updatedInitialState,
  reducers: {
    clearRecentlyViewed: (state) => {
      state.productIds = [];
      localStorage.removeItem("recentlyViewedProductIds");
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchRecentlyViewedProductsThunk.fulfilled, (state, action) => {
        if (action.payload.length > 0) {
          if (!state.productIds || state.productIds.length === 0) {
            state.productIds = action.payload;
            saveToStorage(state.productIds);
            return;
          }

          const localProductIds = [...state.productIds];
          const serverProductIds = action.payload;
          const localOrderedIds = localProductIds.filter(id => serverProductIds.includes(id));
          const newServerIds = serverProductIds.filter(id => !localProductIds.includes(id));
          
          state.productIds = [...localOrderedIds, ...newServerIds];
          saveToStorage(state.productIds);
        }
      })
      .addCase(addToRecentlyViewedThunk.fulfilled, (state, action) => {
        updateProductIds(state, action.payload);
      })
      .addMatcher(
        (action) => action.type === "auth/logout",
        (state) => {
          localStorage.removeItem("recentlyViewedProductIds");
          state.productIds = [];
        }
      )
      .addMatcher(
        (action) => action.type === "auth/login" || action.type === "auth/register",
        (state) => {
          const localData = loadFromStorage();
          if (localData.length > 0 && (!state.productIds || state.productIds.length === 0)) {
            state.productIds = localData;
          }
        }
      );
  },
});

export const selectRecentlyViewedProductIds = (state: {
  recentlyViewed: RecentlyViewedState;
}) => state.recentlyViewed?.productIds || [];

export const { clearRecentlyViewed } = recentlyViewedSlice.actions;
export default recentlyViewedSlice.reducer;
