import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "redux/store";
import { CartItem } from "utils/types/appTypes";

interface LocationData {
  lat: number;
  lng: number;
  address: string;
}

export interface RoomDetailsType {
  roomNo: string;
  floorNo: string;
  guestName: string;
  note: string;
}

export interface OfficeDetailsType {
  officeNo: string;
  floorNo: string;
  note: string;
  company: string;
  contactPerson: string;
  phone: string;
}

export interface GiftDetailsType {
  receiverName: string;
  receiverPhone: string;
  message: string;
  senderName: string;
  senderPhone: string;
  isSecret: boolean;
}

interface CartState {
  items: CartItem[];
  tmp: unknown;
  specialRequest: string;
  location: LocationData | null;
  roomDetails: RoomDetailsType | null;
  officeDetails: OfficeDetailsType | null;
  giftDetails: GiftDetailsType | null;
  coupon: string;
  tip: string;
  tables: string[];
  estimateTime: Date;
  estimateTimeDate: Date;
  estimateTimeTime: string;
  collectionMethod: string;
}

// localStorage keys
const CART_STORAGE_KEYS = {
  ITEMS: 'fascano_cart_items',
  SPECIAL_REQUEST: 'fascano_special_request',
  COUPON: 'fascano_coupon',
  TIP: 'fascano_tip',
  TABLES: 'fascano_tables',
  LOCATION: 'fascano_location',
  ROOM_DETAILS: 'fascano_room_details',
  OFFICE_DETAILS: 'fascano_office_details',
  GIFT_DETAILS: 'fascano_gift_details',
  ESTIMATE_TIME: 'fascano_estimate_time',
  ESTIMATE_TIME_DATE: 'fascano_estimate_time_date',
  ESTIMATE_TIME_TIME: 'fascano_estimate_time_time',
  COLLECTION_METHOD: 'fascano_collection_method',
} as const;

// Utility functions for localStorage
const getFromLocalStorage = <T>(key: string, defaultValue: T): T => {
  if (typeof window === 'undefined') return defaultValue;
  
  try {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : defaultValue;
  } catch (error) {
    console.warn(`Error reading ${key} from localStorage:`, error);
    return defaultValue;
  }
};

const initialState: CartState = {
  items: getFromLocalStorage(CART_STORAGE_KEYS.ITEMS, []),
  tmp: null,
  specialRequest: getFromLocalStorage(CART_STORAGE_KEYS.SPECIAL_REQUEST, ""),
  location: getFromLocalStorage(CART_STORAGE_KEYS.LOCATION, null),
  roomDetails: getFromLocalStorage(CART_STORAGE_KEYS.ROOM_DETAILS, null),
  officeDetails: getFromLocalStorage(CART_STORAGE_KEYS.OFFICE_DETAILS, null),
  giftDetails: getFromLocalStorage(CART_STORAGE_KEYS.GIFT_DETAILS, null),
  coupon: getFromLocalStorage(CART_STORAGE_KEYS.COUPON, ""),
  tip: getFromLocalStorage(CART_STORAGE_KEYS.TIP, ""),
  tables: getFromLocalStorage(CART_STORAGE_KEYS.TABLES, []),
  estimateTime: new Date(getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME, new Date().toISOString())),
  estimateTimeDate: new Date(getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_DATE, new Date().toISOString())),
  estimateTimeTime: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, ""),
  collectionMethod: getFromLocalStorage(CART_STORAGE_KEYS.COLLECTION_METHOD, ""),
};

const orderSlice = createSlice({
  name: "order",
  initialState,
  reducers: {
    reset() {
      return initialState;
    },
    addItem(state, action: PayloadAction<{ item: Omit<CartItem, "quantity">; quantity: number }>) {
      const { item, quantity } = action.payload;
      const existingItem = state.items.find((i) => i.id === item.id);

      if (existingItem) {
        state.items = state.items.map((i) =>
          i.id === item.id ? { ...i, quantity: i.quantity + quantity } : i
        );
      } else {
        state.items = [...state.items, { ...item, quantity }];
      }
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.ITEMS, JSON.stringify(state.items));
      }
    },
    updateQuantity(state, action: PayloadAction<{ id: number | string; quantity: number }>) {
      const { id, quantity } = action.payload;
      state.items = state.items.map((item) =>
        item.id === id ? { ...item, quantity } : item
      );
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.ITEMS, JSON.stringify(state.items));
      }
    },
    removeItem(state, action: PayloadAction<number | string>) {
      state.items = state.items.filter((item) => item.id !== action.payload);
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.ITEMS, JSON.stringify(state.items));
      }
    },
    clearCart(state) {
      state.items = [];
      state.specialRequest = "";
      state.coupon = "";
      state.tip = "";
      state.tables = [];
      state.location = null;
      state.roomDetails = null;
      state.officeDetails = null;
      state.giftDetails = null;
      state.estimateTime = new Date();
      state.estimateTimeDate = new Date();
      state.estimateTimeTime = "";
      state.collectionMethod = "";
      
      // Clear all cart data from localStorage
      if (typeof window !== 'undefined') {
        Object.values(CART_STORAGE_KEYS).forEach(key => {
          localStorage.removeItem(key);
        });
      }
    },
    updateSpecialRequest(state, action: PayloadAction<string>) {
      state.specialRequest = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.SPECIAL_REQUEST, JSON.stringify(state.specialRequest));
      }
    },
    clearSpecialRequest(state) {
      state.specialRequest = "";
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.removeItem(CART_STORAGE_KEYS.SPECIAL_REQUEST);
      }
    },
    updateCoupon(state, action: PayloadAction<string>) {
      state.coupon = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.COUPON, JSON.stringify(state.coupon));
      }
    },
    updateTip(state, action: PayloadAction<string>) {
      state.tip = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.TIP, JSON.stringify(state.tip));
      }
    },
    updateTables(state, action: PayloadAction<string[]>) {
      state.tables = [...state.tables, ...action.payload];
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.TABLES, JSON.stringify(state.tables));
      }
    },
    removeTable(state) {
      state.tables = [];
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.removeItem(CART_STORAGE_KEYS.TABLES);
      }
    },
    setTmp(state, action: PayloadAction<unknown>) {
      state.tmp = action.payload;
    },
    updateLocation(state, action: PayloadAction<LocationData | null>) {
      state.location = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.LOCATION, JSON.stringify(state.location));
      }
    },
    clearLocation(state) {
      state.location = null;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.removeItem(CART_STORAGE_KEYS.LOCATION);
      }
    },
    updateRoomDetails(state, action: PayloadAction<RoomDetailsType | null>) {
      state.roomDetails = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.ROOM_DETAILS, JSON.stringify(state.roomDetails));
      }
    },
    updateOfficeDetails(state, action: PayloadAction<OfficeDetailsType | null>) {
      state.officeDetails = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.OFFICE_DETAILS, JSON.stringify(state.officeDetails));
      }
    },
    updateGiftDetails(state, action: PayloadAction<GiftDetailsType | null>) {
      state.giftDetails = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.GIFT_DETAILS, JSON.stringify(state.giftDetails));
      }
    },
    updateEstimateTime(state, action: PayloadAction<{ date: Date; time: string }>) {
      state.estimateTime = action.payload.date;
      state.estimateTimeDate = action.payload.date;
      state.estimateTimeTime = action.payload.time;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_TIME, JSON.stringify(state.estimateTime.toISOString()));
        localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_TIME_DATE, JSON.stringify(state.estimateTimeDate.toISOString()));
        localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, JSON.stringify(state.estimateTimeTime));
      }
    },
    updateCollectionMethod(state, action: PayloadAction<string>) {
      state.collectionMethod = action.payload;
      
      // Sync to localStorage
      if (typeof window !== 'undefined') {
        localStorage.setItem(CART_STORAGE_KEYS.COLLECTION_METHOD, JSON.stringify(state.collectionMethod));
      }
    },
  },
});

export const {
  addItem,
  updateQuantity,
  removeItem,
  clearCart,
  updateSpecialRequest,
  clearSpecialRequest,
  updateCoupon,
  updateTip,
  updateTables,
  removeTable,
  setTmp,
  updateLocation,
  clearLocation,
  updateRoomDetails,
  updateOfficeDetails,
  updateGiftDetails,
  updateEstimateTime,
  updateCollectionMethod,
  reset,
} = orderSlice.actions;

// Selectors
export const selectCart = (state: RootState) => state.order;
export const selectCartItems = (state: RootState) => state.order.items;
export const selectCartTotal = (state: RootState) => 
  state.order.items.reduce((total, item) => total + item.price * item.quantity, 0);
export const selectCartItemsQuantity = (id: number | string) => (state: RootState) => {
  const item = state.order.items.find((i) => i.id === id);
  return item ? item.quantity : 0;
};

export default orderSlice.reducer;
