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

export interface InvoiceItem {
    id: number;
    invoice_type: string;
    start_date: string;
    end_date: string;
    due_date: string;
    discount: number;
    status: string;
    created_at: string;
    client_company: {
        id: number;
        company_name: string;
    };
    customer: {
        id: number;
        customer_name: string;
    };
}

interface CreateInvoicesPayload {
    isDirectCustomer: boolean;
    clientId: number;
    startDate: string;
    endDate: string;
    invoiceType: 'one_customer' | 'all_customers';
    latestEpisodeOnly: boolean;
    customerId?: number | null;
    dueDate: string;
    cityId?: number | null;
    discount?: number;
    notes?: string;
    invoice_tax?: number;
}

interface GetInvoicesParams {
    limit?: number;
    skip?: number;
    search?: string;
    client_company_id?: number;
    customer_id?: number;
    status?: string;
    is_export?: boolean;
}

interface InvoicesState {
    items: InvoiceItem[];
    status: 'idle' | 'loading' | 'succeeded' | 'failed';
    error: string | null;
    totalCount: number;
    currentPage: number;
    isLoading: boolean;
}

const initialState: InvoicesState = {
    items: [],
    status: 'idle',
    error: null,
    totalCount: 0,
    currentPage: 1,
    isLoading: false,
};

export const createInvoices = createAsyncThunk<any, CreateInvoicesPayload>(
    'invoices/createInvoices',
    async (payload, { rejectWithValue }) => {
        try {
            // Transform the payload to match API expectations
            const apiPayload: Record<string, unknown> = {
                is_direct_customer: payload?.isDirectCustomer,
                client_id: payload.clientId,
                start_date: payload.startDate,
                end_date: payload.endDate,
                invoice_type: payload.invoiceType === 'all_customers' ? 'all' : 'single',
                latest_episode_only: payload.latestEpisodeOnly,
                customer_id: payload.customerId,
                due_date: payload.dueDate,
                discount: payload.discount || 0,
                notes: payload.notes || '',
                status: 'unpaid',
                invoice_tax: payload.invoice_tax || 0,
            };
            if (payload.cityId != null) {
                apiPayload.city_id = payload.cityId;
            }

            const response = await api.post('/invoices', apiPayload);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to create invoices');
        }
    },
);

export const getInvoices = createAsyncThunk<any, GetInvoicesParams>(
    'invoices/getInvoices',
    async (params, { rejectWithValue }) => {
        try {
            const queryParams = new URLSearchParams();

            if (params.limit) queryParams.append('limit', params.limit.toString());
            if (params.skip) queryParams.append('skip', params.skip.toString());
            if (params.search) queryParams.append('search', params.search);
            if (params.client_company_id) queryParams.append('client_company_id', params.client_company_id.toString());
            if (params.customer_id) queryParams.append('customer_id', params.customer_id.toString());
            if (params.status) queryParams.append('status', params.status);
            if (params.is_export !== undefined) queryParams.append('is_export', params.is_export.toString());

            const response = await api.get(`/invoices?${queryParams.toString()}`);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to fetch invoices');
        }
    },
);

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

export const updateInvoice = createAsyncThunk<any, { id: number; payload: CreateInvoicesPayload }>(
    'invoices/updateInvoice',
    async ({ id, payload }, { rejectWithValue }) => {
        try {
            // Transform the payload to match API expectations (same as create)
            const apiPayload: Record<string, unknown> = {
                is_direct_customer: payload?.is_direct_customer,
                client_id: payload.clientId,
                start_date: payload.startDate,
                end_date: payload.endDate,
                invoice_type: payload.invoiceType === 'all_customers' ? 'all' : 'single',
                latest_episode_only: payload.latestEpisodeOnly,
                customer_id: payload.customerId,
                due_date: payload.dueDate,
                discount: payload.discount || 0,
                notes: payload.notes || '',
                status: 'unpaid',
            };
            if (payload.cityId != null) {
                apiPayload.city_id = payload.cityId;
            }

            const response = await api.patch(`/invoices/${id}`, apiPayload);
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to update invoice');
        }
    },
);

export const exportInvoices = createAsyncThunk<any, GetInvoicesParams>(
    'invoices/exportInvoices',
    async (params, { rejectWithValue }) => {
        try {
            const response = await api.get('/invoices/excel/export', {
                params,
                responseType: 'blob',
            });
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to export invoices');
        }
    },
);

export const deleteInvoice = createAsyncThunk<any, number>('invoices/deleteInvoice', async (id, { rejectWithValue }) => {
    try {
        const response = await api.delete(`/invoices/${id}`);
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to delete invoice');
    }
});

export const bulkDownloadInvoices = createAsyncThunk<any, { invoice_ids: number[] }>(
    'invoices/bulkDownload',
    async (payload, { rejectWithValue }) => {
        try {
            const response = await api.post('/invoices/bulk-download', payload, {
                responseType: 'blob',
            });
            return response.data;
        } catch (error: any) {
            return rejectWithValue(error?.response?.data?.message || 'Failed to download invoices');
        }
    },
);

export const downloadInvoicePdf = createAsyncThunk<any, any>('invoices/download', async (payload, { rejectWithValue }) => {
    try {
        const response = await api.post(`/invoices/download`, payload, {
            responseType: 'blob', // ✅ VERY IMPORTANT
        });
        return response.data;
    } catch (error: any) {
        return rejectWithValue(error?.response?.data?.message || 'Failed to download invoice');
    }
});

// export const printInvoice = createAsyncThunk('invoice/printInvoice', async (payload, { rejectWithValue }) => {
//     try {
//         const url = '/invoices/print';

//         const response = await api.post(url, payload, {
//             responseType: 'blob', // Axios will return Blob directly
//         });

//         const pdfBlob = response.data;
//         const pdfUrl = URL.createObjectURL(pdfBlob);

//         const iframe = document.createElement('iframe');
//         iframe.style.display = 'none';
//         iframe.src = pdfUrl;
//         document.body.appendChild(iframe);
//         console.log('202 ---------------', 202);
//         iframe.onload = () => {
//             iframe.contentWindow.print();
//         };
//         console.log('206 ---------------', 206);
//         return true;
//     } catch (error) {
//         console.error(error);
//         return rejectWithValue('Failed to print invoice');
//     }
// });

export const printInvoice = createAsyncThunk('invoice/printInvoice', async (payload, { rejectWithValue }) => {
    try {
        const response = await api.post('/invoices/print', payload, {
            responseType: 'blob',
        });

        const pdfBlob = new Blob([response.data], { type: 'application/pdf' });
        const pdfUrl = URL.createObjectURL(pdfBlob);

        const iframe = document.createElement('iframe');
        iframe.style.position = 'fixed';
        iframe.style.top = '-9999px'; // hidden but active in layout
        iframe.src = pdfUrl;
        document.body.appendChild(iframe);

        iframe.onload = () => {
            setTimeout(() => {
                iframe.contentWindow?.focus();
                iframe.contentWindow?.print();
                // optional: URL.revokeObjectURL(pdfUrl); // free memory
            }, 250);
        };

        return true;
    } catch (error) {
        console.error(error);
        return rejectWithValue('Failed to print invoice');
    }
});

const invoicesSlice = createSlice({
    name: 'invoices',
    initialState,
    reducers: {
        resetInvoices(state) {
            state.items = [];
            state.status = 'idle';
            state.error = null;
            state.totalCount = 0;
            state.currentPage = 1;
            state.isLoading = false;
        },
        setCurrentPage(state, action: PayloadAction<number>) {
            state.currentPage = action.payload;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(createInvoices.pending, (state) => {
                state.status = 'loading';
                state.error = null;
            })
            .addCase(createInvoices.fulfilled, (state, action: PayloadAction<any>) => {
                state.status = 'succeeded';
                if (Array.isArray(action.payload?.data)) {
                    state.items = action.payload.data as InvoiceItem[];
                }
            })
            .addCase(createInvoices.rejected, (state, action) => {
                state.status = 'failed';
                state.error = (action.payload as string) || 'Unknown error';
            })
            .addCase(getInvoices.pending, (state) => {
                state.isLoading = true;
                state.error = null;
            })
            .addCase(getInvoices.fulfilled, (state, action: PayloadAction<any>) => {
                state.isLoading = false;
                state.status = 'succeeded';
                if (Array.isArray(action.payload?.data?.data)) {
                    state.items = action.payload.data.data as InvoiceItem[];
                }
                if (action.payload?.data?.count !== undefined) {
                    state.totalCount = action.payload.data.count;
                }
            })
            .addCase(getInvoices.rejected, (state, action) => {
                state.isLoading = false;
                state.status = 'failed';
                state.error = (action.payload as string) || 'Unknown error';
            })
            .addCase(getInvoiceById.pending, (state) => {
                state.isLoading = true;
                state.error = null;
            })
            .addCase(getInvoiceById.fulfilled, (state, action: PayloadAction<any>) => {
                state.isLoading = false;
                state.status = 'succeeded';
            })
            .addCase(getInvoiceById.rejected, (state, action) => {
                state.isLoading = false;
                state.status = 'failed';
                state.error = (action.payload as string) || 'Unknown error';
            })
            .addCase(updateInvoice.pending, (state) => {
                state.isLoading = true;
                state.error = null;
            })
            .addCase(updateInvoice.fulfilled, (state, action: PayloadAction<any>) => {
                state.isLoading = false;
                state.status = 'succeeded';
            })
            .addCase(updateInvoice.rejected, (state, action) => {
                state.isLoading = false;
                state.status = 'failed';
                state.error = (action.payload as string) || 'Unknown error';
            })
            .addCase(exportInvoices.pending, (state) => {
                state.isLoading = true;
                state.error = null;
            })
            .addCase(exportInvoices.fulfilled, (state, action: PayloadAction<any>) => {
                state.isLoading = false;
                state.status = 'succeeded';
                // Export doesn't update the items, just handles the download
            })
            .addCase(exportInvoices.rejected, (state, action) => {
                state.isLoading = false;
                state.status = 'failed';
                state.error = (action.payload as string) || 'Failed to export invoices';
            })
            .addCase(deleteInvoice.pending, (state) => {
                state.isLoading = true;
                state.error = null;
            })
            .addCase(deleteInvoice.fulfilled, (state, action) => {
                state.isLoading = false;
                state.status = 'succeeded';

                if (action?.payload?.code === 200) {
                    toast.success(action?.payload?.message || 'Invoice removed successfully');
                } else {
                    toast.error(action?.payload?.message || 'Failed to generate invoice');
                }
            })
            .addCase(deleteInvoice.rejected, (state, action) => {
                state.isLoading = false;
                state.status = 'failed';
                state.error = (action.payload as string) || 'Failed to delete invoice';
            })
            .addCase(downloadInvoicePdf.fulfilled, (state, action) => {
                const blob = new Blob([action.payload], { type: 'application/pdf' });
                const url = window.URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', action.meta.arg.invoiceNumber); // filename
                document.body.appendChild(link);
                link.click();
                link.remove();
            })
            .addCase(printInvoice.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(printInvoice.fulfilled, (state) => {
                state.isLoading = false;
            })
            .addCase(printInvoice.rejected, (state, action) => {
                state.isLoading = false;
                state.error = action.payload as string;
            })
            .addCase(bulkDownloadInvoices.pending, (state) => {
                state.isLoading = true;
                state.error = null;
            })
            .addCase(bulkDownloadInvoices.fulfilled, (state) => {
                state.isLoading = false;
                state.status = 'succeeded';
            })
            .addCase(bulkDownloadInvoices.rejected, (state, action) => {
                state.isLoading = false;
                state.status = 'failed';
                state.error = (action.payload as string) || 'Failed to download invoices';
            });
    },
});

export const { resetInvoices, setCurrentPage } = invoicesSlice.actions;
export default invoicesSlice.reducer;
