import axios from 'axios';

let isRefreshing = false;
let failedQueue: Array<{ resolve: (token: string) => void; reject: (error: any) => void }> = [];

const processQueue = (error: any, token: string | null = null) => {
    failedQueue.forEach(prom => {
        if (error) {
            prom.reject(error);
        } else {
            prom.resolve(token!);
        }
    });
    failedQueue = [];
};

const api = axios.create({
    baseURL: '/api',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
    },
});

api.interceptors.request.use((config) => {
    const token = localStorage.getItem('auth_token');
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
});

api.interceptors.response.use(
    (response) => response,
    async (error) => {
        const originalRequest = error.config;

        if (error.response?.status === 401 && !originalRequest._retry && originalRequest.url !== '/refresh-token') {
            if (isRefreshing) {
                return new Promise((resolve, reject) => {
                    failedQueue.push({ resolve, reject });
                }).then(token => {
                    originalRequest.headers.Authorization = `Bearer ${token}`;
                    return api(originalRequest);
                });
            }

            originalRequest._retry = true;
            isRefreshing = true;

            try {
                const res = await api.post('/refresh-token');
                const newToken = res.data.token;
                localStorage.setItem('auth_token', newToken);
                processQueue(null, newToken);
                originalRequest.headers.Authorization = `Bearer ${newToken}`;
                return api(originalRequest);
            } catch (refreshError) {
                processQueue(refreshError, null);
                localStorage.removeItem('auth_token');
                localStorage.removeItem('auth_user');
                window.location.href = '/login';
                return Promise.reject(refreshError);
            } finally {
                isRefreshing = false;
            }
        }

        if (error.response?.status === 401 && originalRequest.url === '/refresh-token') {
            localStorage.removeItem('auth_token');
            localStorage.removeItem('auth_user');
            window.location.href = '/login';
        }

        return Promise.reject(error);
    }
);

export const authApi = {
    login: (email: string, password: string) =>
        api.post('/login', { email, password }),
    logout: () => api.post('/logout'),
    user: () => api.get('/user'),
    updateProfile: (data: Partial<{ name: string; currency: string; timezone: string; auto_backup: boolean }>) =>
        api.put('/user/profile', data),
    changePassword: (current_password: string, password: string, password_confirmation: string) =>
        api.put('/user/password', { current_password, password, password_confirmation }),
    refreshToken: () => api.post('/refresh-token'),
};

export const categoryApi = {
    getAll: () => api.get('/categories'),
    get: (id: number) => api.get(`/categories/${id}`),
    create: (data: { name: string; icon: string; color: string }) =>
        api.post('/categories', data),
    update: (id: number, data: Partial<{ name: string; icon: string; color: string }>) =>
        api.put(`/categories/${id}`, data),
    delete: (id: number) => api.delete(`/categories/${id}`),
};

export const expenseApi = {
    getAll: (params?: {
        category_id?: number;
        payment_method?: string;
        date_from?: string;
        date_to?: string;
        search?: string;
        month?: string;
        page?: number;
        per_page?: number;
    }) => api.get('/expenses', { params }),
    get: (id: number) => api.get(`/expenses/${id}`),
    create: (data: FormData | {
        category_id: number;
        amount: number;
        date: string;
        time?: string;
        note?: string;
        payment_method: string;
        receipt_image?: File;
    }) => {
        if (data instanceof FormData) {
            return api.post('/expenses', data, {
                headers: { 'Content-Type': 'multipart/form-data' },
            });
        }
        return api.post('/expenses', data);
    },
    update: (id: number, data: FormData | Partial<{
        category_id: number;
        amount: number;
        date: string;
        time?: string;
        note?: string;
        payment_method: string;
        receipt_image?: File;
    }>) => {
        if (data instanceof FormData) {
            data.append('_method', 'PUT');
            return api.post(`/expenses/${id}`, data, {
                headers: { 'Content-Type': 'multipart/form-data' },
            });
        }
        return api.put(`/expenses/${id}`, data);
    },
    delete: (id: number) => api.delete(`/expenses/${id}`),
};

export const dashboardApi = {
    stats: () => api.get('/dashboard/stats'),
};

export const budgetApi = {
    getAll: (month?: string) => api.get('/budgets', { params: { month } }),
    get: (id: number) => api.get(`/budgets/${id}`),
    create: (data: { category_id: number; month: string; amount_limit: number }) =>
        api.post('/budgets', data),
    update: (id: number, data: Partial<{ month: string; amount_limit: number }>) =>
        api.put(`/budgets/${id}`, data),
    delete: (id: number) => api.delete(`/budgets/${id}`),
};

export const recurringExpenseApi = {
    getAll: (params?: { page?: number; per_page?: number }) => api.get('/recurring-expenses', { params }),
    get: (id: number) => api.get(`/recurring-expenses/${id}`),
    create: (data: {
        category_id: number;
        amount: number;
        frequency: 'monthly' | 'weekly';
        next_due_date: string;
        note?: string;
    }) => api.post('/recurring-expenses', data),
    update: (id: number, data: Partial<{
        category_id: number;
        amount: number;
        frequency: 'monthly' | 'weekly';
        next_due_date: string;
        note?: string;
        is_active: boolean;
    }>) => api.put(`/recurring-expenses/${id}`, data),
    delete: (id: number) => api.delete(`/recurring-expenses/${id}`),
    markPaid: (id: number) => api.post(`/recurring-expenses/${id}/mark-paid`),
};

export const reportApi = {
    summary: (params: { date_from: string; date_to: string }) =>
        api.get('/reports/summary', { params }),
    exportCsv: (params: { date_from: string; date_to: string }) =>
        api.get('/reports/export-csv', { params, responseType: 'blob' }),
    exportPdf: (params: { date_from: string; date_to: string }) =>
        api.get('/reports/export-pdf', { params, responseType: 'blob' }),
};

export const backupApi = {
    run: () => api.post('/backup/run'),
    status: () => api.get('/backup/status'),
    download: () => api.get('/backup/download', { responseType: 'blob' }),
};

export const exportApi = {
    expenses: () => api.get('/export/expenses', { responseType: 'blob' }),
};

export const userApi = {
    getAll: () => api.get('/users'),
    create: (data: { name: string; email: string; password: string }) =>
        api.post('/users', data),
    delete: (id: number) => api.delete(`/users/${id}`),
};

export default api;
