import { reactive, ref, computed } from 'vue';
import { queryErmcpTradePosition } from '@/services/go/ermcp/futures';
import { QueryErmcpTradePositionRsp } from '@/services/go/ermcp/futures/interface';
import { getQuoteDayInfoByCode } from "@/services/bus/goods";
import { BuyOrSell } from '@/common/constants/enumCommon';
import { getTaAccounts } from '@/services/go/TaAccount';
import { Taaccount } from "@/services/go/TaAccount/interface";
import { geLoginID_number } from '@/services/bus/login';
import { Systemparam } from '@/services/go/useInfo/interface';
import { getSelectedAccountId, setSelectedAccount } from '@/services/bus/account';  // 为了兼容以前代码，待优化后期废除
import { subcriteGoodsQuote } from '@/common/setup/table/tableQuote';
import { TradeAccount, TradePosition } from './interface'
import APP from '@/services';

let stopSubcribe: () => void;
// 加载状态
const loading = ref<boolean>(false);
// 资金账户列表
const tradeAccountList: TradeAccount[] = reactive([]);
// 当前账户期货持仓列表
const tradePositionList: TradePosition[] = reactive([]);
// 当前资金账户信息
const tradeAccount = ref<TradeAccount>();

/**
 * 资金账户-------------------------------------------------------待优化2022.02.11
 */
export function useTradeAccount() {
    // 获取资金账户列表
    const getTradeAccountList = () => {
        // 登录ID
        const loginID = Number(geLoginID_number());
        const tmpAccountList: TradeAccount[] = [];
        loading.value = true;

        getTaAccounts({ loginID }).then(async (res) => {
            for (let i = 0; i < res.length; i++) {
                const account = res[i];
                const positionList: TradePosition[] = [];

                if (account.tradestatus === 1) {
                    // 获取账户下的期货持仓列表
                    await queryErmcpTradePosition({ accountID: account.accountid }).then((res) => {
                        res.forEach((item) => {
                            positionList.push({
                                ...item,
                                ...calcPositionValue(item),
                            })
                        })
                    })

                    tmpAccountList.push({
                        positionList,
                        ...account,
                        ...calcCapitalValue(account, positionList),
                    })
                }
            }

            tradeAccountList.length = 0;
            tradeAccountList.push(...tmpAccountList);

            tradeAccountChange(getSelectedAccountId());
            loading.value = false;
        })
    }

    // 切换资金账户
    const tradeAccountChange = (accountId: number) => {
        tradePositionList.length = 0;
        // 停止上次订阅
        stopSubcribe && stopSubcribe();

        const account = tradeAccountList.find((account) => account.accountid === accountId);
        if (account) {
            tradeAccount.value = account;
            tradePositionList.push(...account.positionList);
            setSelectedAccount(account); // 为了兼容以前代码，待优化后期废除

            // 开始行情订阅
            stopSubcribe = subcriteGoodsQuote(account.positionList.map((e) => e.goodscode));
        } else {
            tradeAccount.value = undefined;
        }
    }

    // 期货账户列表
    const futuresAccountList = computed(() => tradeAccountList.filter((account) => account.taaccounttype === 1));

    return {
        loading,
        tradeAccountList,
        tradePositionList,
        tradeAccount,
        futuresAccountList,
        getTradeAccountList,
        tradeAccountChange,
    }
}

/**
 * 计算持仓数据
 * @param position 
 * @returns 
 */
function calcPositionValue(position: QueryErmcpTradePositionRsp) {
    // 获取对应的商品行情
    const quote = getQuoteDayInfoByCode(position.goodscode);

    // 计算开仓均价
    const openAveragePrice = computed(() => {
        const { opencost, curpositionqty, agreeunit } = position
        // 开仓成本 ÷ 期末头寸 ÷ 合约单位
        return opencost / curpositionqty / agreeunit;
    })

    // 计算持仓均价
    const positionAveragePrice = computed(() => {
        const { positioncost, curpositionqty, agreeunit } = position
        // 持仓成本 ÷ 期末头寸 ÷ 合约单位
        return positioncost / curpositionqty / agreeunit;
    })

    // 计算浮动盈亏 - 对应市场收益权
    const positionProfitAndLoss = computed(() => {
        const { curpositionqty, agreeunit } = position
        if (quote?.last) {
            if (position.buyorsell === BuyOrSell.buy) {
                // 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位
                return (quote.last - openAveragePrice.value) * curpositionqty * agreeunit
            } else {
                // 卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
                return (positionAveragePrice.value - quote.last) * curpositionqty * agreeunit
            }
        }
        return position.positionpl
    })

    // 计算市值 - 对应市场所有权
    const capitalization = computed(() => {
        if (quote?.last) {
            // 市值 = 最新价 * 持仓数量 * 合约单位
            return quote.last * position.curpositionqty * position.agreeunit
        }
        return 0
    })

    // 计算盈亏比例
    const positionProfitAndLossRate = computed(() => {
        const { opencost } = position
        if (opencost > 0) {
            // 持仓盈亏 ÷ 开仓成本
            return positionProfitAndLoss.value / opencost * 100
        }
        return 0
    })

    return {
        openAveragePrice,
        capitalization,
        positionAveragePrice,
        positionProfitAndLoss,
        positionProfitAndLossRate,
    }
}

/**
 * 计算资金数据
 * @param account 
 * @param positionList 
 * @returns 
 */
function calcCapitalValue(account: Taaccount, positionList: TradePosition[]) {
    // 系统参数
    const systemParams = <Systemparam[]>APP.get('systemParams');

    // 计算总浮动盈亏
    const positionProfitAndLoss = computed(() => positionList.reduce((res, item) => res + item.positionProfitAndLoss.value, 0));

    // 计算总市值
    const marketCap = computed(() => {
        // 根据系统参数“087 风险净值是否加上市值 - 0:不加 1:加“
        const flag = systemParams.find((e) => e.paramcode === '087')?.paramvalue === '1';
        if (flag) {
            return positionList.reduce((res, item) => res + item.capitalization.value, 0);
        }
        return 0;
    });

    // 计算可用资金
    const availableBalance = computed(() => {
        // *系统参数"113"（当日浮动盈利是否可用） 0:不可用 1:可用
        const flag = systemParams.find((e) => e.paramcode === '113')?.paramvalue === '1';

        const { currentbalance, usedmargin, freezemargin, freezecharge, otherfreezemargin, outamountfreeze } = account;
        const freeze = currentbalance - usedmargin - freezemargin - otherfreezemargin - freezecharge - outamountfreeze;

        if (positionProfitAndLoss.value < 0 || (positionProfitAndLoss.value >= 0 && flag)) {
            // 账户（总浮动盈亏为负） 或（总浮动盈亏为正 且 113 = 1）
            // 可用资金 = 总浮动盈亏 + 期末余额 - 占用 - 冻结 - 其它冻结 - 手续费冻结 - 出金冻结
            return positionProfitAndLoss.value + freeze;
        } else {
            // 可用资金 = 期末余额 - 占用 - 冻结 - 其它冻结 - 手续费冻结 - 出金冻结
            return freeze;
        }
    });

    // 计算权益/净值
    const equity = computed(() => {
        // 根据系统参数“307 账户净值是否减冻结资金 - 0:不减 1:减“
        const flag = systemParams.find((e) => e.paramcode === '307')?.paramvalue === '1';

        const result = account.currentbalance + marketCap.value + positionProfitAndLoss.value;
        if (flag) {
            const { otherfreezemargin, outamountfreeze } = account;
            // 净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权) - 其它冻结 - 出金冻结
            return result - otherfreezemargin - outamountfreeze;
        } else {
            // 净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权)
            return result;
        }
    })

    // 计算冻结资金
    const freezeAmount = computed(() => {
        const { freezemargin, otherfreezemargin, outamountfreeze, freezecharge } = account;
        // 冻结资金 = 冻结保证金 + 手续费冻结 + 出金冻结 + 其他冻结保证金
        return freezemargin + freezecharge + outamountfreeze + otherfreezemargin;
    })

    // 计算风险净值
    const valueAtRisk = computed(() => {
        // 根据系统参数“307 账户净值是否减冻结资金 - 0:不减 1:减“
        const flag = systemParams.find((e) => e.paramcode === '087')?.paramvalue === '1';
        const { otherfreezemargin, outamountfreeze } = account;

        const result = account.currentbalance + positionProfitAndLoss.value - otherfreezemargin - outamountfreeze;
        if (flag) {
            // 风险净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权) - 其他冻结-出金冻结
            return result + marketCap.value;
        } else {
            // 风险净值 = 期末余额 + 浮动盈亏(收益权) - 其他冻结 - 出金冻结
            return result;
        }
    })

    // 计算风险率
    const hazardRatio = computed(() => {
        // 根据系统参数“132   风险率计算公式”：
        const flag = systemParams.find((e) => e.paramcode === '132')?.paramvalue === '1';
        const { usedmargin, mortgagecredit } = account;

        let result = 0
        if (flag) {
            // 风险率 = 占用 / 风险净值
            result = usedmargin / valueAtRisk.value;
        } else {
            // 风险率 = (占用 - 授信金额) / (风险净值 - 授信金额)
            result = (usedmargin - mortgagecredit) / (valueAtRisk.value - mortgagecredit);
        }

        return isNaN(result) ? 0 : result;
    })

    return {
        equity,
        positionProfitAndLoss,
        availableBalance,
        freezeAmount,
        hazardRatio,
    }
}