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

// Escort Type
export interface Escort {
    id?: number;
    customer_id: number;
    name?: string;
    relation?: string;
    gender?: string;
    date_of_birth?: string;
    passport_number?: string;
    country_code?: string;
    phone_number?: string;
    email?: string;
    visa_start_date?: string;
    visa_end_date?: string;
    is_sponsered?: boolean;
    escort_type?: string;
    should_remove?: boolean;
    created_at?: string;
    updated_at?: string;
}

// Escort Slice State
interface EscortState {
    items: Escort[];
    status: 'idle' | 'loading' | 'succeeded' | 'failed';
    error: string | null;
    filters: {
        search: string;
        skip: number;
        limit: number;
        sortBy?: string;
        sortOrder?: 'ASC' | 'DESC';
        customer_id: string;
    };
    totalCount: number;
}

const initialState: EscortState = {
    items: [],
    status: 'idle',
    error: null,
    filters: {
        search: '',
        limit: 10,
        skip: 0,
        sortBy: '',
        sortOrder: 'ASC',
        customer_id: '',
    },
    totalCount: 0,
};

// Fetch Escorts
export const fetchEscorts = createAsyncThunk(
    'escorts/fetchEscorts',
    async (
        params: {
            skip?: number;
            limit?: number;
            search?: string;
            sortBy?: string;
            sortOrder?: 'ASC' | 'DESC';
            customer_id?: string;
        },
        { rejectWithValue },
    ) => {
        try {
            const response = await api.get(`/escorts`, {
                params: {
                    skip: params?.skip || 0,
                    limit: params?.limit || 10,
                    search: params?.search || '',
                    sortBy: params?.sortBy,
                    sortOrder: params?.sortOrder,
                    customer_id: params?.customer_id,
                },
            });
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error.response?.data?.message || messages.toasts.error.failed_to_fetch_escorts);
        }
    },
);

export const addEscort = createAsyncThunk('escorts/add', async (escort: Escort, { rejectWithValue }) => {
    try {
        const response = await api.post('/escorts', escort);
        handleToastError(response);
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_add_escort);
    }
});

// Fetch Escorts by ID
export const fetchEscortById = createAsyncThunk('escorts/fetchById', async (id: number, { rejectWithValue }) => {
    try {
        const response = await api.get(`/escorts/${id}`);
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_fetch_escort);
    }
});

// Add or Update Escorts
export const bulkUploadEscorts = createAsyncThunk(
    'escorts/bulkUpload',
    async ({ customer_id, escorts }: { customer_id: number; escorts: Escort[] }, { rejectWithValue }) => {
        try {
            const response = await api.patch('/escorts/upsert', { customer_id, escorts });
            handleToastError(response);
            return response.data.data;
        } catch (error: any) {
            const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_upload_escorts;
            toast.error(errorMessage);
            return rejectWithValue(errorMessage);
        }
    },
);

export const deleteEscort = createAsyncThunk('escorts/delete', async (id: number, { rejectWithValue }) => {
    try {
        const response = await api.delete(`/escorts/${id}`);
        handleToastError(response);
        return response.data;
    } catch (err) {
        handleToastError(err);
        return rejectWithValue(messages.toasts.error.failed_to_delete_escort);
    }
});

// Escort Slice
const escortSlice = createSlice({
    name: 'escorts',
    initialState,
    reducers: {
        clearEscorts: (state) => {
            state.items = [];
            state.status = 'idle';
            state.error = null;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchEscorts.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchEscorts.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = action.payload.data.data;
                state.totalCount = action.payload.data.count ?? 0;
            })
            .addCase(fetchEscorts.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(bulkUploadEscorts.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(bulkUploadEscorts.fulfilled, (state, action: PayloadAction<Escort[]>) => {
                state.status = 'succeeded';
                state.items = action.payload;
            })
            .addCase(bulkUploadEscorts.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(addEscort.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(addEscort.fulfilled, (state, action: PayloadAction<Escort>) => {
                state.status = 'succeeded';
                state.items.push(action.payload);
            })
            .addCase(addEscort.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(deleteEscort.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(deleteEscort.fulfilled, (state, action: PayloadAction<Escort>) => {
                state.status = 'succeeded';
                state.items = state.items.filter((escort) => escort.id !== action.payload.id);
            })
            .addCase(deleteEscort.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            });
    },
});

export const { clearEscorts } = escortSlice.actions;
export default escortSlice.reducer;
