import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import api from '@/lib/axios';
import { toast } from 'sonner';
import { ClientCustomer } from '@/lib/types/client';
import moment from 'moment';
import axios from 'axios';
import messages from '@/messages/en.json';

interface TripFilters {
    search?: string;
    limit?: number;
    skip?: number;
    country_id?: number;
    is_medical_patient?: string;
    status?: string;
    trip_type_id?: number;
    driver_id?: number;
    customer_id?: number;
}

interface TripState {
    currentTripId: any | null;
    items: any | null;
    status: 'idle' | 'loading' | 'succeeded' | 'failed';
    driverListing: any;
    error: string | null;
    selectedCustomer: ClientCustomer | null;
    details: any;
    /** Matches the latest `getTripDetail(id)` request so stale responses are ignored */
    lastTripDetailRequestId: any | null;
    totalCount: number;
    filters: TripFilters;
    tripType: [];
    cancelReasons: any[];
    cancelReasonsStatus: 'idle' | 'loading' | 'succeeded' | 'failed';
    tripAddOnsPricing: any;
    tripServicePricing: any;
    basePricing: any;
    tripTimeZone: [];
    chatHistory: any[];
    chatHistoryStatus: 'idle' | 'loading' | 'succeeded' | 'failed';
    chatHistoryError: string | null;
    tripHistory: any[];
    loadingHistory: boolean;
    historyError: string | null;
}

export interface FlightResponse {
    pagination: {
        limit: number;
        offset: number;
        count: number;
        total: number;
    };
    data: Flight[];
}

export interface Flight {
    flight_date: string;
    flight_status: string;
    departure: {
        airport: string;
        timezone: string;
        iata: string;
        icao: string;
        terminal: string | null;
        gate: string | null;
        delay: number | null;
        scheduled: string | null;
        estimated: string | null;
        actual: string | null;
        estimated_runway: string | null;
        actual_runway: string | null;
    };
    arrival: {
        airport: string;
        timezone: string;
        iata: string;
        icao: string;
        terminal: string | null;
        gate: string | null;
        baggage: string | null;
        delay: number | null;
        scheduled: string | null;
        estimated: string | null;
        actual: string | null;
        estimated_runway: string | null;
        actual_runway: string | null;
    };
    airline: {
        name: string;
        iata: string;
        icao: string;
    };
    flight: {
        number: string;
        iata: string;
        icao: string;
        codeshared: {
            airline_name: string;
            airline_iata: string;
            airline_icao: string;
            flight_number: string;
            flight_iata: string;
            flight_icao: string;
        } | null;
    };
    aircraft: null | any;
    live: null | any;
}

export interface SearchParams {
    flight_number?: string;
    flight_date?: string;
    limit?: number;
    offset?: number;
}

const initialState: TripState = {
    items: null,
    details: null,
    lastTripDetailRequestId: null,
    driverListing: null,
    status: 'idle',
    error: null,
    selectedCustomer: null,
    totalCount: 0,
    filters: {
        search: '',
        limit: 10,
        skip: 0,
        country_id: undefined,
        is_medical_patient: undefined,
        status: undefined,
        trip_type_id: undefined,
        customer_id: undefined,
    },
    currentTripId: null,
    tripType: [],
    cancelReasons: [],
    cancelReasonsStatus: 'idle',
    tripAddOnsPricing: [],
    tripServicePricing: [],
    basePricing: [],
    tripTimeZone: [],
    chatHistory: [],
    chatHistoryStatus: 'idle',
    chatHistoryError: null,
    tripHistory: [],
    loadingHistory: false,
    historyError: null,
};

export const fetchTrip = createAsyncThunk('trip/fetchTrip', async (params: TripFilters, { rejectWithValue }) => {
    try {
        const response = await api.get('/trips', {
            params,
        });
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch trips');
    }
});

// Updated scheduleTrip to accept FormData
export const scheduleTrip = createAsyncThunk('customers/addCustomer', async (payload: FormData, { rejectWithValue }) => {
    try {
        const response = await api.post('/trips', payload, {
            headers: {
                'Content-Type': 'multipart/form-data',
            },
        });

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

export const getTripType = createAsyncThunk('trip/getTripType', async (_: void, { rejectWithValue }) => {
    try {
        const response = await api.get('/trips/types');

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

export const getCancelReasons = createAsyncThunk('trip/getCancelReasons', async (type?: string, { rejectWithValue }) => {
    try {
        const response = await api.get('/cancel-reasons', {
            params: type ? { type } : undefined,
        });
        return response;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch cancel reasons');
    }
});

export const cancelTrip = createAsyncThunk(
    'trip/cancelTrip',
    async (
        payload: {
            trip_id: number;
            canceled_by: string;
            canceled_by_id: number;
            reason_id?: number;
            other_input?: string;
        },
        { rejectWithValue },
    ) => {
        try {
            const response = await api.post('/trips/cancel', payload);
            return response;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to cancel trip');
        }
    },
);

export const completeTrip = createAsyncThunk(
    'trip/completeTrip',
    async (
        {
            id,
            data,
        }: {
            id: number | string;
            data: {
                start_time: string;
                end_time: string;
            };
        },
        { rejectWithValue },
    ) => {
        try {
            const response = await api.patch(`/trips/complete-trip/${id}`, data);
            return response?.data;
        } catch (error: any) {
            toast.error(error?.response?.data?.message || 'Failed to complete trip');
            return rejectWithValue(error?.response?.data?.message || 'Failed to complete trip');
        }
    },
);

// Updated updateTrip to accept FormData
export const updateTrip = createAsyncThunk(
    'trip/updateTrip',
    async ({ id, data }: { id: string; data: FormData }, { rejectWithValue }) => {
        try {
            const response = await api.patch(`/trips/${id}`, data, {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
            });

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

export const addTripIntermediateStop = createAsyncThunk('trip/intermediateStop', async (data: any, { rejectWithValue }) => {
    try {
        const response = await api.patch('/trip-intermediate-stops', data?.data);
        return response?.data;
    } catch (error) {
        return rejectWithValue(error);
    }
});

export const getTripDetail = createAsyncThunk('trip/detail', async (id: any, { rejectWithValue }) => {
    try {
        const response = await api.get(`trips/${id}`);

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

export const getChatHistory = createAsyncThunk(
    'trip/getChatHistory',
    async (
        payload: {
            current_user_id: number;
            current_user_type: 'team_member' | 'driver' | 'customer';
            target_user_id: number;
            target_user_type: 'team_member' | 'driver' | 'customer';
            trip_id: number;
        },
        { rejectWithValue },
    ) => {
        try {
            const response = await api.post('/dispatcher/chat-history', payload);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch chat history');
        }
    },
);

export const addBabySeat = createAsyncThunk('trip/babySeat', async (data: any, { rejectWithValue }) => {
    try {
        const response = await api.patch('/trips/assign/baby-seats', data);
        return response;
    } catch (error) {
        return rejectWithValue(error);
    }
});

export const getDriverAvailableForTrip = createAsyncThunk('trip/driver', async (params: any, { rejectWithValue }) => {
    try {
        const response = await api.get(`/trips/available-driver/${params?.id}`, { params });

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

export const getAllAvailableVehicleByType = createAsyncThunk('trip/vehicle-types', async (params: any, { rejectWithValue }) => {
    try {
        const response = await api.get(`/fleet-management/trip/${params?.id}`, { params });
        return response;
    } catch (error) {
        return rejectWithValue(error);
    }
});

export const assignFleetToTrip = createAsyncThunk('trip/fleet-assign', async ({ id, payload }: any, { rejectWithValue }) => {
    try {
        const response = await api.post(`/trips/${id}/assign-fleets`, payload);

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

export const tripAddOnsPricing = createAsyncThunk('trip/addons-pricing', async (id: any, { rejectWithValue }) => {
    try {
        const response = await api.get(`/trips/${id}/selected-addons`);

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

export const tripServicePricing = createAsyncThunk('trip/service-pricing', async (id: any, { rejectWithValue }) => {
    try {
        const response = await api.get(`/trips/${id}/contract-charges`);

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

export const addTripsAddOnPricing = createAsyncThunk('trips/addons-pricing', async (payload: any, { rejectWithValue }) => {
    try {
        const response = await api.patch('/trips/price/add-ons-pricing', payload);

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

export const addTripsServicePricing = createAsyncThunk(
    'trips/service-charge-pricing',
    async (payload: any, { rejectWithValue }) => {
        try {
            const response = await api.patch('/trips/price/service-charge/pricing', payload);

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

export const calculateTripPricing = createAsyncThunk(
    'trips/service-charge-pricing',
    async (payload: any, { rejectWithValue }) => {
        try {
            const response = await api.post('/trips/calculate-pricing', payload);

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

export const getVehicleBasePricing = createAsyncThunk('trips/base-pricing', async (id: any, { rejectWithValue }) => {
    try {
        const response = await api.get(`/trips/${id}/base-price`);

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

export const updateVehicleBasePricing = createAsyncThunk('trips/base-pricing', async (payload: any, { rejectWithValue }) => {
    try {
        const response = await api.patch('/trips/price/base-pricing', payload);

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

export const tripTimeZone = createAsyncThunk('trips/timeZone', async (_: void, { rejectWithValue }) => {
    try {
        const response = await api.get('/trips/timezone');
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch trip timezones');
    }
});

export const fetchTripTimelineHistory = createAsyncThunk(
    'trips/fetchTripTimelineHistory',
    async (tripId: number, { rejectWithValue }) => {
        try {
            const response = await api.get(`/trips/${tripId}/timeline`);
            return response.data.data; // only array needed
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch trip history');
        }
    },
);

export const checkDriverAvailability = createAsyncThunk(
    'trips/fetchTripTimelineHistory',
    async ({ fleetId, tripId }: any, { rejectWithValue }) => {
        try {
            const response = await api.get(`/fleet-management/check-fleet-availability/${fleetId}/trip/${tripId}`);
            return response?.data?.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch trip history');
        }
    },
);

export const createAroundTrip = createAsyncThunk('trips/createAroundTrip', async (id: any, { rejectWithValue }) => {
    try {
        const response = await api.post(`/trips/${id}/create-round-trip`);

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

export const searchFlightByNumber = async (
    flightNumber: string,
    page: number = 1,
    limit: number = 10,
    token: any,
    flightDate?: string,
): Promise<FlightResponse> => {
    try {
        const currentDate = flightDate || moment().format('YYYY-MM-DD');
        const offset = (page - 1) * limit;

        const API_BASE_URL = 'https://api.aviationstack.com/v1';

        const response = await axios.get(`${API_BASE_URL}/flights`, {
            params: {
                access_key: token.toString(),
                flight_iata: flightNumber,
                flight_date: currentDate,
                limit,
                offset,
            },
        });
        return response.data;
    } catch (error) {
        console.error('Error fetching flight data:', error);
        throw error;
    }
};

const tripSlice = createSlice({
    name: 'trips',
    initialState,
    reducers: {
        setCurrentTripId(state, action: PayloadAction<number>) {
            state.currentTripId = action.payload;
        },
        clearTripDetail(state) {
            state.details = null;
            state.currentTripId = null;
            state.lastTripDetailRequestId = null;
        },
        /** Clears only `details` — use when the trip id in the URL / context changes before refetching */
        clearTripDetails(state) {
            state.details = null;
            state.lastTripDetailRequestId = null;
        },
        updateTripFilters(state, action: PayloadAction<Partial<TripFilters>>) {
            state.filters = { ...state.filters, ...action.payload };
        },
        resetTripFilters(state) {
            state.filters = {
                search: '',
                limit: 10,
                skip: 0,
                country_id: undefined,
                is_medical_patient: undefined,
                status: undefined,
                trip_type_id: undefined,
                customer_id: undefined,
            };
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchTrip.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchTrip.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = action.payload?.data?.data || [];
                state.totalCount = action.payload?.data?.count || 0;
            })
            .addCase(fetchTrip.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(scheduleTrip.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(scheduleTrip.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(scheduleTrip.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(getTripType.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(getTripType.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.tripType = action.payload?.data?.data || [];
            })
            .addCase(getTripType.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(updateTrip.fulfilled, (state, action) => {
                state.status = 'succeeded';

                if (action?.payload?.code === 404) {
                    toast.error(action?.payload?.message || messages.toasts.error.generic);
                }
            })
            .addCase(createAroundTrip.fulfilled, (state, action) => {
                state.status = 'succeeded';
                if (action?.payload?.code === 200) {
                    toast.success(action?.payload?.message || 'Round trip created successfully');
                } else {
                    toast.error(action?.payload?.message);
                }
            })
            .addCase(addTripIntermediateStop.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(getTripDetail.pending, (state, action: any) => {
                state.status = 'loading';
                state.details = null;
                state.lastTripDetailRequestId = action.meta.arg;
            })
            .addCase(getTripDetail.fulfilled, (state, action: any) => {
                const requestedId = action.meta.arg;
                if (Number(requestedId) !== Number(state.lastTripDetailRequestId)) {
                    return;
                }
                state.details = action?.payload?.data?.data ?? null;
                state.status = 'succeeded';
            })
            .addCase(getTripDetail.rejected, (state, action: any) => {
                const requestedId = action.meta.arg;
                if (state.lastTripDetailRequestId != null && Number(requestedId) !== Number(state.lastTripDetailRequestId)) {
                    return;
                }
                state.status = 'failed';
                state.details = null;
            })
            .addCase(addBabySeat.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(getDriverAvailableForTrip.fulfilled, (state, action) => {
                state.driverListing = action.payload;
            })
            .addCase(assignFleetToTrip.fulfilled, (state, action) => {
                if (action?.payload?.data?.code === 400) {
                    toast.error(action?.payload?.data?.message);
                }
            })
            .addCase(getCancelReasons.pending, (state) => {
                state.cancelReasonsStatus = 'loading';
            })
            .addCase(getCancelReasons.fulfilled, (state, action) => {
                state.cancelReasonsStatus = 'succeeded';
                state.cancelReasons = action.payload?.data?.data || [];
            })
            .addCase(getCancelReasons.rejected, (state, action) => {
                state.cancelReasonsStatus = 'failed';
                state.error = action.payload as string;
            })
            .addCase(cancelTrip.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(cancelTrip.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(completeTrip.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(completeTrip.fulfilled, (state, action: any) => {
                state.status = 'succeeded';
                if (action?.payload?.code === 200) {
                    toast.success(action?.payload?.message || 'Trip marked as completed');
                }
            })
            .addCase(completeTrip.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(tripAddOnsPricing.fulfilled, (state, action) => {
                state.tripAddOnsPricing = action?.payload?.data;
            })
            .addCase(tripServicePricing.fulfilled, (state, action) => {
                state.tripServicePricing = action?.payload?.data;
            })
            .addCase(addTripsAddOnPricing.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(getVehicleBasePricing.fulfilled, (state, action) => {
                state.basePricing = action?.payload?.data;
            })
            .addCase(tripTimeZone.fulfilled, (state, action) => {
                state.tripTimeZone = action?.payload?.data || [];
            })
            .addCase(getChatHistory.pending, (state) => {
                state.chatHistoryStatus = 'loading';
                state.chatHistoryError = null;
            })
            .addCase(getChatHistory.fulfilled, (state, action) => {
                state.chatHistoryStatus = 'succeeded';
                const history = action.payload?.data?.history;
                state.chatHistory = Array.isArray(history) ? history : [];
            })
            .addCase(getChatHistory.rejected, (state, action) => {
                state.chatHistoryStatus = 'failed';
                state.chatHistoryError = action.payload as string;
            })
            .addCase(fetchTripTimelineHistory.pending, (state) => {
                state.loadingHistory = true;
                state.historyError = null;
            })
            .addCase(fetchTripTimelineHistory.fulfilled, (state, action) => {
                state.loadingHistory = false;
                state.tripHistory = action.payload;
            })
            .addCase(fetchTripTimelineHistory.rejected, (state, action) => {
                state.loadingHistory = false;
                state.historyError = action.payload as string;
            });
    },
});

export const { setCurrentTripId, clearTripDetail, clearTripDetails, updateTripFilters, resetTripFilters } = tripSlice.actions;

export default tripSlice.reducer;
