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;
  senderEmail: string;
  isSecret: boolean;
}

interface CartState {
  items: CartItem[];
  tmp: any;
  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;
  phone: string;
  paymentMethod: string;
  orderType: string;
  useLoyaltyPoints: boolean;
  loyaltyValidationError: string | null;
}

// localStorage keys
export 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",
  PHONE: "fascano_phone",
  PAYMENT_METHOD: "fascano_payment_method",
  ORDER_TYPE: "fascano_order_type",
  USE_LOYALTY_POINTS: "fascano_use_loyalty_points",
  LOYALTY_VALIDATION_ERROR: "fascano_loyalty_validation_error",
} 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,
    "",
  ),
  phone: getFromLocalStorage(CART_STORAGE_KEYS.PHONE, ""),
  paymentMethod: getFromLocalStorage(CART_STORAGE_KEYS.PAYMENT_METHOD, ""),
  orderType: getFromLocalStorage(CART_STORAGE_KEYS.ORDER_TYPE, ""),
  useLoyaltyPoints: getFromLocalStorage(
    CART_STORAGE_KEYS.USE_LOYALTY_POINTS,
    false,
  ),
  loyaltyValidationError: getFromLocalStorage(
    CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR,
    null,
  ),
};

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 }];
      }

      // Validate loyalty points if enabled
      if (state.useLoyaltyPoints) {
        const loyaltyItems = state.items.filter((item) => item.isHasLoyalty);
        if (loyaltyItems.length === 0) {
          state.loyaltyValidationError = "cart.noLoyaltyItemsInCart";
        } else {
          state.loyaltyValidationError = null;
        }
      }

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.ITEMS,
          JSON.stringify(state.items),
        );
        localStorage.setItem(
          CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR,
          JSON.stringify(state.loyaltyValidationError),
        );
      }
    },
    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);

      // Validate loyalty points if enabled
      if (state.useLoyaltyPoints) {
        const loyaltyItems = state.items.filter((item) => item.isHasLoyalty);
        if (loyaltyItems.length === 0) {
          state.loyaltyValidationError = "cart.noLoyaltyItemsInCart";
        } else {
          state.loyaltyValidationError = null;
        }
      }

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.ITEMS,
          JSON.stringify(state.items),
        );
        localStorage.setItem(
          CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR,
          JSON.stringify(state.loyaltyValidationError),
        );
      }
    },
    clearCart(state) {
      state.items = [];
      state.specialRequest = "";
      state.phone = "";
      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 = "";
      state.paymentMethod = "";
      state.loyaltyValidationError = null;
      // Clear all cart data from localStorage
      if (typeof window !== "undefined") {
        Object.values(CART_STORAGE_KEYS)
          .filter((key) => key !== CART_STORAGE_KEYS.ORDER_TYPE)
          .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 = 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),
        );
      }
    },
    updatePhone(state, action: PayloadAction<string>) {
      state.phone = action.payload;

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.PHONE,
          JSON.stringify(state.phone),
        );
      }
    },
    updatePaymentMethod(state, action: PayloadAction<string>) {
      state.paymentMethod = action.payload;

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.PAYMENT_METHOD,
          JSON.stringify(state.paymentMethod),
        );
      }
    },
    updateOrderType(state, action: PayloadAction<string>) {
      state.orderType = action.payload;

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.ORDER_TYPE,
          JSON.stringify(state.orderType),
        );
      }
    },
    updateUseLoyaltyPoints(state, action: PayloadAction<boolean>) {
      state.useLoyaltyPoints = action.payload;

      // Validate loyalty points usage
      if (action.payload) {
        const loyaltyItems = state.items.filter((item) => item.isHasLoyalty);
        if (loyaltyItems.length === 0) {
          state.loyaltyValidationError = "cart.noLoyaltyItemsInCart";
        } else {
          state.loyaltyValidationError = null;
        }
      } else {
        state.loyaltyValidationError = null;
      }

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.USE_LOYALTY_POINTS,
          JSON.stringify(state.useLoyaltyPoints),
        );
        localStorage.setItem(
          CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR,
          JSON.stringify(state.loyaltyValidationError),
        );
      }
    },
    validateLoyaltyPoints(state) {
      if (state.useLoyaltyPoints) {
        const loyaltyItems = state.items.filter((item) => item.isHasLoyalty);
        if (loyaltyItems.length === 0) {
          state.loyaltyValidationError = "cart.noLoyaltyItemsInCart";
        } else {
          state.loyaltyValidationError = null;
        }
      } else {
        state.loyaltyValidationError = null;
      }

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR,
          JSON.stringify(state.loyaltyValidationError),
        );
      }
    },
    clearLoyaltyValidationError(state) {
      state.loyaltyValidationError = null;

      // Sync to localStorage
      if (typeof window !== "undefined") {
        localStorage.setItem(
          CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR,
          JSON.stringify(state.loyaltyValidationError),
        );
      }
    },
  },
});

export const {
  addItem,
  updateQuantity,
  removeItem,
  clearCart,
  updateSpecialRequest,
  clearSpecialRequest,
  updateCoupon,
  updateTip,
  updateTables,
  removeTable,
  setTmp,
  updateLocation,
  clearLocation,
  updateRoomDetails,
  updateOfficeDetails,
  updateGiftDetails,
  updateEstimateTime,
  updateCollectionMethod,
  updatePhone,
  updatePaymentMethod,
  updateOrderType,
  updateUseLoyaltyPoints,
  validateLoyaltyPoints,
  clearLoyaltyValidationError,
  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;
  };

// Loyalty selectors
export const selectLoyaltyItems = (state: RootState) =>
  state.order.items.filter((item) => item.isHasLoyalty);

export const selectHighestPricedLoyaltyItem = (state: RootState) => {
  const loyaltyItems = selectLoyaltyItems(state);
  if (loyaltyItems.length === 0) return null;

  return loyaltyItems.reduce((highest, current) =>
    current.price > highest.price ? current : highest,
  );
};

export const selectCartTotalWithLoyaltyDiscount = (state: RootState) => {
  const total = selectCartTotal(state);
  const useLoyaltyPoints = state.order.useLoyaltyPoints;
  const highestLoyaltyItem = selectHighestPricedLoyaltyItem(state);

  if (useLoyaltyPoints && highestLoyaltyItem) {
    return total - highestLoyaltyItem.price;
  }

  return total;
};

export const selectLoyaltyValidation = (state: RootState) => {
  const useLoyaltyPoints = state.order.useLoyaltyPoints;
  const loyaltyItems = selectLoyaltyItems(state);

  return {
    canUseLoyaltyPoints: loyaltyItems.length > 0,
    hasLoyaltyItems: loyaltyItems.length > 0,
    loyaltyItemsCount: loyaltyItems.length,
    errorMessage:
      useLoyaltyPoints && loyaltyItems.length === 0
        ? "cart.noLoyaltyItemsInCart"
        : null,
  };
};

export default orderSlice.reducer;
