import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import Cookies from 'js-cookie';
import axiosInstance from '@/services/axiosClient';
import { closeAuthModal } from './auth';
import { RootState } from './store';
import toast from 'react-hot-toast';
import { getAllCartItems } from './cart';
import { getAllFavItems } from './fav';
import { setLocation } from './locationSlice';
import { showDynamicSwal } from '@/utils/helpers';
import Alert from "@/assets/images/alert.svg";
import dayjs from 'dayjs';
import 'dayjs/locale/ar';

dayjs.locale('ar');
// Define authentication state interface
interface AuthState {
  user: any;
  id: string | null;
  user_type: string | null;
  token: string | null;
  full_name: string | null;
  email: string | null;
  avatar: string | null;
  phone: string | null;
  phone_code: string | null;
  locale: string | null;
  gender: string | null;
  is_allow_notification: any;
  isLoading: boolean;
  image: any | null;
  is_verify: any;
  birthday: string | null;
  commercial_registration_number_file :any|null;
  commercial_registration_number:string|null;
  wallet:any|null;
  balance:string|null;
  wallet_balance?:string|null;
  my_subscriptions?:any|null;
  categories?:any|null;
}

const initialState: AuthState = {
  id: null,
  user: {},
  user_type:Cookies.get("user_type") || "guest",
  token: Cookies.get("user_token") || null,
  full_name: null,
  email: null,
  avatar: null,
  phone: "",
  phone_code: "",
  locale: null,
  gender: null,
  isLoading: false,
  is_allow_notification: false,
  image: null,
  is_verify:Cookies.get("is_verify") || false,
  birthday:null,
  commercial_registration_number_file:null,
  commercial_registration_number:null,
  my_subscriptions:true,
  wallet:null,
  balance:null,
  categories:null
};

// Async thunk for login
export const authLogin = createAsyncThunk(
  'auth/authLogin', 
  async ({ values,getStep,t }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/login', { ...values });
      if (data) {
        if(data?.data.is_verify){
          dispatch(setAuthedUserData(data?.data));
          dispatch(setLocation({
            lat:data?.data?.default_location?.lat,
            lng:data?.data?.default_location?.lng,
            location_description:data?.data?.default_location?.location,
            id:data?.data?.default_location?.id,
          }))
          dispatch(closeAuthModal());
          return{
            data  :data?.data,
            status: 200
          }
        }else{
            const confirm =  await showDynamicSwal({
              title: t("Messages.not_verified"),
              imageUrl: `${Alert.src}`,
              text: t("Messages.not_verified_desc"),
              confirmButtonText: t("buttons.ok"),
              cancelButtonText: t("buttons.noKeepMe"),
              customClass: {
                title: "swal-title",
                confirmButton:"app-btn",
                cancelButton:"app-btn outline-btn"
              },
            });
            if(confirm.isConfirmed){
              Cookies.set("userPhone", JSON.stringify({ phone_code: values.phone_code, phone: values.phone }));
              Cookies.set("user_token", data?.data?.token);
              dispatch(ResendCode({values,getStep}))
            }else if(confirm.isDismissed || confirm.isDenied){
              dispatch(closeAuthModal());
            }
        }
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error.message);
    }
  }
);

// Async thunk for registration
export const authRegister = createAsyncThunk(
  'auth/authRegister', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue , getState }) => {
    try {
      const state = getState() as RootState
      values = {
        ...values,
        lat:state?.locationConfig.lat,
        lng:state?.locationConfig.lng,
        location:state?.locationConfig.location_description,
      }
      const { data } = await axiosInstance.post('/register', { ...values });
      if (data) {
        // Save user data in cookies
        const userData = data?.data;
        // Dispatch the user data to the Redux store
        dispatch(setAuthedUserData(userData));
        // Save user data in cookies
        Cookies.set("userPhone", JSON.stringify({ phone_code: values.phone_code, phone: values.phone }));
        Cookies.set("user_token", userData?.token);
        toast.success(data?.message);
        getStep(3);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for OTP verification
export const authVerifyOtp = createAsyncThunk(
  'auth/authVerifyOtp', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/verify', { ...values });
      if (data) {
        toast.success(data?.message);
        getStep(8);
        // Dispatch the user data to the Redux store
        dispatch(setAuthedUserData(data?.data));
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for edit phone
export const authEditPhone = createAsyncThunk(
  'auth/authEditPhone', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/profile/edit-phone', { ...values });
      if (data) {
        toast.success(data?.message);
        Cookies.set("userPhone", JSON.stringify({ phone_code: values.phone_code, phone: values.phone }));
        getStep(10);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for edit phone
export const authVerifyEditPhone = createAsyncThunk(
  'auth/authVerifyEditPhone', 
  async ({ values, handleClose }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/profile/update-phone', { ...values });
      if (data) {
        toast.success(data?.message);

        handleClose();
        return {
          phone_code:values?.phone_code,
          phone:values?.phone
        }
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for edit phone
export const authChangePassword = createAsyncThunk(
  'auth/authChangePassword', 
  async ({ values, handleClose }: any, { rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.patch('/profile/update-password', { ...values });
      if (data) {
        toast.success(data?.message);
        handleClose();
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for logout
export const logout = createAsyncThunk(
  'auth/logout',
  async ({router}:{router:any}, { dispatch, rejectWithValue }) => {
    try {
      const {data} = await axiosInstance.post('/logout');
      if (data) {
        dispatch(deleteAuthedUserData());
        dispatch(getAllCartItems());
        dispatch(getAllFavItems());
        router.replace("/");
        setTimeout(() => {
          router.refresh()
        }, 0);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error.message);
    }
  }
);

// Async thunk for logout
export const deleteAcc = createAsyncThunk(
  'auth/deleteAcc',
  async ({router}:{router:any}, { dispatch, rejectWithValue }) => {
    try {
      const {data} = await axiosInstance.delete('/profile');
      if (data) {
        dispatch(deleteAuthedUserData());
        toast.success(data?.message);
        dispatch(getAllCartItems());
        dispatch(getAllFavItems());
        router.replace("/");
        setTimeout(() => {
          router.refresh()
        }, 0);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error.message);
    }
  }
);

// Async thunk for OTP verification
export const authRestSendOtp = createAsyncThunk(
  'auth/authRestSendOtp', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/send', { ...values });
      if (data?.status == "success") {
        toast.success(data?.message);
        Cookies.set("userPhone", JSON.stringify({ phone_code: values.phone_code, phone: values.phone }));
        getStep(5);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for edit phone for non user
export const editPhoneGuest = createAsyncThunk(
  'auth/editPhoneGuest', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/edit-phone', { ...values });
      if (data?.status == "success") {
        toast.success(data?.message);
        Cookies.set("userPhone", JSON.stringify({ phone_code: values.phone_code, phone: values.phone }));
        getStep(3);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk for OTP verification
export const authVerifyRestOtp = createAsyncThunk(
  'auth/authVerifyRestOtp', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/check-code', { ...values });
      if (data) {
        toast.success(data?.message);
        Cookies.set("otp_code", values.code);
        getStep(6);
        // Dispatch the user data to the Redux store
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);


// Async resend code for OTP verification
export const ResendCode = createAsyncThunk(
  'auth/ResendCode', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/send', { ...values });
      if (data?.status == "success") {
        toast.success(data?.message);
        getStep(3);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

export const authRestPassword = createAsyncThunk(
  'auth/authRestPassword', 
  async ({ values, getStep }: any, { dispatch, rejectWithValue }) => {
    try {
      const { data } = await axiosInstance.post('/reset-password', { ...values });
      if (data) {
        toast.success(data?.message);
        Cookies.remove("otp_code")
        getStep(0);
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);


export const authUpdateProfile = createAsyncThunk(
  'auth/authUpdateProfile', 
  async ({ values }: any, { dispatch, rejectWithValue,getState }) => {
    try {
      const state = getState() as RootState;
      
      console.log("🚀 ~ values:",state.ProfileConfig.image?.id && state.ProfileConfig.image?.id == values.image?.id)
      delete values.password;
      delete values.phone;

      if(
        state.ProfileConfig.commercial_registration_number_file && 
        state.ProfileConfig.commercial_registration_number_file.id == values.commercial_registration_number_file.id
      ){
        values.commercial_registration_number_file = values.commercial_registration_number_file.url
      }

      if(state.ProfileConfig.image?.id && state.ProfileConfig.image?.id == values.image?.id){
          delete values.image
      }

      values.birthday = dayjs(values.birthday,'YYYY MMMM D').format('YYYY-MM-DD');


      const { data } = await axiosInstance.post('/profile/update', { ...values,_method:"PUT" });
      if (data) {
        toast.success(data?.message);

        dispatch(setAuthedUserData(data?.data));
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk to fetch authenticated user data
export const getAuthedUserData = createAsyncThunk(
  'auth/getAuthedUserData',
  async (_, { dispatch, rejectWithValue }) => {
    try {
      const {data} = await axiosInstance.get('/profile');
      if (data) {
        dispatch(setLocation({
          lat:data?.data?.default_location?.lat,
          lng:data?.data?.default_location?.lng,
          location_description:data?.data?.default_location?.location,
          id:data?.data?.default_location?.id,
        }))
        dispatch(setAuthedUserData(data?.data));
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

// Async thunk to fetch authenticated user data
export const getWallet = createAsyncThunk(
  'auth/getWallet',
  async (_, { dispatch, rejectWithValue }) => {
    try {
      const {data} = await axiosInstance.get('/wallet');
      if (data) {
        return data?.data
      }
    } catch (error: any) {
      toast.error(error?.response?.data?.message);
      return rejectWithValue(error?.response?.data?.message);
    }
  }
);

const profileSlice = createSlice({
  name: 'profile',
  initialState,
  reducers: {
    setAuthedUserData: (state, action: PayloadAction<Partial<AuthState>>) => {
      const { token, user_type,is_verify, ...userData } = action.payload;      
      state.user = userData;
      state.balance = action.payload.wallet_balance || null;
      Object.assign(state, action.payload);
      
      // Set cookies with user data
      if(token){
        Cookies.set('user_token', token , { expires: 30 });
      }
      Cookies.set('user_type', user_type || '', { expires: 30 });
      Cookies.set('user_verify', is_verify || false, { expires: 30 });
      Cookies.set('user_data', JSON.stringify(action.payload), { expires: 30 });
    
    },
    deleteAuthedUserData: (state) => {
      Object.assign(state, initialState);
      Cookies.remove('user_token');
      Cookies.remove('client_location');
      Cookies.remove('user_type');
      Cookies.remove('userPhone');
      Cookies.remove('user_verify');
      Cookies.remove('user_data');
    },
    resetState: (state) => {
      Object.assign(state, initialState);
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(authLogin.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authLogin.fulfilled, (state, action) => {
        state.isLoading = false;
        if(action.payload?.status == 200){
          Object.assign(state, action.payload);
        }
      })
      .addCase(authLogin.rejected, (state) => {
        state.isLoading = false;
      })
      .addCase(authRegister.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authRegister.fulfilled, (state, action) => {
        state.isLoading = false;
        Object.assign(state, action.payload);
      })
      .addCase(authRegister.rejected, (state) => {
        state.isLoading = false;
      })
      .addCase(authVerifyOtp.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authVerifyOtp.fulfilled, (state, action) => {
        state.isLoading = false;
        Object.assign(state, action.payload);
      })
      .addCase(authVerifyOtp.rejected, (state) => {
        state.isLoading = false;
      })
      // edit phone 
      .addCase(authVerifyEditPhone.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authVerifyEditPhone.fulfilled, (state, action) => {
        state.isLoading = false;
        state.phone_code = action.payload?.phone_code;
        state.phone = action.payload?.phone;
      })
      .addCase(authVerifyEditPhone.rejected, (state) => {
        state.isLoading = false;
      })
      // rest password 
      .addCase(authRestSendOtp.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authRestSendOtp.fulfilled, (state, action) => {
        state.isLoading = false;
      })
      .addCase(authRestSendOtp.rejected, (state) => {
        state.isLoading = false;
      }) 
      // rest password 
      .addCase(editPhoneGuest.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(editPhoneGuest.fulfilled, (state, action) => {
        state.isLoading = false;
      })
      .addCase(editPhoneGuest.rejected, (state) => {
        state.isLoading = false;
      }) 
      .addCase(authVerifyRestOtp.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authVerifyRestOtp.fulfilled, (state, action) => {
        state.isLoading = false;
      })
      .addCase(authVerifyRestOtp.rejected, (state) => {
        state.isLoading = false;
      }) 
      .addCase(authRestPassword.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authRestPassword.fulfilled, (state, action) => {
        state.isLoading = false;
      })
      .addCase(authRestPassword.rejected, (state) => {
        state.isLoading = false;
      }) 
      .addCase(getAuthedUserData.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(getAuthedUserData.fulfilled, (state, action) => {
        state.isLoading = false;
        Object.assign(state, action.payload);
      })
      .addCase(getAuthedUserData.rejected, (state) => {
        state.isLoading = false;
      })
      .addCase(getWallet.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(getWallet.fulfilled, (state, action) => {
        state.isLoading = false;
        state.wallet = action.payload;
        state.balance = action.payload.balance;
      })
      .addCase(getWallet.rejected, (state) => {
        state.isLoading = false;
      })
      .addCase(authUpdateProfile.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authUpdateProfile.fulfilled, (state) => {
        state.isLoading = false;
      })
      .addCase(authUpdateProfile.rejected, (state) => {
        state.isLoading = false;
      })
      .addCase(authChangePassword.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(authChangePassword.fulfilled, (state) => {
        state.isLoading = false;
      })
      .addCase(authChangePassword.rejected, (state) => {
        state.isLoading = false;
      })
      .addCase(logout.pending, (state) => {
        state.isLoading = false;
      })
      .addCase(logout.fulfilled, (state) => {
        state.isLoading = false;
      })
      .addCase(logout.rejected, (state) => {
        state.isLoading = false;
      });
  },
});

export const { setAuthedUserData, deleteAuthedUserData, resetState } = profileSlice.actions;
export default profileSlice.reducer;
