import { v4 } from 'uuid'
import { Package50 } from '@/utils/websocket/package'
import { FunCode } from '@/constants/funcode'
import { useLoginStore } from '@/stores/modules/login'
import { useErrorInfoStore } from '@/stores/modules/errorInfo'
import { IMessageHead } from './protobuf/proto'
import { TradeParams, TradeResponse } from './interface'
import Protobuf from './protobuf'
import socket from '../index'

/**
 * 构建消息头部
 */
function getProtoHeader(funCode: keyof typeof FunCode, header?: IMessageHead, marketId?: number) {
    const { getUserId } = useLoginStore();
    // 组合请求头
    const protoHeader: IMessageHead = {
        FunCode: FunCode[funCode],
        UUID: v4(),
        UserID: getUserId(),
        ...(header ?? {})
    }
    if (marketId) {
        protoHeader.MarketID = marketId;
    }
    return protoHeader;
}

/**
 * 向交易服务器发送请求
 * @param params 请求参数
 * @param reqKey 请求代码
 * @param rspKey 回调代码
 * @param marketId 市场ID
 */
function tradeServerMiddleware<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: keyof typeof FunCode, params: TradeParams<Req, Rsp>, marketId?: number): Promise<Rsp> {
    params.data.Header = getProtoHeader(reqKey, params.data.Header, marketId);
    console.log(reqKey, FunCode[reqKey], params.data);

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

/**
 * 向交易服务器发送请求
 * @param reqKey 
 * @param rspKey 
 * @param params 
 * @param marketId 
 */
export async function tradeServerRequest<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: keyof typeof FunCode, params: TradeParams<Req, Rsp & TradeResponse>, marketId?: number) {
    const { getErrorInfoByCode } = useErrorInfoStore();
    const { success, fail, complete } = params;

    await tradeServerMiddleware(reqKey, rspKey, params, marketId).then((res) => {
        const { RetCode, Status, RetDesc } = { ...res };
        switch (RetCode) {
            case 0: {
                success && success(res);
                return Promise.resolve();
            }
            case -1: {
                // 管理端错误消息
                return Promise.reject(RetDesc);
            }
            case 12018: {
                if (RetDesc) {
                    // 解析base64
                    res.RetDesc = Buffer.from(RetDesc, 'base64').toString();
                }
                return Promise.reject(res.RetDesc);
            }
            default: {
                // 银行 业务 以 Status 作为判断依据
                if (Status === 0 || Status == 6007) {
                    success && success(res);
                    return Promise.resolve();
                }
                const msg = getErrorInfoByCode(RetCode || Status);
                const error = String(RetDesc || RetCode);
                return Promise.reject(msg ?? error);
            }
        }
    }).catch((err) => {
        fail && fail(err);
        return Promise.reject(err);
    }).finally(() => {
        complete && complete();
    })
}