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

// Types based on your API response
interface City {
    id: number;
    name: string;
}

interface State {
    id: number;
    name: string;
}

interface Country {
    id: number;
    name: string;
}

interface Hospital {
    id: number;
    name: string;
    address: string;
    phone_number: string;
    email: string;
}

interface VehicleType {
    id: number;
    name: string;
}

// Customer Rating - Updated to match new API response
interface CustomerRatings {
    ratingCount: number;
    averageRating: number;
    topTags: string[];
}

interface Customer {
    id: number;
    client_company_id: number;
    client_contact_id: number;
    city_id: number;
    state_id: number;
    country_id: number;
    pricing_city_id?: number;
    pricing_city?: { id: number; name: string };
    hospital_id: number;
    vehicle_type_id: number;
    profile_photo: string | null;
    customer_name: string;
    date_of_birth: string;
    gender: string;
    primary_address: string;
    secondary_address: string;
    zip_code: string;
    country_code: string;
    phone_number: string;
    email: string;
    visa_start_date: string;
    visa_end_date: string;
    reference_number: string;
    prn_number: string;
    logNumber: string;
    episodeStartDate: string | null;
    episode: string;
    log_issue_at: string | null;
    log_expire_at: string | null;
    letter_of_guarantee: string;
    is_medical_tourist: boolean;
    department: string;
    job_title: string;
    status: string;
    current_step: number;
    created_at: string;
    updated_at: string;
    deleted_at: string | null;
    tags: string[];
    city: City;
    state: State;
    country: Country;
    hospital: Hospital;
    vehicle_type: VehicleType;
}

interface CustomerResponse {
    count: number;
    data: Customer[];
}

interface ApiResponse {
    success: boolean;
    code: number;
    message: string;
    data: CustomerResponse;
}

interface CustomerFilters {
    search?: string;
    limit?: number;
    skip?: number;
    sortBy?: string;
    sortOrder?: 'asc' | 'desc';
    country_id?: number;
    is_medical_patient?: string;
    client_id: number | undefined;
    dispatcher_id?: number;
    is_direct_customer?: boolean;
    hospital_id?: number;
    prn_number?: any;
    is_customer_dropdown?: boolean;
}

// Fixed CustomerState interface
interface CustomerState {
    items: Customer[] | null;
    status: 'idle' | 'loading' | 'succeeded' | 'failed';
    error: string | null;
    selectedCustomer: ClientCustomer | null;
    totalCount: number;
    filters: CustomerFilters;
    customerRatings: CustomerRatings | null;
    customerRatingsStatus: 'idle' | 'loading' | 'succeeded' | 'failed';
    customerEpisodes: any;
    episodeLogs: any;
}

const initialState: CustomerState = {
    items: null,
    status: 'idle',
    error: null,
    selectedCustomer: null,
    totalCount: 0,
    filters: {
        search: '',
        limit: 10,
        skip: 0,
        sortBy: 'created_at',
        sortOrder: 'desc',
        country_id: undefined,
        is_medical_patient: undefined,
        client_id: undefined,
        dispatcher_id: undefined,
    },
    customerRatings: null,
    customerRatingsStatus: 'idle',
    customerEpisodes: null,
    episodeLogs: null,
};

export const fetchCustomers = createAsyncThunk(
    'customers/fetchCustomers',
    async (params: CustomerFilters, { rejectWithValue }) => {
        try {
            const response = await api.get('/customers', {
                params: {
                    ...(params.search && { search: params.search }),
                    ...(params.limit && { limit: params.limit }),
                    ...(params.skip && { skip: params.skip }),
                    ...(params.sortBy && { sortBy: params.sortBy }),
                    ...(params.sortOrder && { sortOrder: params.sortOrder }),
                    ...(params.is_customer_dropdown && { is_customer_dropdown: params.is_customer_dropdown }),
                    ...(params.country_id !== undefined && { country_id: params.country_id }),
                    ...(params.is_medical_patient !== undefined && { is_medical_patient: params.is_medical_patient }),
                    ...(params.client_id !== undefined && { client_id: params.client_id }),
                    ...(params.dispatcher_id !== undefined && { dispatcher_id: params.dispatcher_id }),
                    ...(params.is_direct_customer !== undefined && { is_direct_customer: params.is_direct_customer }),
                    ...(params.hospital_id !== undefined && { hospital_id: params.hospital_id }),
                    ...(params.prn_number !== undefined && { prn_number: params.prn_number }),
                },
            });
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch customers');
        }
    },
);

export const fetchCustomerById = createAsyncThunk('customers/fetchCustomerById', async (id: number, { rejectWithValue }) => {
    try {
        const response = await api.get(`/customers/${id}`);
        return response.data.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch customer details');
    }
});

export const createCustomer = createAsyncThunk('customers/createCustomer', async (formData: FormData, { rejectWithValue }) => {
    try {
        const response = await api.post('/customers', formData, {
            headers: {
                'Content-Type': 'application/json',
            },
        });
        handleToastError(response);
        return response.data;
    } catch (error: any) {
        const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_save_customer_information;
        toast.error(errorMessage);
        return rejectWithValue(errorMessage);
    }
});

export const updateCustomer = createAsyncThunk(
    'customers/updateCustomer',
    async ({ id, formData }: { id: number; formData: FormData }, { rejectWithValue }) => {
        try {
            const response = await api.patch(`/customers/${id}`, formData, {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
            });
            handleToastError(response);
            return response.data;
        } catch (error: any) {
            const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_update_customer_information;
            toast.error(errorMessage);
            return rejectWithValue(errorMessage);
        }
    },
);

export const deleteCustomer = createAsyncThunk('customers/deleteCustomer', async (id: number, { rejectWithValue }) => {
    try {
        await api.delete(`/customers/${id}`);
        // toast.success('Customer deleted successfully');
        return id;
    } catch (error: any) {
        toast.error(error?.response?.data?.message || messages.toasts.error.failed_to_delete_customer);
        return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_delete_customer);
    }
});

export const fetchTags = createAsyncThunk('customers/fetchTags', async (type: string, { rejectWithValue }) => {
    try {
        const response = await api.get(`/customers/tags/${type}`);
        return response;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to fetch tags');
    }
});

export const addPhoneNumbers = createAsyncThunk(
    'customers/addPhoneNumbers',
    async ({ customer_id, formData }: { customer_id: number; formData: FormData }, { rejectWithValue }) => {
        try {
            const response = await api.patch(`/customers/phone-number/${customer_id}`, formData, {
                headers: {
                    'Content-Type': 'application/json',
                },
            });
            handleToastError(response);
            return response.data;
        } catch (error: any) {
            const errorMessage = error?.response?.data?.message || 'Failed to add phone number';
            return rejectWithValue(errorMessage);
        }
    },
);

// Fetch customer ratings
export const getCustomerRatings = createAsyncThunk(
    'customers/getCustomerRatings',
    async (customerId: number, { rejectWithValue }) => {
        try {
            const response = await api.get(`/customers/count/ratings/${customerId}`);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch customer ratings');
        }
    },
);

export const getAllCustomerEpisode = createAsyncThunk(
    'customers/getCustomerEpisode',
    async (customerId: number, { rejectWithValue }) => {
        try {
            const response = await api.get(`customers/${customerId}/episodes`);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch customer ratings');
        }
    },
);

export const createCustomerEpisode = createAsyncThunk(
    'customers/createCustomerEpisode',
    async ({ customerId, payload }: { customerId: number; payload: any }, { rejectWithValue }) => {
        try {
            const response = await api.post(`/customers/${customerId}/episodes`, payload);
            handleToastError(response);
            return response;
        } catch (error: any) {
            const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_create_episode;
            toast.error(errorMessage);
            return rejectWithValue(errorMessage);
        }
    },
);

// export const createCustomerEpisode = createAsyncThunk(
//     'customers/createCustomerEpisode',
//     async ({ customerId, payload }: { customerId: number; payload: any }, { rejectWithValue }) => {
//         try {
//             const response = await api.post(`/customers/${customerId}/episodes`, payload);

//             handleToastError(response);

//             // Extract episode ID safely
//             const episodeId = Number(
//                 response?.data?.data?.episode_id ?? response?.data?.data?.id ?? response?.data?.episode_id ?? response?.data?.id,
//             );

//             if (!episodeId) {
//                 console.error('❌ Episode ID extraction failed:', response);
//                 return rejectWithValue('Invalid episode ID received');
//             }

//             return {
//                 episodeId,
//                 apiResponse: response.data,
//             };
//         } catch (error: any) {
//             const msg = error?.response?.data?.message || 'Failed to create episode';

//             toast.error(msg);
//             return rejectWithValue(msg);
//         }
//     },
// );

export const updateEpisode = createAsyncThunk(
    'customers/updateEpisode',
    async ({ episodeId, payload }: { episodeId: number; payload: any }, { rejectWithValue }) => {
        try {
            const response = await api.patch(`/customers/episodes/${episodeId}`, payload);
            handleToastError(response);
            return response.data;
        } catch (error: any) {
            const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_update_episode;
            toast.error(errorMessage);
            return rejectWithValue(errorMessage);
        }
    },
);

export const getCustomerEpisodeLog = createAsyncThunk(
    'customers/getCustomerEpisodeLog',
    async (episodeId: any, { rejectWithValue }) => {
        try {
            const response = await api.get(`/customers/episodes/${episodeId}/logs`);

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

export const createEpisodeLog = createAsyncThunk(
    'customer/createEpisodeLog',
    async ({ episodeId, payload }: any, { rejectWithValue }) => {
        try {
            const response = await api.post(`/customers/episodes/${episodeId}/logs`, payload);

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

export const fetchEpisodeLogById = createAsyncThunk(
    'customer/fetchEpisodeLogById',
    async (logId: number, { rejectWithValue }) => {
        try {
            const response = await api.get(`/customers/logs/${logId}`);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch episode log');
        }
    },
);

export const updateEpisodeLog = createAsyncThunk(
    'customer/updateEpisodeLog',
    async ({ logId, payload }: { logId: number; payload: FormData }, { rejectWithValue }) => {
        try {
            const response = await api.patch(`/customers/logs/${logId}`, payload);
            handleToastError(response);
            return response.data;
        } catch (error: any) {
            const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_update_episode_log;
            toast.error(errorMessage);
            return rejectWithValue(errorMessage);
        }
    },
);

export const deleteEpisodeLog = createAsyncThunk('customer/deleteEpisodeLog', async (logId: any, { rejectWithValue }) => {
    try {
        const response = await api.delete(`/customers/logs/${logId}`);
        handleToastError(response);
        return response.data;
    } catch (error: any) {
        const errorMessage = error?.response?.data?.message || messages.toasts.error.failed_to_delete_episode_log;
        toast.error(errorMessage);
        return rejectWithValue(errorMessage);
    }
});

export const getCustomerActiveEpisodeLog = createAsyncThunk(
    'customer/activeEpisodeLog',
    async ({ customerId, params }: any, { rejectWithValue }) => {
        try {
            const response = await api.get(`/customers/active/episode/${customerId}`, { params });
            handleToastError(response);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch episode log');
        }
    },
);

export const checkUninvoicedTrips = createAsyncThunk('episode/checkUninvoicedTrips', async (episodeId, { rejectWithValue }) => {
    try {
        const response = await api.get(`/customers/${episodeId}/invoice-status`);
        return response?.data?.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data || 'Something went wrong');
    }
});

// export const uploadCustomersExcel = createAsyncThunk('customers/uploadExcel', async (file: any) => {
//     const formData = new FormData();
//     formData.append('file', file);

//     // const response = await fetch('/api/customers/bulk-upload', {
//     //     method: 'POST',
//     //     body: formData,
//     // });

//     const response: any = await api.post('/customers/bulk-upload', formData, {
//         headers: {
//             'Content-Type': 'multipart/form-data',
//         },
//     });

//     if (!response.ok) throw new Error('Upload failed');
//     return await response.json();
// });

export const uploadCustomersExcel = createAsyncThunk('customers/uploadExcel', async (payload: any, { rejectWithValue }) => {
    try {
        const response = await api.post('/customers/bulk-upload', payload, {
            responseType: 'blob', // VERY IMPORTANT
            headers: {
                'Content-Type': 'multipart/form-data',
            },
        });

        if (response.status === 207) {
            const blob = new Blob([response.data], {
                type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            });

            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `bulk-upload-errors-${Date.now()}.xlsx`;
            a.click();
            window.URL.revokeObjectURL(url);

            return {
                downloaded: true,
                message: 'Error Excel downloaded',
            };
        }

        // CASE 2 → Success JSON response (200)
        const text = await response.data.text();
        const json = JSON.parse(text);
        toast.success(messages.toasts.success.excel_uploaded_successfully);
        return json;
    } catch (error: any) {
        return rejectWithValue(error.message);
    }
});

export const downloadSampleExcel = createAsyncThunk('customers/downloadSample', async () => {
    const a = document.createElement('a');
    a.href = '/sample-customers.xlsx'; // in /public folder
    a.download = 'sample-customers.xlsx';
    a.click();
    return true;
});

const customerSlice = createSlice({
    name: 'customers',
    initialState,
    reducers: {
        setSelectedCustomer: (state, action: PayloadAction<ClientCustomer | null>) => {
            state.selectedCustomer = action.payload;
        },
        updateFilters: (state, action: PayloadAction<Partial<CustomerFilters>>) => {
            state.filters = { ...state.filters, ...action.payload };
        },
        resetFilters: (state) => {
            state.filters = initialState.filters;
        },
        /** Full reset for the customers list route: avoids stale items/filters/detail data when the page loads or the user refreshes. */
        resetCustomersPageState: () => initialState,
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchCustomers.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchCustomers.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = action.payload?.data?.data || [];
                state.totalCount = action.payload?.data?.count || 0;
            })
            .addCase(fetchCustomers.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(fetchCustomerById.pending, (state) => {
                state.status = 'loading';
                state.error = null;
            })
            .addCase(fetchCustomerById.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.selectedCustomer = action.payload || null;
            })
            .addCase(fetchCustomerById.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
            })
            .addCase(createCustomer.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(updateCustomer.fulfilled, (state, action) => {
                state.selectedCustomer = action.payload;
                state.status = 'succeeded';
            })
            .addCase(deleteCustomer.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(getCustomerRatings.pending, (state) => {
                state.customerRatingsStatus = 'loading';
            })
            .addCase(getCustomerRatings.fulfilled, (state, action) => {
                state.customerRatingsStatus = 'succeeded';
                // Extract data from the new API response structure
                state.customerRatings = action.payload?.data;
            })
            .addCase(getCustomerRatings.rejected, (state, action) => {
                state.customerRatingsStatus = 'failed';
                state.customerRatings = null;
            })
            .addCase(getAllCustomerEpisode.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.customerEpisodes = action.payload?.data || null;
            })
            .addCase(createCustomerEpisode.fulfilled, (state, action) => {
                state.status = 'succeeded';
                const newEpisode = action?.payload?.data?.data ?? action?.payload?.data;
                if (newEpisode) {
                    if (Array.isArray(state.customerEpisodes)) {
                        state.customerEpisodes = [...state.customerEpisodes, newEpisode];
                    } else {
                        state.customerEpisodes = [newEpisode];
                    }
                }
                if (action?.payload?.data?.message) {
                    toast.success(action.payload.data.message);
                }
            })
            // .addCase(createCustomerEpisode.fulfilled, (state, action) => {
            //     state.status = 'succeeded';

            //     const episode = action.payload?.apiResponse?.data ?? null;

            //     if (episode) {
            //         if (Array.isArray(state.customerEpisodes)) {
            //             state.customerEpisodes.push(episode);
            //         } else {
            //             state.customerEpisodes = [episode];
            //         }
            //     }

            //     const message = action.payload?.apiResponse?.message;
            //     if (message) toast.success(message);
            // })
            .addCase(getCustomerEpisodeLog.pending, (state, action) => {
                state.status = 'succeeded';
                state.episodeLogs = null;
            })
            .addCase(getCustomerEpisodeLog.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.episodeLogs = action.payload?.data || null;
            })
            .addCase(createEpisodeLog.fulfilled, (state, action) => {
                state.status = 'succeeded';

                if (action?.payload?.data?.code === 200) {
                    toast.success(action?.payload?.data?.message);
                }
            })
            .addCase(fetchEpisodeLogById.fulfilled, (state, action) => {
                state.status = 'succeeded';
            })
            .addCase(updateEpisodeLog.fulfilled, (state, action) => {
                state.status = 'succeeded';
                if (action?.payload?.code === 200) {
                    toast.success(`${action?.payload?.message}`);
                }
            })
            .addCase(deleteEpisodeLog.fulfilled, (state, action) => {
                state.status = 'succeeded';
                if (action?.payload?.code === 200) {
                    toast.success(`${action?.payload?.message}`);
                }
            })
            .addCase(updateEpisode.fulfilled, (state, action) => {
                if (action?.payload?.code === 200) {
                    toast.success(`${action?.payload?.message}`);
                }
            });
    },
});

export const { setSelectedCustomer, updateFilters, resetFilters, resetCustomersPageState } = customerSlice.actions;
export default customerSlice.reducer;
