// type PayloadAction<T> = {
//   type: string;
//   payload: T;
// }
import axios from "axios";
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { STORAGE_KEYS, MESSAGES, BASE_URL } from "../constants/config";
import { AUTH_STATUSES, StatusType } from "../constants/types";

interface AuthState {
  phone: string | null;
  otpId: number | null;
  isLoggedIn: boolean;
  status: StatusType;
  sendOTPError: string | null;
  verifyOTPError: string | null;
  generalError: string | null;
}

interface SendOTPResponse {
  success: boolean;
  message: string;
  data: {
    otpId: number;
    phone: string;
  };
}

interface VerifyOTPResponse {
  success: boolean;
  message: string;
  data: {
    success: boolean;
    message: string;
    token: string;
    token_expires_in: string;
  };
}

interface SendOTPParams {
  phone: string | null;
}

interface VerifyOTPParams {
  phone: string | null;
  otp: string | null;
  otpId: string | null;
}

const initialState: AuthState = {
  phone: null,
  otpId: null,
  isLoggedIn: false,
  status: AUTH_STATUSES.IDLE,
  sendOTPError: null,
  verifyOTPError: null,
  generalError: null,
};

//async thunk to send otp
export const sendOTP = createAsyncThunk<SendOTPResponse, SendOTPParams>(
  "auth/sendOTP",
  async (params, { rejectWithValue }) => {
    try {
      const response = await axios.post<SendOTPResponse>(
        `${BASE_URL}/api/v1/send-otp`,
        params
      );
      return response.data;
      // if (!response.data.status) throw new Error(response.data.message);
    } catch (error: any) {
      const serverMessage = error.response?.data?.message;
      return rejectWithValue(serverMessage || "Something went wrong");
    }
  }
);

export const verifyOTP = createAsyncThunk<VerifyOTPResponse, VerifyOTPParams>(
  "auth/verifyOTP",
  async (params, { rejectWithValue }) => {
    try {
      console.log("params", params);
      const response = await axios.post<VerifyOTPResponse>(
        `${BASE_URL}/api/v1/verify-otp`,
        params
      );
      if (!response.data.success) throw new Error(response.data.message);

      // Store tokens
      await AsyncStorage.setItem(
        STORAGE_KEYS.AUTH_TOKEN,
        response.data.data.token
      );

      return response.data;
    } catch (error: any) {
      console.log(error.message);
      return rejectWithValue(MESSAGES.AUTHENTICATION.VERIFICATION_FAILED);
    }
  }
);

export const logout = createAsyncThunk(
  "auth/logout",
  async (_, { dispatch }) => {
    await AsyncStorage.removeItem(STORAGE_KEYS.AUTH_TOKEN);
    dispatch(authSlice.actions.logout());
  }
);

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    loginRequest: (state) => {
      state.status = AUTH_STATUSES.LOADING;
    },
    loginSuccess: (state, action) => {
      state.status = AUTH_STATUSES.SUCCESS;
      state.isLoggedIn = true; // Set logged-in state to true
    },
    setIsLoggedIn: (state, action) => {
      state.isLoggedIn = action.payload;
    },
    loginFailure: (state, action: PayloadAction<string>) => {
      state.status = AUTH_STATUSES.FAILED;
      state.generalError = action.payload;
    },
    logout: (state) => {
      state.isLoggedIn = false;
    },
    clearSendOTPError: (state) => {
      state.sendOTPError = null;
    },
    clearVerifyOTPError: (state) => {
      state.verifyOTPError = null;
    },
    clearAllErrors: (state) => {
      state.sendOTPError = null;
      state.verifyOTPError = null;
      state.generalError = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(sendOTP.pending, (state) => {
        state.status = AUTH_STATUSES.LOADING;
        state.sendOTPError = null;
      })
      .addCase(sendOTP.fulfilled, (state, action) => {
        state.status = AUTH_STATUSES.SUCCESS;
        state.otpId = action.payload.data.otpId;
        state.phone = action.payload.data.phone;
        state.sendOTPError = null;
      })
      .addCase(sendOTP.rejected, (state, action) => {
        state.status = AUTH_STATUSES.FAILED;
        state.sendOTPError = (action.payload as string) || "Failed to send OTP";
      })
      .addCase(verifyOTP.pending, (state) => {
        state.status = AUTH_STATUSES.LOADING;
        state.verifyOTPError = null;
      })
      .addCase(verifyOTP.fulfilled, (state, action) => {
        state.status = AUTH_STATUSES.SUCCESS;
        state.isLoggedIn = true;
        state.verifyOTPError = null;
        const token = action.payload.data.token;
        AsyncStorage.setItem(STORAGE_KEYS.AUTH_TOKEN, token).catch((error) => {
          console.log("Error storing token", error);
        });
      })
      .addCase(verifyOTP.rejected, (state, action) => {
        state.status = AUTH_STATUSES.FAILED;
        state.verifyOTPError = action.error.message || "Failed to verify OTP";
      })
      .addCase(logout.pending, (state) => {
        state.status = AUTH_STATUSES.LOADING;
      })
      .addCase(logout.fulfilled, (state) => {
        state.otpId = null;
        state.isLoggedIn = false;
        state.status = AUTH_STATUSES.IDLE;
        state.verifyOTPError = null;
        state.generalError = null;
        state.sendOTPError = null;
        state.phone = null;
      })
      .addCase(logout.rejected, (state, action) => {
        state.status = AUTH_STATUSES.FAILED;
        state.generalError = action.error.message || "Failed to log out";
      });
  },
});

export const {
  logout: localLogout,
  clearSendOTPError,
  clearVerifyOTPError,
  clearAllErrors,
} = authSlice.actions;

export default authSlice.reducer;
