import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { isAxiosError } from "axios";
import { AUTH_TOKEN } from "../environments/environments";
import { axiosBuzzOne } from "../utils/axios";
import { TOKEN_NAME } from "../utils/constants";

export const buzzOneGetUserAsync = createAsyncThunk(`auth/me`, async () => {
	const response = await axiosBuzzOne({
		method: "GET",
		url: "auth/me",
		headers: {
			"x-user-type": "akademy",
			"Content-Type": "application/json",
			Authorization: AUTH_TOKEN(),
		},
	});

	return response.data;
});

export const buzzOneSignInAsync = createAsyncThunk(
	`auth/signin`,
	async (payload, { rejectWithValue }) => {
		try {
			const response = await axiosBuzzOne({
				method: "POST",
				url: "auth/identity/email-and-password/login",
				data: { ...payload },
			});

			return response.data;
		} catch (error) {
			return rejectWithValue(error.response.data);
		}
	}
);

export const buzzOneSignUpAsync = createAsyncThunk(
	`auth/signup`,
	async (payload, { rejectWithValue }) => {
		try {
			const response = await axiosBuzzOne({
				method: "POST",
				url: "auth/identity/email-and-password/signup",
				data: { ...payload },
				headers: { "x-user-type": "AKADEMY" },
			});

			const data = response.data;
			localStorage.setItem(TOKEN_NAME, `${data.token}`);
			localStorage.setItem("userId", data.id);
			return data;
		} catch (error) {
			return rejectWithValue(error.response.data);
		}
	}
);

export const buzzOneSendOtpAsync = createAsyncThunk(
	`auth/profile/verify/email/send`,
	async (payload, { rejectWithValue }) => {
		try {
			const response = await axiosBuzzOne({
				headers: {
					Authorization: payload.token ? `Bearer ${payload.token}` : AUTH_TOKEN(),
				},
				method: "POST",
				url: "profile/verify/email/send",
			});
			const data = response.data;
			return data;
		} catch (error) {
			return rejectWithValue(error.response.data);
		}
	}
);

export const buzzOneVerifyOtpAsync = createAsyncThunk(
	`auth/profile/verify/email/verify`,
	async (payload, { rejectWithValue }) => {
		const { token, ...data } = payload;
		try {
			const response = await axiosBuzzOne({
				headers: {
					Authorization: token ? `Bearer ${token}` : AUTH_TOKEN(),
				},
				method: "POST",
				url: "profile/verify/email/verify",
				data,
			});
			const data = response.data;
			return data;
		} catch (error) {
			return rejectWithValue(error.response.data);
		}
	}
);

export const emailResendOtpAsync = createAsyncThunk(
	`auth/emailResendOtp`,
	async (payload) => {
		const response = await axiosBuzzOne({
			headers: {
				Authorization: payload.token ? `Bearer ${payload.token}` : AUTH_TOKEN(),
			},
			method: "POST",
			url: "signup/resendOtpEmailVerification",
		});
		const data = response.data;
		return data;
	}
);

export const postVerificationSteps = createAsyncThunk(
	`postVerificationSteps`,
	async (_, { getState, dispatch }) => {
		const {
			auth: { user, userProfile },
			purchase: { userDetails, purchaseDetails },
		} = getState();

		let payload = { userId: user?._id, schoolId: userProfile?.schoolId };

		if (!user) {
			const user = await dispatch(createNewAkademyUser()).unwrap();
			payload.userId = user._id;
		}

		let schoolProducts = purchaseDetails.cartItems.filter(
			({ plan }) =>
				plan.productCategory === "TUTION_EDUCATOR" ||
				plan.productCategory === "ENTERPRISE_SCHOOL"
		);

		if (schoolProducts.length > 0 && !userProfile?.schoolId) {
			const school = await dispatch(
				createNewAkademySchool({ userName: userDetails.fullName })
			).unwrap();
			payload.schoolId = school._id;
		}

		return payload;
	}
);

export const createNewAkademyUser = createAsyncThunk(
	`akadmy/create/user`,
	async (payload, { getState }) => {
		const {
			purchase: { userDetails },
		} = getState();

		try {
			const response = await axiosBuzzOne({
				method: "POST",
				url: "/profile/akademy/user",
				data: {
					email: userDetails.email,
					name: userDetails.fullName,
					address: {
						city: userDetails.city,
						pincode: userDetails.pincode,
					},
				},
			});
			return response.data.data;
		} catch (err) {
			console.log(err);
			if (isAxiosError(err))
				throw new Error(err.response.data.message || "Something went wrong");
			throw err;
		}
	}
);

export const findUserByEmail = createAsyncThunk(
	`find/user_by_email`,
	async (payload, { getState }) => {
		const {
			purchase: { userDetails },
		} = getState();

		try {
			const response = await axiosBuzzOne({
				method: "GET",
				url: `/profile/akademy/users/email/${payload.email || userDetails.email}`,
			});
			return response.data.data;
		} catch (err) {
			console.log(err);
			if (isAxiosError(err))
				throw new Error(err.response.data.message || "Something went wrong");
			throw err;
		}
	}
);

export const createNewAkademySchool = createAsyncThunk(
	`akadmy/create/school`,
	async (payload) => {
		try {
			const response = await axiosBuzzOne({
				method: "POST",
				url: `/akademy/school`,
				data: {
					name: `${payload.userName}'s school`,
				},
			});

			return response.data.data;
		} catch (err) {
			console.log(err);
			if (isAxiosError(err))
				throw new Error(err.response.data.message || "Something went wrong");
			throw err;
		}
	}
);

export const sendOTPViaEmail = createAsyncThunk(
	`auth/sendOTPViaEmail`,
	async (payload, { getState, dispatch }) => {
		const { purchase, auth } = getState();

		try {
			const response = await axiosBuzzOne({
				method: "POST",
				url: "/auth/otp",
				data: {
					email: purchase.userDetails.email,
					isAuthenticatedUser: false,
				},
			});

			dispatch(emailOTPSentSuccess());

			const data = response.data;
			return data;
		} catch (err) {
			console.log(err);
			if (isAxiosError(err))
				throw new Error(err.response.data.message || "Something went wrong");
			throw err;
		}
	}
);

export const verifyEmailOTP = createAsyncThunk(
	`auth/verifyEmailOTP`,
	async (payload, { getState }) => {
		const { purchase } = getState();

		try {
			const response = await axiosBuzzOne({
				method: "POST",
				url: "/auth/verify",
				data: {
					email: purchase.userDetails.email,
					otp: payload.otp,
					isAuthenticatedUser: false,
				},
			});
			const data = response.data;
			return data;
		} catch (err) {
			console.log(err);
			if (isAxiosError(err))
				throw new Error(err.response.data.message || "Something went wrong");
			throw err;
		}
	}
);

export const getUserSubscriptions = createAsyncThunk(
	`find/user/subscriptions`,
	async (payload, { getState }) => {
		const {
			auth: { user },
		} = getState();

		try {
			const response = await axiosBuzzOne({
				method: "GET",
				url: `/akademy/subscriptions/users/${payload.userId || user._id}`,
			});
			return response.data;
		} catch (err) {
			console.log(err);
			if (isAxiosError(err))
				throw new Error(err.response.data.message || "Something went wrong");
			throw err;
		}
	}
);

export const authSlice = createSlice({
	name: "auth",
	initialState: {
		loading: false,
		token: localStorage.getItem(TOKEN_NAME),
		availability: null,
		isAuthenticated: null,
		sendOtpStatus: null,
		user:
			(localStorage.getItem("AUTH_USER") &&
				JSON.parse(localStorage.getItem("AUTH_USER"))) ||
			null,
		userProfile:
			(localStorage.getItem("AUTH_USER_PROFILE") &&
				JSON.parse(localStorage.getItem("AUTH_USER_PROFILE"))) ||
			null,
		isUserVerified:
			localStorage.getItem("IS_USER_VERIFIED") == "true" ? true : false,

		isEmailOTPSent:
			localStorage.getItem("IS_EMAIL_OTP_SENT") == "true" ? true : false,
	},
	reducers: {
		setUser: (state, { payload }) => {
			state.user = payload;
			if (payload) localStorage.setItem("AUTH_USER", JSON.stringify(payload));
			else localStorage.removeItem("AUTH_USER");
		},
		setUserProfile: (state, { payload }) => {
			state.userProfile = payload;
			if (payload)
				localStorage.setItem("AUTH_USER_PROFILE", JSON.stringify(payload));
			else localStorage.removeItem("AUTH_USER_PROFILE");
		},
		emailOTPSentSuccess: (state) => {
			state.isEmailOTPSent = true;
			localStorage.setItem("IS_EMAIL_OTP_SENT", true);
		},
		resetEmailOTPStatus: (state) => {
			state.isEmailOTPSent = false;
			localStorage.setItem("IS_EMAIL_OTP_SENT", false);
		},
		userVerificationSuccess: (state) => {
			state.isUserVerified = true;
			localStorage.setItem("IS_USER_VERIFIED", true);
		},
		logOut: (state) => {
			state.isAuthenticated = false;
			state.loading = false;
			state.user = null;
			state.token = null;
			localStorage.removeItem(TOKEN_NAME);
			localStorage.removeItem("userId");
			localStorage.removeItem("schoolId");
		},
	},

	extraReducers: (builder) => {
		builder.addCase(buzzOneGetUserAsync.pending, (state, action) => {
			state.loading = true;
		});
		builder.addCase(buzzOneGetUserAsync.fulfilled, (state, action) => {
			state.isAuthenticated = true;
			state.loading = false;
			state.user = action.payload;
		});
		builder.addCase(buzzOneGetUserAsync.rejected, (state, action) => {
			state.isAuthenticated = false;
			state.loading = false;
			state.user = null;
			state.token = null;
			localStorage.removeItem(TOKEN_NAME);
		});

		builder.addCase(buzzOneSignInAsync.pending, (state, action) => {
			state.loading = true;
		});
		builder.addCase(buzzOneSignInAsync.fulfilled, (state, action) => {
			state.loading = false;
			localStorage.setItem(TOKEN_NAME, `${action.payload.token}`);
			localStorage.setItem("userId", action.payload.profiles[0]._id);
			localStorage.setItem("identityId", action.payload._id);
			console.log("user loaded", action.payload);
		});
		builder.addCase(buzzOneSignInAsync.rejected, (state, action) => {
			state.isAuthenticated = false;
			state.loading = false;
			state.user = null;
			state.token = null;
			localStorage.removeItem(TOKEN_NAME);
		});

		builder.addCase(postVerificationSteps.fulfilled, (state, action) => {
			state.user = action.payload.user;
		});
	},
});

// Action creators are generated for each case reducer function
export const {
	setUser,
	setUserProfile,
	logOut,
	userVerificationSuccess,
	emailOTPSentSuccess,
} = authSlice.actions;

export default authSlice.reducer;
