import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import http from "../../lib/https"; // Assuming you have a custom HTTP library for requests
import { toast } from "sonner";
import dayjs from "dayjs";

// Define TypeScript types
interface Slot {
	id: string;
	stationId: string;
	date?: string;
	startTime: string;
	startingDate?: string;
	endingDate?: string;
	endTime: string;
	duration: number;
	isAvailable: boolean;
	stationName: string;
	ChargingStation: { name: string };
}

interface SlotState {
	slots: Slot[];
	availableSlots: Slot[];
	loading: boolean;
	error: string | null;
}

// Initial state
const initialState: SlotState = {
	slots: [],
	availableSlots: [], // <-- Initialize this as an empty array
	loading: false,
	error: null,
};

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

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

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

		return response.data.data;
	} catch (error: any) {
		toast.error("Error Fetching Profile" + error);
		return rejectWithValue(
			error?.response?.data?.message || "An error occurred"
		);
	}
});
export const fetchManagersSlots = createAsyncThunk<
	Slot[],
	void,
	{ rejectValue: string }
>("fetchManagersSlots", async (_, { rejectWithValue }) => {
	try {
		const token = localStorage?.getItem("authToken");
		if (!token) throw new Error("No token found");

		const response = await http.get("/manager-slots");

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

		return response.data.data;
	} catch (error: any) {
		toast.error("Error Fetching Profile" + error);
		return rejectWithValue(
			error?.response?.data?.message || "An error occurred"
		);
	}
});
export const createSlot = createAsyncThunk<
	Slot[], // <-- updated from Slot to Slot[]
	{
		date?: string;
		startingDate?: string;
		endingDate?: string;
		startHour: string;
		endHour: string;
		isAvailable: boolean;
		duration: number;
		stationId: number;
	},
	{ rejectValue: string }
>("slots/createSlot", async (payload, { rejectWithValue }) => {
	try {
		const token = localStorage?.getItem("authToken");
		if (!token) throw new Error("No token found");

		// Make the API call to create the slots
		const response = await http.post("create-slot", payload);

		toast.success("Slot(s) created successfully");
		return response.data.data; // Return the array of created slots
	} catch (error: any) {
		toast.error("Error creating slot: " + error?.message);
		return rejectWithValue(
			error.response?.data?.message || "An error occurred"
		);
	}
});

// Update Slot details
export const updateSlot = createAsyncThunk<
	Slot,
	{
		id: string;
		startTime: string;
		endTime: string;
	},
	{ rejectValue: string }
>("slots/updateSlot", async ({ id, ...slotData }, { rejectWithValue }) => {
	try {
		const response = await http.patch(`/update-availability/${id}`, {
			...slotData,
			// Ensure data matches exactly what backend expects
			startHour: slotData.startTime,
			endHour: slotData.endTime,
		});
		toast.success("Slot updated successfully");
		return response.data.data;
	} catch (error: any) {
		toast.error("Error updating the slot: " + error?.message);
		return rejectWithValue(
			error.response?.data?.message || "An error occurred"
		);
	}
});
export const toggleStatus = createAsyncThunk<
	any,
	{ id: string; isAvailable: boolean },
	{ rejectValue: string }
>("slot/toggleStatus", async ({ id, isAvailable }, { rejectWithValue }) => {
	try {
		const response = await http.patch(`/update-availability/${id}`, {
			isAvailable,
		});

		if (response.data.statusCode === 200) {
			toast.success(
				response.data.message || "Status updated successfully"
			);
			return {
				responseData: response.data,
				id,
				isAvailable,
			};
		} 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"
		);
	}
});
export const deleteSlot = createAsyncThunk<
	string, // Return type (id of deleted slot)
	string,
	{ rejectValue: string }
>("slots/deleteSlot", async (id, { rejectWithValue }) => {
	try {
		const response = await http.delete(`/delete-slot/${id}`);
		toast.success("Slot deleted successfully");
		return id; // Return the id of the deleted slot
	} catch (error: any) {
		toast.error("Error deleting the slot: " + error?.message);
		return rejectWithValue(
			error.response?.data?.message || "An error occurred"
		);
	}
});

const slotSlice = createSlice({
	name: "slots",
	initialState,
	reducers: {},
	extraReducers: (builder) => {
		builder
			.addCase(fetchAvailableSlots.pending, (state) => {
				state.loading = true;
				state.error = null;
			})
			.addCase(
				fetchAvailableSlots.fulfilled,
				(state, action: PayloadAction<Slot[]>) => {
					state.loading = false;
					state.availableSlots = action.payload;
				}
			)
			.addCase(fetchAvailableSlots.rejected, (state, action) => {
				state.loading = false;
				state.error =
					action.payload || "Failed to fetch available slots";
			})
			.addCase(fetchManagersSlots.pending, (state) => {
				state.loading = true;
				state.error = null;
			})
			.addCase(
				fetchManagersSlots.fulfilled,
				(state, action: PayloadAction<Slot[]>) => {
					state.loading = false;
					state.availableSlots = action.payload;
				}
			)
			.addCase(fetchManagersSlots.rejected, (state, action) => {
				state.loading = false;
				state.error =
					action.payload || "Failed to fetch available slots";
			})
			.addCase(createSlot.pending, (state) => {
				state.loading = true;
			})
			.addCase(
				createSlot.fulfilled,
				(state, action: PayloadAction<Slot[]>) => {
					state.loading = false;

					const normalizedSlots = action.payload.map((slot) => {
						const combinedStart = `${slot.date} ${slot.startTime}`; // Keep raw for now
						const combinedEnd = `${slot.date} ${slot.endTime}`;

						return {
							...slot,
							startTime: combinedStart,
							endTime: combinedEnd,
						};
					});

					console.log("Normalized Slots →", normalizedSlots); // Check this in console

					state.slots.push(...normalizedSlots);
					state.availableSlots.push(...normalizedSlots);
				}
			)

			.addCase(createSlot.rejected, (state, action) => {
				state.loading = false;
				state.error = action.payload || "Failed to create slot";
			})
			.addCase(updateSlot.pending, (state) => {
				state.loading = true;
			})
			.addCase(
				updateSlot.fulfilled,
				(state, action: PayloadAction<Slot>) => {
					state.loading = false;
					// Update the slot in the state with the updated data
					const index = state.availableSlots.findIndex(
						(slot) => slot.id === action.payload.id
					);
					if (index !== -1) {
						state.availableSlots[index] = action.payload;
					}
				}
			)

			.addCase(updateSlot.rejected, (state, action) => {
				state.loading = false;
				state.error = action.payload || "Failed to update slot";
			})
			.addCase(deleteSlot.pending, (state) => {
				state.loading = true;
			})

			.addCase(toggleStatus.pending, (state) => {
				state.loading = true;
			})
			.addCase(
				toggleStatus.fulfilled,
				(state, action: PayloadAction<any>) => {
					state.loading = false;
					const { id, isAvailable } = action.payload;

					const stationIndex = state.availableSlots.findIndex(
						(slot) => slot.id === id
					);
					if (stationIndex !== -1) {
						state.availableSlots[stationIndex] = {
							...state.availableSlots[stationIndex],
							isAvailable: isAvailable,
						};
					}
				}
			)
			.addCase(
				toggleStatus.rejected,
				(state, action: PayloadAction<string | undefined>) => {
					state.loading = false;
					state.error =
						action.payload || "Failed to toggle station status";
				}
			)
			.addCase(
				deleteSlot.fulfilled,
				(state, action: PayloadAction<string>) => {
					state.loading = false;
					// Ensure we're filtering the correct array (availableSlots)
					state.availableSlots = state.availableSlots.filter(
						(slot) => String(slot.id) !== String(action.payload)
					);
					// Also update slots array if it exists
					if (state.slots) {
						state.slots = state.slots.filter(
							(slot) => String(slot.id) !== String(action.payload)
						);
					}
				}
			)
			.addCase(deleteSlot.rejected, (state, action) => {
				state.loading = false;
				state.error = action.payload || "Failed to delete slot";
			});
	},
});

export default slotSlice.reducer;
