import axios, { type AxiosRequestConfig } from 'axios'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { ElMessage } from 'element-plus'
import router from '@/router'
import { getToken, removeToken } from '@/utils/cookie'
import { saveAs } from 'file-saver'

const instance = axios.create({
    baseURL: window.config.API_BASE_URL,
    timeout: 60 * 1000,
    headers: {
        'Content-Type': 'application/json;charset=utf-8'
    }
})

// 请求拦截器
instance.interceptors.request.use(
    (config) => {
        NProgress.start()
        config.headers['Cross-Origin-Embedder-Policy'] = 'require-corp'
        config.headers['Cross-Origin-Opener-Policy'] = 'same-origin'
        config.headers['Accept-Language'] = 'zh-CN'
        const token = getToken()
        if (token) {
            config.headers.Authorization = `Bearer ${token}`
        }
        return config
    },
    (error) => {
        NProgress.done()
        ElMessage({
            message: error || '请求失败！',
            type: 'warning',
            plain: true
        })
        return Promise.reject(error)
    }
)

// 响应拦截器
instance.interceptors.response.use(
    (response) => {
        NProgress.done()
        const { status } = response
        const { message } = response.data
        if (status === 200) {
            // 处理附件下载
            if (response.headers?.['content-disposition']?.startsWith('attachment;')) {
                const blob = new Blob([response.data])
                const fileName = decodeURIComponent(
                    response.headers['content-disposition'].split(';')[1].split('filename=')[1]
                )
                saveAs(blob, fileName)
            }

            return response
        } else {
            ElMessage({
                message: message || '请求失败！',
                type: 'warning',
                plain: true
            })
            return Promise.reject(new Error(message || '请求失败！'))
        }
    },
    (error) => {
        NProgress.done()
        const { response } = error
        const status = response?.status
        if (status) {
            if (status === 401) {
                removeToken()
                router.push('/login')
            }

            if (status == 500) {
                ElMessage({
                    message: response.data.message || '请求失败',
                    type: 'error',
                    plain: true
                })
                return Promise.reject(new Error(`请求失败，状态码：${status}`))
            }
        } else {
            ElMessage({
                message: error.message || '请求失败！',
                type: 'warning',
                plain: true
            })
            return Promise.reject(error)
        }
    }
)

/**
 * axios请求
 * @param url 请求地址
 * @param method {METHOD} http method
 * @param params 请求参数
 * @returns {Promise<AxiosResponse<T>>}
 */

export default {
    request(queryData: AxiosRequestConfig) {
        const { url, data, method, params, headers, responseType, timeout } = queryData
        return instance({
            url,
            data,
            method,
            params,
            headers,
            timeout,
            responseType
        })
    },
    get(url: string, params?: object) {
        return instance.get(url, { params })
    },
    post(url: string, data?: object) {
        return instance.post(url, data)
    },
    put(url: string, data?: object) {
        return instance.put(url, data)
    },
    delete(url: string, data?: object) {
        return instance.delete(url, data)
    },
    download(
        url: string,
        method: string,
        data?: object,
        responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
    ) {
        return instance({
            url,
            method: method || 'get',
            data: data,
            responseType: responseType || 'arraybuffer'
        })
    }
}
