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';

// PaymentPlan Type
export interface PaymentPlan {
    id?: number;
    name: string;
    description?: string;
    is_default?: boolean;
    status?: 'active' | 'inactive';
    created_at?: string;
    updated_at?: string;
}

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

const initialState: PaymentPlansState = {
    items: [],
    status: 'idle',
    error: null,
    filters: {
        search: '',
        sortBy: '',
        sortOrder: 'ASC',
    },
    totalCount: 0,
};

// ─── Async Thunks ────────────────────────────────

// Fetch all plans
export const fetchPaymentPlans = createAsyncThunk(
    'paymentPlans/fetchAll',
    async (
        params: {
            search?: string;
            sortBy?: string;
            sortOrder?: 'ASC' | 'DESC';
        },
        { rejectWithValue },
    ) => {
        try {
            const response = await api.get('/plans', {
                params: {
                    search: params?.search || '',
                    sortBy: params?.sortBy,
                    sortOrder: params?.sortOrder,
                },
            });
            return response;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_fetch_payment_plans);
        }
    },
);

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

// Add
export const addPaymentPlan = createAsyncThunk('paymentPlans/add', async (plan: PaymentPlan, { rejectWithValue }) => {
    try {
        const response = await api.post('/plans', plan);
        handleToastError(response);
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_add_payment_plan);
    }
});

// Update
export const updatePaymentPlan = createAsyncThunk(
    'paymentPlans/update',
    async ({ id, updates }: { id: number; updates: Partial<PaymentPlan> }, { rejectWithValue }) => {
        try {
            const response = await api.patch(`/plans/${id}`, updates);
            handleToastError(response);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || messages.toasts.error.failed_to_update_payment_plan);
        }
    },
);

// Delete
export const deletePaymentPlan = createAsyncThunk('paymentPlans/delete', async (id: number, { rejectWithValue }) => {
    try {
        const response = await api.delete(`/plans/${id}`);
        const data = response?.data;

        if (data?.success) {
            return { id, success: true, message: data?.message } as { id: number; success: true; message?: string };
        }

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

// ─── Slice ────────────────────────────────
const paymentPlansSlice = createSlice({
    name: 'paymentPlans',
    initialState,
    reducers: {
        clearPaymentPlans: (state) => {
            state.items = [];
            state.status = 'idle';
            state.error = null;
        },
        updateFilters: (state, action: PayloadAction<Partial<PaymentPlansState['filters']>>) => {
            state.filters = { ...state.filters, ...action.payload };
        },
        resetFilters: (state) => {
            state.filters = initialState.filters;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchPaymentPlans.pending, (state) => {
                state.status = 'loading';
            })
            .addCase(fetchPaymentPlans.fulfilled, (state, action) => {
                state.status = 'succeeded';
                state.items = action.payload.data.data;
                state.totalCount = action.payload.count;
            })
            .addCase(fetchPaymentPlans.rejected, (state, action) => {
                state.status = 'failed';
                state.error = action.payload as string;
                toast.error((action.payload as string) || messages.toasts.error.failed_to_fetch_payment_plans);
            })
            .addCase(addPaymentPlan.fulfilled, (state, action: PayloadAction<PaymentPlan>) => {
                state.items.push(action.payload);
            })
            .addCase(addPaymentPlan.rejected, (_, action) => {
                toast.error((action.payload as string) || messages.toasts.error.failed_to_add_payment_plan);
            })
            .addCase(updatePaymentPlan.fulfilled, (state, action: PayloadAction<PaymentPlan>) => {
                state.items = state.items.map((plan) => (plan.id === action.payload.id ? { ...plan, ...action.payload } : plan));
            })
            .addCase(updatePaymentPlan.rejected, (_, action) => {
                toast.error((action.payload as string) || messages.toasts.error.failed_to_update_payment_plan);
            })
            .addCase(
                deletePaymentPlan.fulfilled,
                (state, action: PayloadAction<{ id: number; success: true; message?: string }>) => {
                    state.status = 'succeeded';
                    toast.success(action.payload?.message || messages.toasts.success.payment_plan_deleted);
                },
            )
            .addCase(deletePaymentPlan.rejected, (_, action) => {
                toast.error((action.payload as string) || messages.toasts.error.failed_to_delete_payment_plan);
            });
    },
});

export const { clearPaymentPlans, updateFilters, resetFilters } = paymentPlansSlice.actions;
export default paymentPlansSlice.reducer;
