import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import { ElMessage as Message, ElMessageBox as MessageBox, ElLoading as Loading } from 'element-plus';
import  tokenInfo  from '@/stores/modules/token';
import useUserInfo from "@/stores/modules/user";
import pinia from "@/stores/index";
import ENV_CONFIG from "@/config.json";
import client from '@/stores/modules/client';

// 加载动画的并发管理
const activeRequests = new Set<string>();
let loadingObj = null;
/**
 * 关闭加载动画
 * 当所有请求完成时，关闭加载动画
 */
function loadingClose(requestId: string) {
    activeRequests.delete(requestId);
    if (activeRequests.size === 0 && loadingObj) {
        loadingObj.close();
        loadingObj = null
    }
}

/**
 * 处理token失效
 * 关闭所有子窗口，清空用户信息，跳转到首页
 */
async function handleTokenExpiry() {
    try {
        // 关闭所有子窗口
        try {
            const clientStore = client();
            await clientStore.ipc.invoke('controller.utils.closeAllWindows');
            console.log('Token失效：所有子窗口已关闭');
        } catch (error) {
            console.error('Token失效：关闭子窗口失败:', error);
        }

        // 清空用户信息
        const useUserInfoStore = useUserInfo();
        try {
            const tokenStore = tokenInfo();
            tokenStore.clearToken();
        } catch (e) {
            await useUserInfoStore.updateToken('');
        }
        await useUserInfoStore.updateUserInfo({});

        // 跳转到首页（在会话存储中标记需要显示登录框）
        try {
            sessionStorage.setItem('NEED_LOGIN_MODAL', '1');
            // 在Electron环境中使用正确的协议
            if (window.location.protocol === 'file:') {
                window.location.href = window.location.href.split('#')[0] + '#/';
                window.location.reload()
            } else {
                window.location.href = '/';
            }
            console.log('Token失效：已跳转到首页');
        } catch (error) {
            console.error('Token失效：跳转到首页失败:', error);
        }
        // 刷新后在 main.ts 中处理显示登录弹窗
    } catch (error) {
        console.error('Token失效处理失败:', error);
    }
}

/**
 * 创建一个axios实例，用于发送HTTP请求
 * 配置了请求拦截器和响应拦截器，支持加载动画和错误提示
 */
const service = axios.create({
    timeout: 10000, // 设置请求超时时间
   // baseURL: '__API__',
});
console.log('__API__');

// 请求拦截器
service.interceptors.request.use(
    (config: AxiosRequestConfig) => {

        // 动态设置baseURL
        const appConfig = pinia.state.value.config?.appConfig;
        let env = appConfig?.env || 'prod'; // 默认环境
        if (env) {
            // 从ENV_CONFIG获取对应环境的API地址
            const apiConfig = ENV_CONFIG[env];
            if (apiConfig?.api) {
                config.baseURL = apiConfig.api;
            }
        }
        console.log(`使用环境: ${env}, API地址: ${config.baseURL || '__API__'}`);

        // 在发送请求之前做些什么，例如添加 token
        const tokenInfoStore = tokenInfo();
        const token = tokenInfoStore.getToken; // computed ref
        const tokenValue = typeof token === 'object' && token !== null && 'value' in token ? (token as any).value : token as any;
        if (tokenValue) {
            config.headers['Authorization'] = `Bearer ${tokenValue}`;
        }

        // 如果配置中启用了加载动画，则显示加载动画
        if (config.loading) {
            const requestId = `${Date.now()}-${Math.random()}`;
            activeRequests.add(requestId);
            if (activeRequests.size === 1) {
                loadingObj = Loading.service({
                    lock: true,
                    text: '请稍候',
                    background: 'rgba(0, 0, 0, 0)',
                });
            }
            config.requestId = requestId; // 将 requestId 挂载到 config 上
        }

        return config;
    },
    (error: AxiosError) => {
        // 对请求错误做些什么
        return Promise.reject(error);
    }
);

// 响应拦截器
service.interceptors.response.use(
    (response: AxiosResponse) => {
        // 对响应数据做点什么
        const res = response.data;
        const useUserInfoStore = useUserInfo();

        // 如果配置中启用了加载动画，则关闭加载动画
        if (response.config?.loading && response.config.requestId) {
            loadingClose(response.config.requestId as string);
        }

        // 如果自定义状态码不为0，则判断为错误
        if (res.code !== 0) {
            switch (res.code) {
                case 401:
                    setTimeout(()=>{

                        Message({
                            message: '登录状态已失效，请重新登录',
                            type: 'error',
                            duration: 3 * 1000,
                        });
                    },1000)
                    // 处理token失效
                    handleTokenExpiry();
                    break;
                default:
                    if (response.config.showErrorMessage) {
                        if (res.message?.length > 30 || res.code === 400011) {
                            let message = '<div style="white-space: pre-line; max-height: 500px; overflow: auto;">' + res.message + '</div>' || 'Error';
                            MessageBox.alert(message, '提示', {
                                dangerouslyUseHTMLString: true,
                            });
                        } else {
                            Message({
                                message: res.message || 'Error',
                                type: 'error',
                                duration: 5 * 1000,
                            });
                        }
                    }
                    break;
            }

            return Promise.reject(res || 'Error');
        } else {
            return res;
        }
    },
    (error: AxiosError) => {
        // 对响应错误做点什么
        let errMessage = '';

        // 如果配置中启用了加载动画，则关闭加载动画
        if (error.config?.loading && error.config.requestId) {
            loadingClose(error.config.requestId as string);
        }

        const useUserInfoStore = useUserInfo();
        try {
            if (error.response) {
                switch (error.response.status) {
                    case 400: errMessage = '请求错误(400)'; break;
                    case 401: errMessage = '登录状态已失效，请重新登录';
                    // 处理token失效
                    handleTokenExpiry();
                     break;
                    case 403: errMessage = '拒绝访问(403)'; break;
                    case 404: errMessage = '请求出错(404)'; break;
                    case 408: errMessage = '请求超时(408)'; break;
                    case 500: errMessage = '服务器错误(500)'; break;
                    case 501: errMessage = '服务未实现(501)'; break;
                    case 502: errMessage = '网络错误(502)'; break;
                    case 503: errMessage = '服务不可用(503)'; break;
                    case 504: errMessage = '网络超时(504)'; break;
                    case 505: errMessage = 'HTTP版本不受支持(505)'; break;
                    default: errMessage = '连接出错!';
                }
            } else {
                errMessage = '未知错误';
            }
        } catch (e) {
            console.log(e);
        }

        // 如果配置中启用了错误提示，则显示错误信息
        if (error.config?.showErrorMessage) {
            if (error.message && error.message.includes('timeout')) {
                Message({
                    message: '请求超时！',
                    type: 'error',
                    duration: 5 * 1000,
                });
            } else if (errMessage) {
                Message({
                    message: errMessage,
                    type: 'error',
                    duration: 5 * 1000,
                });
            }
        }

        // 对响应错误做处理
        return Promise.reject(error);
    }
);


/**
 * 发起 GET 请求
 *
 * @template T 泛型，表示返回数据的类型
 * @param {string} url 请求的 URL
 * @param {any} [data] 请求参数
 * @param {any} [config] 请求配置
 * @returns {Promise<T>} 返回一个 Promise，解析为响应数据
 */
export function GET<T>(url: string, data?: any, config?: any): Promise<T> {
    return service.get(url, {
        params: data,
        loading: config?.loading ?? false,
        showErrorMessage: config?.showErrorMessage ?? true,
    });
}

/**
 * 发起 POST 请求
 *
 * @template T 泛型，表示返回数据的类型
 * @param {string} url 请求的 URL
 * @param {any} [data] 请求体
 * @param {any} [config] 请求配置
 * @returns {Promise<T>} 返回一个 Promise，解析为响应数据
 */
export function POST<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return service.post(url, data, {
        ...config,
        loading: config?.loading ?? true,
        showErrorMessage: config?.showErrorMessage ?? true,
    });
}


// 导出配置好的 axios 实例
export default service;
