import request from '@/utils/request';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

// 定义通用的响应接口
export interface ApiResponse<T = any> {
    code: number;
    data: T;
    msg?: string;
    message?: string;
}

// 定义请求配置接口
export interface RequestConfig extends AxiosRequestConfig {
    // 是否显示loading
    loading?: boolean;
    // 是否显示错误信息
    showError?: boolean;
    // 自定义错误处理
    errorHandler?: (error: any) => void;
}

/**
 * GET请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 * @returns Promise<T>
 */
export const get = <T = any>(url: string, params?: Record<string, any>, config?: RequestConfig): Promise<ApiResponse<T>> => {
    return request.get(url, {
        params,
        ...config
    });
};

/**
 * POST请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<T>
 */
export const post = <T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> => {
    return request.post(url, data, config);
};

/**
 * PUT请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<T>
 */
export const put = <T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> => {
    return request.put(url, data, config);
};

/**
 * DELETE请求
 * @param url 请求地址
 * @param config 请求配置
 * @returns Promise<T>
 */
export const del = <T = any>(url: string, config?: RequestConfig): Promise<ApiResponse<T>> => {
    return request.delete(url, config);
};

/**
 * PATCH请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<T>
 */
export const patch = <T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> => {
    return request.patch(url, data, config);
};

/**
 * 上传文件
 * @param url 请求地址
 * @param formData 表单数据
 * @param config 请求配置
 * @returns Promise<T>
 */
export const upload = <T = any>(url: string, formData: FormData, config?: RequestConfig): Promise<ApiResponse<T>> => {
    return request.post(url, formData, {
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        ...config
    });
};

/**
 * 下载文件
 * @param url 请求地址
 * @param params 请求参数
 * @param filename 文件名
 * @param config 请求配置
 * @returns Promise<Blob>
 */
export const download = (url: string, params?: Record<string, any>, filename?: string, config?: RequestConfig): Promise<Blob> => {
    return request
        .get(url, {
            params,
            responseType: 'blob',
            ...config
        })
        .then((response: any) => {
            // 创建下载链接
            const blob = new Blob([response]);
            const downloadUrl = window.URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = downloadUrl;
            link.download = filename || 'download';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            window.URL.revokeObjectURL(downloadUrl);
            return blob;
        });
};

/**
 * 请求拦截器辅助方法
 * @param config 请求配置
 * @returns 处理后的配置
 */
export const requestInterceptor = (config: RequestConfig) => {
    // 可以在这里添加通用的请求处理逻辑
    // 比如添加loading、token等
    return config;
};

/**
 * 响应拦截器辅助方法
 * @param response 响应数据
 * @returns 处理后的响应
 */
export const responseInterceptor = <T = any>(response: AxiosResponse<ApiResponse<T>>) => {
    // 可以在这里添加通用的响应处理逻辑
    // 比如统一的错误处理、数据格式化等
    return response.data;
};

/**
 * 并发请求
 * @param requests 请求数组
 * @returns Promise<T[]>
 */
export const concurrent = <T = any>(requests: Array<Promise<any>>): Promise<T[]> => {
    return Promise.allSettled(requests).then((results) => {
        return results
            .map((result) => {
                if (result.status === 'fulfilled') {
                    return result.value;
                } else {
                    console.error('Request failed:', result.reason);
                    return null;
                }
            })
            .filter(Boolean);
    });
};

/**
 * 重试请求
 * @param requestFn 请求函数
 * @param maxRetries 最大重试次数
 * @param delay 重试延迟(毫秒)
 * @returns Promise<T>
 */
export const retry = <T = any>(requestFn: () => Promise<T>, maxRetries: number = 3, delay: number = 1000): Promise<T> => {
    return requestFn().catch((error) => {
        if (maxRetries > 0) {
            return new Promise((resolve) => {
                setTimeout(() => {
                    resolve(retry(requestFn, maxRetries - 1, delay));
                }, delay);
            });
        } else {
            throw error;
        }
    });
};

// 导出默认的request实例，以便直接使用
export { request as default };

// 导出所有方法
export const httpRequests = {
    get,
    post,
    put,
    delete: del,
    patch,
    upload,
    download,
    concurrent,
    retry,
    request
};
