import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios";
import http from "../../lib/https";
import { toast } from "sonner";

// Define TypeScript types
interface Role {
	id: string;
	name: string;
	resource: {
		moduleName: string;
		moduleId: string;
		permissions: string[];
	}[];
	status: number;
}

interface RoleState {
	roles: Role[];
	loading: boolean;
	error: string | null;
}

// Initial state
const initialState: RoleState = {
	roles: [],
	loading: false,
	error: null,
};

export const roleList = createAsyncThunk<any, void, { rejectValue: string }>(
	"fetchRoles",
	async (_, { rejectWithValue }) => {
		try {
			const token = localStorage?.getItem("authToken");
			if (!token) throw new Error("No token found");

			const response = await http.get("get");

			if (!response.data) throw new Error("Invalid API response");

			// Return the full response to handle in the reducer
			return response.data;
		} catch (error: any) {
			toast.error("Error Fetching Roles: " + error.message);
			return rejectWithValue(
				error?.response?.data?.message || "An error occurred"
			);
		}
	}
);

// Create Role
export const createRole = createAsyncThunk<
	any,
	{
		name: string;
		resource: {
			moduleName: string;
			moduleId: string;
			permissions: string[];
		}[];
	},
	{ rejectValue: string }
>("role/createRole", async (data, { rejectWithValue }) => {
	try {
		const response = await http.post("create", data);
		toast.success("Role created successfully");
		return response.data;
	} catch (error: any) {
		toast.error(
			"Failed to create role: " +
				(error.response?.data?.message || "Unknown error")
		);
		return rejectWithValue(
			error.response?.data?.message || "An error occurred"
		);
	}
});

export const toggleStatus = createAsyncThunk<
	any,
	{ id: string; status: number },
	{ rejectValue: string }
>("role/toggleStatus", async ({ id, status }, { rejectWithValue }) => {
	try {
		const response = await http.patch(`${id}`, { status });

		if (response.data.statusCode === 200) {
			toast.success(
				response.data.message || "Status updated successfully"
			);
			// Return both the response data and the requested status for reliable state updates
			return {
				responseData: response.data,
				id,
				status,
			};
		} else {
			throw new Error(response.data.message || "Failed to update status");
		}
	} catch (error: any) {
		toast.error(
			"Error updating status: " + (error.message || "Unknown error")
		);
		return rejectWithValue(
			error.response?.data?.message ||
				error.message ||
				"An error occurred"
		);
	}
});

const roleSlice = createSlice({
	name: "roles",
	initialState,
	reducers: {},
	extraReducers: (builder) => {
		builder
			.addCase(roleList.pending, (state) => {
				state.loading = true;
				state.error = null;
			})
			.addCase(
				roleList.fulfilled,
				(state, action: PayloadAction<any>) => {
					state.loading = false;
					// Properly extract roles from the response data structure
					state.roles =
						action.payload.data?.results ||
						action.payload.data ||
						[];
				}
			)
			.addCase(roleList.rejected, (state, action) => {
				state.loading = false;
				state.error = action.payload || "Failed to fetch roles";
			})
			.addCase(createRole.pending, (state) => {
				state.loading = true;
			})
			.addCase(
				createRole.fulfilled,
				(state, action: PayloadAction<any>) => {
					state.loading = false;
					// Add the newly created role to the state if it exists in the response
					if (action.payload.data) {
						state.roles.push(action.payload.data);
					}
				}
			)
			.addCase(
				createRole.rejected,
				(state, action: PayloadAction<string | undefined>) => {
					state.loading = false;
					state.error = action.payload || "Failed to create role";
				}
			)
			.addCase(toggleStatus.pending, (state) => {
				state.loading = true;
			})
			.addCase(
				toggleStatus.fulfilled,
				(state, action: PayloadAction<any>) => {
					state.loading = false;

					// Get the id and updated status from the action payload
					const { id, status } = action.payload;

					// Find and update the role with the new status
					const roleIndex = state.roles.findIndex(
						(role) => role.id === id
					);
					if (roleIndex !== -1) {
						state.roles[roleIndex] = {
							...state.roles[roleIndex],
							status: status,
						};
					}
				}
			)
			.addCase(
				toggleStatus.rejected,
				(state, action: PayloadAction<string | undefined>) => {
					state.loading = false;
					state.error =
						action.payload || "Failed to toggle role status";
				}
			);
	},
});

export default roleSlice.reducer;
