import { ref } from 'vue'
import { v4 } from 'uuid'
import { timerTask } from '@/utils/timer'
import { useStore } from '@/stores'
import { initBaseData, checkTokenLoop } from '@/business/common'
import socket from '@/services/socket'
import cryptojs from 'crypto-js'

// AES加密处理
const encrypt = (data: string, key: string) => {
    const { enc: { Utf8 }, AES } = cryptojs
    // 统一将传入的字符串转成UTF8编码
    const dataHex = Utf8.parse(data) // 需要加密的数据
    const keyHex = Utf8.parse(key) // 秘钥
    const ivHex = Utf8.parse(key) // 偏移量
    const encrypted = AES.encrypt(dataHex, keyHex, { iv: ivHex, })
    return encrypted.ciphertext.toString() //  返回加密后的值
}

// AES解密处理
const decrypt = (encryptedData: string, key: string) => {
    const { enc: { Utf8, Hex, Base64 }, AES } = cryptojs
    // 统一将传入的字符串转成UTF8编码
    const encryptedHexStr = Hex.parse(encryptedData)
    const srcs = Base64.stringify(encryptedHexStr)
    const keyHex = Utf8.parse(key) // 秘钥
    const ivHex = Utf8.parse(key) // 偏移量
    const decrypt = AES.decrypt(srcs, keyHex, { iv: ivHex })
    return decrypt.toString(Utf8).toString()
}

function useAutoLogin() {
    // 获取自动登录数据
    const getAutoLoginData = (autoLogin = false) => {
        const autologinKey = localStorage.getItem('thj_autologin_key') // 自动登录密钥
        const autologinData = localStorage.getItem('thj_autologin_data') // 自动登录数据
        const loginData: Proto.LoginReq = {
            LoginID: '',
            LoginPWD: '',
            GUID: '',
            LoginType: 0,
            ClientType: 4,
            Version: '2.0.0.0',
            DeviceID: ''
        }
        if (autologinKey && autologinData) {
            const decryptedData = decrypt(autologinData, autologinKey)
            if (decryptedData) {
                const loginReq: Proto.LoginReq = JSON.parse(decryptedData)
                // 自动登录
                if (autoLogin) {
                    return loginReq
                } else {
                    loginData.LoginID = loginReq.LoginID
                }
            }
        }
        return loginData
    }

    // 保存自动登录数据
    const setAutoLoginData = (data?: Proto.LoginReq) => {
        const loginKey = v4() // 随机密钥
        const loginData = data ?? getAutoLoginData(false)
        const encryptedData = encrypt(JSON.stringify(loginData), loginKey)
        localStorage.setItem('thj_autologin_key', loginKey)
        localStorage.setItem('thj_autologin_data', encryptedData)
    }

    return {
        getAutoLoginData,
        setAutoLoginData
    }
}

export function useAuth(autoLogin = false) {
    const { loginStore } = useStore()
    const { getAutoLoginData, setAutoLoginData } = useAutoLogin()
    const loading = ref(false)
    const user = ref<Proto.LoginReq>(getAutoLoginData(autoLogin))

    // 用户登录
    const login = () => {
        const { LoginID, LoginPWD } = user.value
        if (LoginID && LoginPWD) {
            return new Promise<void>((resolve, reject) => {
                loading.value = true
                const catchError = (err: string) => {
                    loading.value = false
                    reject(err)
                }

                loginStore.userLogin(user.value).then(() => {
                    initBaseData().then(() => {
                        setAutoLoginData(user.value)
                        checkTokenLoop()
                        resolve()
                    }).catch((err) => {
                        catchError(err)
                    })
                }).catch((err) => {
                    setAutoLoginData()
                    catchError(err)
                })
            })
        }
        return Promise.reject('登录失败')
    }

    // 用户登出
    const logout = (callback?: () => void) => {
        const { loginStore, accountStore } = useStore()
        const { setAutoLoginData } = useAutoLogin()

        setAutoLoginData()
        socket.closeAll()
        timerTask.clearAll()
        loginStore.reset()
        accountStore.reset()
        callback && callback()
    }

    return {
        loading,
        user,
        login,
        logout,
    }
}