import { shallowRef, reactive } from 'vue'
import { v4 } from 'uuid'
import { timerTask } from '@/utils/timer'
import { queryLoginId, login } from '@/services/api/account'
import { useLoginStore, useUserStore, useEnumStore, useErrorInfoStore, useFavoriteStore, useAccountStore, usePerformanceStore, useExrateStore, useNotice } from '@/stores'
import { checkToken, checkTokenLoop } from '@/business/common'
import service from '@/services'
import socket from '@/services/socket'
import eventBus from '@/services/bus'
import cryptojs from 'crypto-js'

/**
 * 登录业务模块
 * @param persist 登录状态是否持久化
 * @returns 
 */
export function useLogin(persist = false) {
    const enumStore = useEnumStore()
    const errorInfoStore = useErrorInfoStore()
    const loginStore = useLoginStore()
    const userStore = useUserStore()
    const accountStore = useAccountStore()
    const performanceStore = usePerformanceStore()
    const exrateStore = useExrateStore()
    const favoriteStore = useFavoriteStore()
    const noticeStore = useNotice()

    const { logining, token } = loginStore.$toRefs()

    const remember = shallowRef(true) // 记住账号
    const formData = reactive<Proto.LoginReq>({
        LoginID: localStorage.getItem('gz_loginId') ?? '',
        LoginPWD: '',
        GUID: v4(),
        LoginType: 0,
        ClientType: 4,
        Version: '2.0.0.0',
        DeviceID: ''
    })

    const loadBaseData = async () => {
        await service.onReady() // 等待服务初始化
        await Promise.all([
            errorInfoStore.getErrorInfoList(),
            enumStore.getAllEnumList(),
        ])
    }

    const loadUserData = async () => {
        await checkToken() // 令牌校验
        await userStore.getUserData()
        performanceStore.getPerformanceTemplateList()
        performanceStore.getPerformanceStepTypeList()
        accountStore.getAccountList()
        favoriteStore.getFavoriteList()
        exrateStore.getExrateList()
        noticeStore.getNoticeList()
        checkTokenLoop()
    }

    // 用户登录
    const userLogin = async (autoLogin = false) => {
        try {
            logining.value = true
            await loadBaseData()
            const payload = await new Promise<Proto.LoginReq>((resolve, reject) => {
                if (autoLogin) {
                    const params = loginStore.getAutoLoginData()
                    if (params) {
                        resolve(params)
                    } else {
                        reject('自动登录失败')
                    }
                } else {
                    queryLoginId({
                        username: formData.LoginID
                    }).then((res) => {
                        const params = { ...formData }
                        params.LoginID = res.data
                        params.LoginPWD = cryptojs.SHA256(res.data + formData.LoginPWD).toString()
                        resolve(params)
                    }).catch((err) => {
                        reject(err)
                    })
                }
            })
            payload.GUID = v4()
            await login(payload).then(async (res) => {
                loginStore.setLoginInfo(res, persist)
                loginStore.setAutoLoginData(payload)
                localStorage.setItem('gz_loginId', formData.LoginID) // 记住登录ID
                await loadUserData()
                eventBus.$emit('LoginNotify') // 登录成功通知
            })
        } finally {
            logining.value = false
        }
    }

    // 用户登出
    const userLogout = (callback?: () => void) => {
        socket.closeAll()
        timerTask.clearAll()
        loginStore.clearAutoLoginData()
        loginStore.clearLoginInfo()
        callback && callback()
    }

    // 初始化业务数据
    const initBaseData = async (autoLogin = false) => {
        try {
            logining.value = true
            await loadBaseData()
            if (token.value) {
                await loadUserData()
            } else if (autoLogin && loginStore.getAutoLoginData()) {
                await userLogin(true)
            }
        } finally {
            logining.value = false
        }
    }

    return {
        logining,
        remember,
        formData,
        initBaseData,
        userLogin,
        userLogout,
    }
}