import api from '@/lib/axios';
import { createAsyncThunk, createSlice, type PayloadAction } from '@reduxjs/toolkit';
import { toast } from 'sonner';

// Define types based on your API response
export interface ChargeType {
    id: number;
    name: string;
    description?: string | null;
    unit_of_measure: string; // Changed to match API response
}

interface ChargeTypesState {
    items: ChargeType[];
    status: 'idle' | 'loading' | 'succeeded' | 'failed';
    error: string | null;
    filters: {
        search: string;
        sortBy?: string;
        sortOrder?: 'ASC' | 'DESC';
    };
    totalCount: number;
}

// Initial state
const initialState: ChargeTypesState = {
    items: [],
    status: 'idle',
    error: null,
    filters: {
        search: '',
        sortBy: '',
        sortOrder: 'DESC',
    },
    totalCount: 0,
};

// Async thunks for API calls
export const fetchChargeTypes = createAsyncThunk(
    'chargeTypes/fetchChargeTypes',
    async (params: { skip?: number; limit?: number; search?: string; sortBy?: string; sortOrder?: 'ASC' | 'DESC' }) => {
        try {
            const response = await api.get(`/charge-types`, {
                params: {
                    skip: params.skip || 0,
                    limit: params.limit || 10,
                    search: params.search || '',
                    sortBy: params.sortBy,
                    sortOrder: params.sortOrder,
                },
            });
            return response.data;
        } catch (error: any) {
            throw error.response?.data?.message || 'Failed to fetch charge types';
        }
    },
);

export const addChargeType = createAsyncThunk(
    'chargeTypes/addChargeType',
    async (data: { name: string; description?: string; unit_of_measure: string }) => {
        try {
            const response = await api.post(`/charge-types`, data);
            return response.data;
        } catch (error: any) {
            throw error.response?.data?.message || 'Failed to add charge type';
        }
    },
);

export const updateChargeType = createAsyncThunk(
    'chargeTypes/updateChargeType',
    async ({ id, data }: { id: number; data: { name: string; description?: string; unit_of_measure: string } }) => {
        try {
            const response = await api.patch(`/charge-types/${id}`, data);
            return response.data;
        } catch (error: any) {
            throw error.response?.data?.message || 'Failed to update charge type';
        }
    },
);

export const deleteChargeType = createAsyncThunk('chargeTypes/deleteChargeType', async (id: number) => {
    try {
        const response = await api.delete(`/charge-types/${id}`);
        return response.data;
    } catch (error: any) {
        throw error.response?.data?.message || 'Failed to delete charge type';
    }
});

export const fetchChargeTypeDetails = createAsyncThunk('chargeTypes/fetchDetails', async (id: number) => {
    try {
        const response = await api.get(`/charge-types/${id}`);
        return response.data;
    } catch (error: any) {
        throw error.response?.data?.message || 'Failed to fetch charge type details';
    }
});

// Create the slice
const chargeTypesSlice = createSlice({
    name: 'chargeTypes',
    initialState,
    reducers: {
        updateFilters: (state, action: PayloadAction<Partial<ChargeTypesState['filters']>>) => {
            state.filters = { ...state.filters, ...action.payload };
        },
        resetFilters: (state) => {
            state.filters = initialState.filters;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchChargeTypes.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchChargeTypes.fulfilled, (state, action) => {
                state.status = 'succeeded';
                if (action.payload.success && action.payload.code === 200) {
                    state.items = action.payload.data.data; // Extract data.data array
                    state.totalCount = action.payload.data.count; // Extract count
                } else {
                    state.error = action.payload.message || 'Failed to fetch charge types';
                    toast.error(action.payload.message || 'Failed to fetch charge types');
                }
            })
            .addCase(fetchChargeTypes.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.error.message || 'Failed to fetch charge types';
                toast.error(action.error.message || 'Failed to fetch charge types');
            })
            .addCase(addChargeType.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(addChargeType.fulfilled, (state, action) => {
                if (action.payload.success && action.payload.code === 200) {
                    toast.success(action.payload.message || 'Charge type added successfully');
                } else if (action.payload.code === 422) {
                    toast.error('Charge type already exists');
                } else {
                    toast.error(action.payload.message || 'Something went wrong');
                }
            })
            .addCase(addChargeType.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.error.message || 'Failed to add charge type';
                toast.error(action.error.message || 'Failed to add charge type');
            })
            .addCase(updateChargeType.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(updateChargeType.fulfilled, (state, action) => {
                if (action.payload.success && action.payload.code === 200) {
                    toast.success(action.payload.message || 'Charge type updated successfully');
                } else if (action.payload.code === 422) {
                    toast.error('Charge type already exists');
                } else {
                    toast.error(action.payload.message || 'Something went wrong');
                }
            })
            .addCase(updateChargeType.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.error.message || 'Failed to update charge type';
                toast.error(action.error.message || 'Failed to update charge type');
            })
            .addCase(deleteChargeType.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(deleteChargeType.fulfilled, (state, action) => {
                if (action.payload.success && action.payload.code === 200) {
                    toast.success(action.payload.message || 'Charge type deleted successfully');
                } else {
                    toast.error(action.payload.message || 'Something went wrong');
                }
            })
            .addCase(deleteChargeType.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.error.message || 'Failed to delete charge type';
                toast.error(action.error.message || 'Failed to delete charge type');
            })
            .addCase(fetchChargeTypeDetails.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchChargeTypeDetails.fulfilled, (state, action) => {
                state.status = 'succeeded';
                if (!action.payload.success || action.payload.code !== 200) {
                    toast.error(action.payload.message || 'Failed to fetch charge type details');
                }
            })
            .addCase(fetchChargeTypeDetails.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.error.message || 'Failed to fetch charge type details';
                toast.error(action.error.message || 'Failed to fetch charge type details');
            });
    },
});

export const { updateFilters, resetFilters } = chargeTypesSlice.actions;

export default chargeTypesSlice.reducer;
