import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import { authService } from "@/features/auth/services/auth.service";
import { persistAuth } from "@/lib/utils/persistAuth";
import type {
  AuthUser,
  LoginPayload,
  RegisterPayload,
} from "@/types/api/auth.types";

interface AuthState {
  user: AuthUser | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  error: string | null;
}

const initialState: AuthState = {
  user: null,
  isAuthenticated: false,
  isLoading: false,
  error: null,
};

function extractErrorMessage(err: unknown, fallback: string): string {
  const errMsg = (err as Error)?.message;
  const httpMsg = (err as { response?: { data?: { message?: string } } })
    ?.response?.data?.message;
  return httpMsg ?? errMsg ?? fallback;
}

export const loginWithOTP = createAsyncThunk(
  "auth/loginWithOTP",
  async (payload: LoginPayload, { rejectWithValue }) => {
    try {
      const data = await authService.login(payload);
      const user = data.result[0];
      persistAuth(user);
      return user;
    } catch (err) {
      return rejectWithValue(
        extractErrorMessage(err, "OTP login failed. Please try again."),
      );
    }
  },
);

export const loginWithEmail = createAsyncThunk(
  "auth/loginWithEmail",
  async (payload: LoginPayload, { rejectWithValue }) => {
    try {
      const data = await authService.login(payload);
      const user = data.result[0];
      persistAuth(user);
      return user;
    } catch (err) {
      return rejectWithValue(
        extractErrorMessage(err, "Login failed. Please try again."),
      );
    }
  },
);

export const registerUser = createAsyncThunk(
  "auth/register",
  async (payload: RegisterPayload, { rejectWithValue }) => {
    try {
      await authService.register(payload);
      // Auto-login after successful registration
      const loginData = await authService.login({
        type: 4,
        email: payload.email,
        password: payload.password,
        full_name: payload.full_name,
        image: "",
        country_code: payload.country_code,
        mobile_number: payload.mobile_number,
        country_name: payload.country_name,
        device_type: 3,
        device_token: payload.device_token,
      });
      const user = loginData.result[0];
      persistAuth(user);
      return user;
    } catch (err) {
      return rejectWithValue(
        extractErrorMessage(err, "Registration failed. Please try again."),
      );
    }
  },
);

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    clearError: (state) => {
      state.error = null;
    },
    logout: (state) => {
      state.user = null;
      state.isAuthenticated = false;
    },
    setUser: (state, action: PayloadAction<AuthUser>) => {
      state.user = action.payload;
      state.isAuthenticated = true;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(loginWithEmail.pending, (state) => {
        state.isLoading = true;
        state.error = null;
      })
      .addCase(loginWithEmail.fulfilled, (state, action) => {
        state.isLoading = false;
        state.user = action.payload;
        state.isAuthenticated = true;
      })
      .addCase(loginWithEmail.rejected, (state, action) => {
        state.isLoading = false;
        state.error = (action.payload as string) ?? "Something went wrong.";
      })
      .addCase(registerUser.pending, (state) => {
        state.isLoading = true;
        state.error = null;
      })
      .addCase(registerUser.fulfilled, (state, action) => {
        state.isLoading = false;
        state.user = action.payload;
        state.isAuthenticated = true;
      })
      .addCase(registerUser.rejected, (state, action) => {
        state.isLoading = false;
        state.error = (action.payload as string) ?? "Something went wrong.";
      })
      .addCase(loginWithOTP.pending, (state) => {
        state.isLoading = true;
        state.error = null;
      })
      .addCase(loginWithOTP.fulfilled, (state, action) => {
        state.isLoading = false;
        state.user = action.payload;
        state.isAuthenticated = true;
      })
      .addCase(loginWithOTP.rejected, (state, action) => {
        state.isLoading = false;
        state.error = (action.payload as string) ?? "Something went wrong.";
      });
  },
});

export const { clearError, logout, setUser } = authSlice.actions;
export default authSlice.reducer;
