import { UserOrderModel, UserOrderModelType } from '../db/UserOrder';
import { ACTIVITY_TYPE, DEBUG_PRICE, MAIL_TYPE, ORDER_STATE, PAY_TYPE, PUSH_ROUTE, REFUND_PRICE_TO_GOLD, STATUS, TASK_TYPE, TA_EVENT, TA_USERSET_TYPE } from '../consts';
import { dicRMB } from '../pubUtils/dictionary/DicRMB';
import { makeYuanbaoShopReward } from './activity/yuanbaoService';
import { RoleModel } from '../db/Role';
import { makeMonthlyTicketReward } from './activity/monthlyTicketService';
import { makeSignInVIP } from './activity/signInService';
import { makeDailyRMBGiftsReward } from './activity/dailyRMBGiftsService';
import { checkPopUpShopCanBuy, makePopUpShopReward } from './activity/popUpShopService';
import { ActivityModel, ActivityModelType } from '../db/Activity';
import { ActivityFirstGiftModel } from '../db/ActivityFirstGift';
import { ServerlistModel } from '../db/Serverlist';
import { makeGrowthFund } from './activity/growthFundService';
import { checkLimitPackageCanBuy, makeLimitPackageReward } from './activity/limitPackageService';
import { makeShop } from './activity/treasureHuntService';
import { makeSelfServerShop } from './activity/selfServiceShopActivityService';
import { makeRefreshShopReward } from './activity/refreshShopService';
import { ActivityMonopolyModel, ActivityMonopolyModelType } from '../db/ActivityMonopoly';
import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '../db/ActivityMonopolyLand';
import { parseGoodStr, resResult } from '../pubUtils/util';
import { checkOrderWX } from './pay/weixinPay';
import { addRechargeMoney } from './activity/rechargeMoneyService';
import { addVipRechargeMoney } from './activity/vipRechargeMoneyService';
import { checkTask } from './task/taskService';
import { checkOrderALI } from './pay/aliPay';
import { getRoleOnlineInfo } from './redisService';
import { PayCallback37Data } from '../domain/sdk';
import { reportTAEvent, reportTAUserSet } from './sdkService';
import { savePayLog } from '../pubUtils/logUtil';
import { recordFirstGift } from './activity/firstGiftService';
import { makeTaskPass } from './activity/taskPassService';
import { addGuildPay } from './activity/guildPayService';
import { sendMessageToUserWithSuc } from './pushService';
import { gameData } from '../pubUtils/data';
import { checkParamPrice, needRebate } from '../pubUtils/sdkUtil';
import { checkShopCanBuyInOrder, makeShopOrder } from './shopService';
import { UserModel } from '../db/User';
import { HistoryOrderModel } from '../db/HistoryOrder';
import { sendMailByContent } from './mailService';
import { getGoldObject } from './role/rewardService';
import { RECHARGE } from '../pubUtils/dicParam';

export async function checkOrderCanBuy(roleId: string, serverId: number, activityData: ActivityModelType, productID: string, paramStr: string) {
    let activityId = activityData.activityId;

    switch(activityData.type) {
        case ACTIVITY_TYPE.POP_UP_SHOP:
            {
                return await checkPopUpShopCanBuy(roleId, serverId, activityId, productID, paramStr)
            }
        case ACTIVITY_TYPE.SHOP:
            {
                return await checkShopCanBuyInOrder(roleId, serverId, activityData, productID)
            } 
        case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE:
        case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY:
        case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY:
            {
                return await checkLimitPackageCanBuy(roleId, serverId, activityData, productID)
            } 
    }
    return true
}

/**
 * 结算账单 
 * @param localOrderID 本地订单号
 */
export async function makeOrder(orderInfo: UserOrderModelType, sid: string) {

    //商品价格信息
    let productInfo = dicRMB.get(orderInfo.productID)


    let productType = productInfo.type;//类型
    let price = orderInfo.price;//下单时的价格
    let payType = orderInfo.payType;//支付类型
    let roleId = orderInfo.roleId;//角色

    const roleInfo = await RoleModel.increaseTotalPay(roleId, price);

    let rewardResult: any = { code: 0, data: null };

    switch (productType) {
        case ACTIVITY_TYPE.SIGN_IN_VIP:
            {
                rewardResult = await makeSignInVIP(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE:
            {
                rewardResult = await makeLimitPackageReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY:
        case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY:
            {
                rewardResult = await makeLimitPackageReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.YUAN_BAO_SHOP:
            {
                rewardResult = await makeYuanbaoShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }

        case ACTIVITY_TYPE.MONTHLY_TICKET_1:
        case ACTIVITY_TYPE.MONTHLY_TICKET_2:
            {
                rewardResult = await makeMonthlyTicketReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.DAILY_RMB_GIFTS:
            {
                rewardResult = await makeDailyRMBGiftsReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.POP_UP_SHOP://弹出礼包
            {
                rewardResult = await makePopUpShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, orderInfo.paramStr, roleInfo)
                break;
            }
        case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金（高阶）
            {
                rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金（高阶）
            {
                rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金（高阶）
            {
                rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.TREASURE_HUNT://寻宝奇兵活动-每日物资商店
            {
                rewardResult = await makeShop(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.SELF_SERVICE_SHOP://自选商店-购买礼包（糜家商队）
            {
                rewardResult = await makeSelfServerShop(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;
            }
        case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店（分页，可刷新，限制购买次数，支持rmb与资源兑换）
            {
                if (orderInfo.paramStr) {//大富翁商店结算
                    let paramObj = JSON.parse(orderInfo.paramStr);
                    let activityId = paramObj.activityId;//大富翁活动id；   orderInfo.activityId是大富翁中的商店活动id
                    if (activityId) {
                        let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(orderInfo.serverId, activityId, roleId);
                        let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(orderInfo.serverId, activityId, roleId, playerMonopolyData.curPosition);
                        let roundIndex = playerLandData.stopCount;
                        rewardResult = await makeRefreshShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, roundIndex)
                        break;
                    }
                }
                //正常商店结算
                rewardResult = await makeRefreshShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, 0)
                break;
            }
        case ACTIVITY_TYPE.TASK_PASS: // 战令-高级卡
            {
                rewardResult = await makeTaskPass(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;

            }
        case ACTIVITY_TYPE.SHOP: // 商店
            {
                rewardResult = await makeShopOrder(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID)
                break;

            }
        default:
            rewardResult = STATUS.ERROR_TYPE;
            break;
    }

    if(rewardResult.code == 0) {
        await recordFirstGift(roleInfo, orderInfo.serverId);
    }

    await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { totalPay: roleInfo.totalPay }, sid);
    
    return {...rewardResult, roleInfo}
}

export async function settleOrder(order: UserOrderModelType, serverId: number, sid?: string) {
    if(!sid) {
        let onlineUser = await getRoleOnlineInfo(order.roleId);
        sid = onlineUser.sid;
    }
    //结算奖励
    let result = await makeOrder(order, sid);
    if (result.code !== 0) {//结算失败
        console.log(`支付失败..... ${JSON.stringify(result)}`)
        reportTAEvent(order.roleId, TA_EVENT.RECHARGE_FAIL, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: order.useVoucher? "现金": "代金券" })
        savePayLog(order);
        return resResult(result);
    }
    //推送
    console.log('***** settleOrder', order.roleId, sid)
    //活动统计
    await addRechargeMoney(order.roleId, serverId, order.price);
    await addVipRechargeMoney(order.roleId, serverId, order.price);
    await addGuildPay(result.roleInfo, order.price)
    //成长任务
    await checkTask(serverId, order.roleId, sid, TASK_TYPE.ACTIVITY_RMB, { count: order.price });
    if(order.payType != PAY_TYPE.TEST) {    
        reportTAEvent(order.roleId, TA_EVENT.RECHARGE_SUCCESS, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: order.useVoucher? "现金": "代金券" })
        reportTAUserSet(TA_USERSET_TYPE.SET_ONCE, order.roleId, { first_pay_time: new Date() });
        reportTAUserSet(TA_USERSET_TYPE.SET, order.roleId, { last_pay_time: new Date() });
        reportTAUserSet(TA_USERSET_TYPE.ADD, order.roleId, { total_revenue: order.price });
    }
    savePayLog(order);
    if(!!sid) {
        sendMessageToUserWithSuc(order.roleId, PUSH_ROUTE.ORDER, {
            ...result.data,
            price: order.price,
            state: order.state,
            localOrderID: order.localOrderID}, sid);
    }
    return result.data;
}

export async function settleOrderWx(order: UserOrderModelType, serverId: number, sid: string) {

    if (order.state == ORDER_STATE.RESULT_SUCCESS) {
        return STATUS.DUPLICATE_ORDER;
    }
    order = await UserOrderModel.check(order.roleId, order.localOrderID);
    if (!order) {
        return STATUS.DUPLICATE_ORDER;
    }

    let weixinResult = await checkOrderWX(order.localOrderID);
    if (weixinResult.code == 0) {
        console.log('微信订单查询失败')
        return STATUS.ORDER_ERROR;
    }
    if (parseInt(weixinResult.data.total_fee) / 100 != order.price) {
        console.log('订单价格错误')
        return STATUS.PRICE_ERROR;
    }
    if (weixinResult.data.trade_state != "SUCCESS" ||
        weixinResult.data.result_code != "SUCCESS" ||
        weixinResult.data.return_code != "SUCCESS") {
        return STATUS.NO_PAY;
    }    

    let result = await  settleOrder(order, serverId, sid);
    order = await UserOrderModel.success(order.roleId, order.localOrderID, result);

    return STATUS.SUCCESS
}

export async function settleOrderAli(order: UserOrderModelType, serverId: number, sid: string) {
    if (order.state == ORDER_STATE.RESULT_SUCCESS) {
        return STATUS.DUPLICATE_ORDER;
    }
    let aliResult = await checkOrderALI(order.localOrderID);
    if (aliResult.code == 0) {
        console.log('支付宝订单查询失败')
        return STATUS.ORDER_ERROR;
    }
    if (parseInt(aliResult.data.total_amount) != order.price) {
        console.log('订单价格错误')
        return STATUS.PRICE_ERROR;
    }
    if (aliResult.data.trade_status != "TRADE_SUCCESS") {
        return STATUS.NO_PAY;
    }
    let aliOrderID = aliResult.data.trade_no;
    let result = await settleOrder(order, serverId, sid);
    await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, aliOrderID, result);

    return STATUS.SUCCESS
}

export async function settleOrderFromRedisPub(message: string) {
    console.log('**********settleOrderFromRedisPub*******')
    console.log('message: ', message);

    let params: PayCallback37Data;
    try {
        params = JSON.parse(message);
    } catch(e) {
        return false;
    }

    let order = await UserOrderModel.findOrder(params.order_no);
    if(!order || order.state != ORDER_STATE.CHECK_ORDER) {
        console.log('订单状态错误');
        return false;
    }
    if(order.roleId != params.actor_id) {
        console.log('订单玩家错误');
        return false;
    }
    if((!checkParamPrice(order.price, params.money))) {
        console.log('订单金额错误');
        return false;
    }

    let aliOrderID = params.order_id;

    let result = await settleOrder(order, parseInt(`${params.sid}`));
    await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, aliOrderID, JSON.stringify(result));

    return true
}

export async function settleOrderFromHandler(localOrderID: string, roleId: string, serverId: number, sid: string ) {

    let order = await UserOrderModel.findOrder(localOrderID);
    if(!order || order.state != ORDER_STATE.APPLY) {
        return STATUS.DUPLICATE_ORDER;
    }
    if(order.roleId != roleId) {
        console.log('订单玩家错误');
        return STATUS.ORDER_STATUS_ERROR;
    }

    let result = await settleOrder(order, serverId, sid);
    await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, '', JSON.stringify(result));

    return STATUS.SUCCESS
}

export async function refundOrderFromRedisPub(message: string) {
    console.log('**********refundOrderFromRedisPub*******')
    console.log('message: ', message);

    let params: PayCallback37Data;
    try {
        params = JSON.parse(message);
    } catch(e) {
        return false;
    }

    let order = await UserOrderModel.findOrder(params.order_no);
    if(!order || order.state != ORDER_STATE.CHECK_TO_REFUND) {
        console.log('订单状态错误');
        return false;
    }
    if(order.roleId != params.actor_id) {
        console.log('订单玩家错误');
        return false;
    }

    let price = order.price;
    let refundGold = price * REFUND_PRICE_TO_GOLD;
    let role = await RoleModel.incRoleInfo(order.roleId, { gold: -refundGold }, {});
    let onlineUser = await getRoleOnlineInfo(order.roleId);
    let sid = onlineUser.sid;
    sendMessageToUserWithSuc(order.roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold }, sid);
    await UserOrderModel.refund(order.roleId, order.localOrderID, message);

    return true
}

export async function rebateHistoryOrder(roleId: string, uid: number) {
    let user = await UserModel.findUserByUid(uid);
    if(user) {
        let historyOrders = await HistoryOrderModel.findByChannelId(user.channelId);
        if(needRebate() && historyOrders.length > 0) {
            for(let historyOrder of historyOrders) {
                if(!historyOrder.isReceived) {
                    let totalPay = historyOrder.totalPay;
                    if(totalPay > 0) {
                        let gold = 0;
                        let goods = parseGoodStr(RECHARGE.RECHARGE_RMB_RETURN_RATIO).map(({ id, count }) => {
                            let result = Math.floor(count * totalPay)
                            gold += result;
                            return { id, count: result }
                        });
                        await sendMailByContent(MAIL_TYPE.REBATE, roleId, { goods, params: [`${totalPay}`, `${gold}`] });
                        await HistoryOrderModel.receive(historyOrder._id, roleId);
                    }
                }
            }
        }
    }
}