import api from '@/lib/axios';
import { handleToastError } from '@/lib/utils';
import { createSlice, createAsyncThunk, type PayloadAction } from '@reduxjs/toolkit';
import { toast } from 'sonner';
import messages from '@/messages/en.json';

// Define a type for the vehicle
export interface Vehicle {
    id: number;
    vehicle_manufacture_id: number;
    vehicle_model_id: number;
    passenger_capacity: string;
    year: string;
    color: string;
    registration_number: string;
    registration_start_date?: string;
    registration_expiry_date?: string;
    state: number;
    vin_number: string;
    odo_reader: number;
    unit: 'km' | 'miles';
    status: 'Operational' | 'Reserved' | 'Under Maintenance' | 'Unassigned';
    vehicle_description?: string;
    makeName: string;
    modelName: string;
    typeName: string;
    vehicle_ownership: string;
    owner_information: string;
    vehicle_location_id: number;
    assigned_driver_id: number;
    assigned_dispatcher_id: number;
    driverName: string;
    dispatcherName: string;
}

// Define the state interface
export interface VehiclesState {
    items: Vehicle[];
    status: 'idle' | 'loading' | 'succeeded' | 'failed';
    error: string | null;
    filters: {
        search: string;
        limit: number;
        skip: number;
        sortBy: string;
        sortOrder: string;
        make: string;
        type: string;
        status: string;
        vehicle_ownership: string;
    };
    totalCount: number;
    driver: any;
    dispatcher: Vehicle[];
}

// Initial state
const initialState: VehiclesState = {
    items: [],
    status: 'idle',
    error: null,
    filters: {
        search: '',
        limit: 10,
        skip: 0,
        sortBy: 'name',
        sortOrder: 'ASC',
        make: 'all',
        type: 'all',
        status: 'all',
        vehicle_ownership: '',
    },
    totalCount: 0,
    driver: [],
    dispatcher: [],
};

// Sample data for initial development

// Define types for adding a new vehicle
type AddVehiclePayload =
    | {
          vehicle_ownership: string;
          owner_information?: string;
          vehicle_manufacture_id: number;
          vehicle_model_id: number;
          vehicle_type_id: number;
          passenger_capacity: string;
          year: string;
          color: string;
          registration_number: string;
          registration_start_date?: string;
          registration_expiry_date?: string;
          state_id: number;
          vin_number: string;
          odo_reader: number;
          unit: string;
          vehicle_status_id: number;
          vehicle_description?: string;
          assigned_driver?: number;
          vehicle_location_id: number;
          assigned_dispatcher_id?: number;
          dispatcherName?: string;
          registration_document?: string;
      }
    | FormData;

// Async thunk for fetching vehicles
export const fetchVehicles = createAsyncThunk(
    'vehicles/fetchVehicles',
    async (
        params: {
            skip?: number;
            limit?: number;
            search?: string;
            sortBy?: string;
            sortOrder?: 'ASC' | 'DESC';
            vehicle_manufacture_id?: string;
            vehicle_type_id?: string;
            vehicle_status_id?: string;
            vehicle_ownership?: string;
        },
        { rejectWithValue },
    ) => {
        try {
            const response = await api.get('fleet-management', {
                params: {
                    skip: params.skip || 0,
                    limit: params.limit || 10,
                    search: params.search || '',
                    sortBy: params.sortBy || 'name',
                    sortOrder: params.sortOrder || 'ASC',
                    vehicle_manufacture_id: params.vehicle_manufacture_id,
                    vehicle_type_id: params.vehicle_type_id,
                    vehicle_status_id: params.vehicle_status_id,
                    vehicle_ownership: params.vehicle_ownership,
                },
            });
            return response?.data;
        } catch (error) {
            return rejectWithValue('Failed to fetch vehicles');
        }
    },
);

// Async thunk for adding a new vehicle
export const addVehicle = createAsyncThunk('vehicles/addVehicle', async (payload: AddVehiclePayload, { rejectWithValue }) => {
    try {
        let response;

        if (payload instanceof FormData) {
            // When uploading files
            response = await api.post('fleet-management', payload, {
                headers: { 'Content-Type': 'multipart/form-data' },
            });
        } else {
            // ✅ When no file is uploaded
            response = await api.post('fleet-management', payload, {
                headers: { 'Content-Type': 'application/json' },
            });
        }

        handleToastError(response);
        return response;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_add_vehicle);
    }
});

export const fetchVehicleDetail = createAsyncThunk('vehicles/details', async (id: number, { rejectWithValue }) => {
    try {
        const response = await api.get(`fleet-management/${id}`);
        return response.data.data;
    } catch (error) {
        return rejectWithValue('Failed to add vehicle');
    }
});

// Async thunk for deleting a vehicle
export const deleteVehicle = createAsyncThunk('vehicles/deleteVehicle', async (vehicleId: number, { rejectWithValue }) => {
    try {
        const response = await api.delete(`fleet-management/${vehicleId}`);
        if (response.data.code === 200) {
            toast.success(messages.toasts.success.vehicle_deleted);
            return vehicleId;
        } else {
            toast.error(messages.toasts.error.failed_to_delete_vehicle);
            return rejectWithValue(messages.toasts.error.failed_to_delete_vehicle);
        }
    } catch (error) {
        toast.error(messages.toasts.error.failed_to_delete_vehicle);
        return rejectWithValue(messages.toasts.error.failed_to_delete_vehicle);
    }
});

// Async thunk for updating a vehicle
export const updateVehicle = createAsyncThunk(
    'vehicles/updateVehicle',
    async ({ id, vehicleData }: { id: number; vehicleData: Partial<AddVehiclePayload> | FormData }, { rejectWithValue }) => {
        try {
            let response;

            if (vehicleData instanceof FormData) {
                // With file(s)
                response = await api.patch(`fleet-management/${id}`, vehicleData, {
                    headers: { 'Content-Type': 'multipart/form-data' },
                });
            } else {
                // ✅ Without file(s) – plain JSON
                response = await api.patch(`fleet-management/${id}`, vehicleData, {
                    headers: { 'Content-Type': 'application/json' },
                });
            }

            handleToastError(response);
            return response;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_update_vehicle);
        }
    },
);

export const addRegistrationDocument = createAsyncThunk(
    'vehicles/addRegistrationDocument',
    async ({ id, vehicleData }: { id: number; vehicleData: Partial<AddVehiclePayload> }, { rejectWithValue, getState }) => {
        try {
            const response = await api.patch(`fleet-management/${id}/registration-document`, vehicleData);

            return response;
        } catch (error) {
            return rejectWithValue('Failed to add registration document');
        }
    },
);

export const getAllDriver = createAsyncThunk('vehicles/driver', async (_, { rejectWithValue }) => {
    try {
        const response = await api.get('/team-member/drivers-by-role');
        return response;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch drivers');
    }
});

export const getAllDispatcher = createAsyncThunk('vehicles/dispatcher', async (_, { rejectWithValue }) => {
    try {
        const response = await api.get('/team-member/dispatchers-by-role');

        return response;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch drivers');
    }
});

// Reducers
const vehiclesSlice = createSlice({
    name: 'vehicles',
    initialState,
    reducers: {
        setFilters: (state, action: PayloadAction<Partial<VehiclesState['filters']>>) => {
            state.filters = { ...state.filters, ...action.payload };
        },
        resetFilters: (state) => {
            state.filters = initialState.filters;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchVehicles.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchVehicles.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = action.payload?.data?.data;
                state.totalCount = action.payload?.data.count;
            })
            .addCase(fetchVehicles.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(addVehicle.fulfilled, (state, action) => {
                const code = action.payload?.data?.code;

                if (code === 200 || code === 201) {
                    toast.success(messages.toasts.success.vehicle_added);
                } else if (code === 422) {
                    toast.error(messages.toasts.error.vehicle_exists);
                } else {
                    toast.error(action.payload?.data?.message);
                }
            })
            .addCase(deleteVehicle.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(deleteVehicle.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = state.items.filter((item) => item.id !== action.payload);
            })
            .addCase(deleteVehicle.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(updateVehicle.fulfilled, (state, action) => {
                const code = action?.payload?.data?.code;
                if (code === 200 || code === 201) {
                    toast.success(messages.toasts.success.vehicle_updated);
                } else if (code === 422) {
                    toast.error(messages.toasts.error.vehicle_exists);
                } else {
                    toast.error(action.payload?.data?.message);
                }
            })
            .addCase(addRegistrationDocument.fulfilled, (state, action) => {
                const code = action?.payload?.data?.code;
                if (code === 200 || code === 201) {
                    toast.success(messages.toasts.success.registration_document_added);
                } else if (code === 422) {
                    toast.error(messages.toasts.error.registration_document_exists);
                } else {
                    toast.error(messages.toasts.error.generic);
                }
            })
            .addCase(getAllDriver.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(getAllDriver.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.driver = action.payload?.data?.data || [];
            })
            .addCase(getAllDriver.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(getAllDispatcher.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(getAllDispatcher.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.dispatcher = action.payload?.data?.data || [];
            })
            .addCase(getAllDispatcher.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(fetchVehicleDetail.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchVehicleDetail.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(fetchVehicleDetail.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            });
    },
});

export const { setFilters, resetFilters } = vehiclesSlice.actions;

export default vehiclesSlice.reducer;
