import { v4 } from 'uuid'
import { Package50 } from '@/utils/websocket/package'
import { FunCode } from '@/constants/funcode'
import { useLoginStore, useErrorInfoStore } from '@/stores'
import { TradeResponse, TradeRequestConfig } from './interface'
import cryptojs from 'crypto-js'
import Protobuf from './protobuf'
import socket from '../index'

export default new (class {
    /**
     * 向交易服务器发送请求
     * @param config 
     * @returns 
     */
    private send<T>({ params, reqName, rspName, marketId = 0 }: TradeRequestConfig) {
        const { userId, firstAccountId } = useLoginStore()
        const reqCode = FunCode[reqName]
        const rspCode = FunCode[rspName]

        // 默认请求头
        params.Header = {
            AccountID: firstAccountId,
            MarketID: marketId,
            FunCode: reqCode,
            UUID: v4(),
            UserID: userId,
            ...params.Header
        }

        console.log(reqName, reqCode, params)

        return new Promise<T>((resolve, reject) => {
            Protobuf.requestEncode(reqName, params).then((res) => {
                // 发送消息
                socket.sendTradeServer({
                    data: {
                        rspCode: rspCode,
                        payload: new Package50(reqCode, res)
                    },
                    success: (raw) => {
                        Protobuf.responseDecode<T>(rspName, raw.content).then((res) => {
                            console.log(rspName, rspCode, res)
                            resolve(res)
                        }).catch(() => {
                            console.error(rspName, raw)
                            reject('报文解析失败')
                        })
                    },
                    fail: (err) => {
                        console.error(reqName, err)
                        reject(err)
                    }
                })
            }).catch((msg) => {
                console.error(reqName, msg)
                reject('报文构建失败')
            })
        })
    }

    /**
     * 向交易服务器发送请求
     * @param config 
     * @returns 
     */
    async sendMessage<T extends TradeResponse>(config: TradeRequestConfig) {
        const res = await this.send<T>(config)
        switch (res.RetCode) {
            case 0: {
                return Promise.resolve(res)
            }
            case 12018: {
                if (res.RetDesc) {
                    const { Utf8, Base64 } = cryptojs.enc
                    const word = Base64.parse(res.RetDesc) // 解析base64
                    res.RetDesc = Utf8.stringify(word)
                }
                return Promise.reject(res.RetDesc)
            }
            default: {
                // 银行 业务 以 Status 作为判断依据
                if (res.Status === 0 || res.Status == 6007) {
                    return Promise.resolve(res)
                }
                const { getErrorInfoByCode } = useErrorInfoStore()
                const msg = getErrorInfoByCode(res.RetCode)
                const error = String(res.RetDesc || res.RetCode)
                return Promise.reject(msg ?? error)
            }
        }
    }
})