package com.sonic.frog.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sonic.common.rpc.Page;
import com.sonic.daosupport.converter.PageConverter;
import com.sonic.frog.dao.AiUserGiftDao;
import com.sonic.frog.domain.entity.AiUser;
import com.sonic.frog.domain.entity.AiUserGift;
import com.sonic.frog.domain.entity.GiftDict;
import com.sonic.frog.domain.input.AiUserGiftListInput;
import com.sonic.frog.domain.input.SendGiftInput;
import com.sonic.frog.domain.output.AiUserGiftListOutput;
import com.sonic.frog.domain.output.AiUserHeartbeatRelationOutput;
import com.sonic.frog.enums.HeartbeatLevelEnum;
import com.sonic.frog.enums.MessageTypeEnum;
import com.sonic.frog.enums.SendGiftSceneEnum;
import com.sonic.frog.enums.ToastResultCode;
import com.sonic.frog.event.inner.payload.AiUserStatPayload;
import com.sonic.frog.event.inner.payload.CalcHeartbeatLevelPayload;
import com.sonic.frog.event.outer.payload.AiChatPayload;
import com.sonic.frog.service.*;
import com.sonic.frog.utils.KeyGenerator;
import com.sonic.lion.lib.client.PayClient;
import com.sonic.lion.lib.client.SubscribeClient;
import com.sonic.lion.lib.enums.BizType;
import com.sonic.lion.lib.input.BalanceCheckoutInput;
import com.sonic.pigeon.lib.bo.ScoreExtension;
import com.sonic.pigeon.lib.client.ImMessageClient;
import com.sonic.pigeon.lib.enums.ImMessageTypeEnum;
import com.sonic.pigeon.lib.input.SendAiCustomerMessageInput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.sonic.frog.enums.Constants.*;

/**
 * AI用户收到礼物业务实现类
 */
@Service
@Slf4j
public class AiUserGiftServiceImpl extends ServiceImpl<AiUserGiftDao, AiUserGift> implements AiUserGiftService {

    @Autowired
    private AiUserGiftDao aiUserGiftDao;
    @Autowired
    private GiftDictService giftDictService;
    @Autowired
    private ImMessageClient imMessageClient;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private GiftRewardRecordService giftRewardRecordService;
    @Autowired
    private CommonMessageService commonMessageService;
    @Autowired
    private AiUserSearchService aiUserSearchService;
    @Autowired
    private HeartbeatLevelDictService heartbeatLevelDictService;
    @Autowired
    private AiUserHeartbeatRelationService aiUserHeartbeatRelationService;
    @Autowired
    private UserAiMeetService userAiMeetService;
    @Autowired
    private PayClient payClient;
    @Autowired
    private SubscribeClient subscribeClient;

    @Override
    public Page<AiUserGiftListOutput> getAiUserGiftList(AiUserGiftListInput input) {
        //分页获取
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<AiUserGiftListOutput> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(input.getPage().getPn(), input.getPage().getPs());
        IPage<AiUserGiftListOutput> aiUserGiftList = aiUserGiftDao.getAiUserGiftList(page, input.getAiId());
        return PageConverter.convert(aiUserGiftList, aiUserGiftListOutput -> {
            return aiUserGiftListOutput;
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendGift(Long currentUserId, SendGiftInput input) {
        Long giftId = input.getGiftId();
        Integer num = input.getNum();
        Long aiId = input.getAiId();
        SendGiftSceneEnum scene = input.getScene();
        //判断Ai是否存在
        AiUser aiUser = aiUserSearchService.getAiUserByAiId(aiId);
        ToastResultCode.AI_USER_NOT_EXIST.check(aiUser == null);
        //ai是否删除或设置成私密
        Boolean isDelete = aiUser.getIsDelete();
        //判断礼物是否存在
        GiftDict giftDict = giftDictService.getById(giftId);
        ToastResultCode.GIFT_NOT_EXIST.check(giftDict == null);
        //送该礼物需要的心动等级
        HeartbeatLevelEnum needHeartbeatLevel = giftDict.getHeartbeatLevel();
        if (needHeartbeatLevel != null) {
            //获取用户与Ai的关动等级
            HeartbeatLevelEnum userHeartbeatLevel = aiUserHeartbeatRelationService.getHeartbeatLevel(currentUserId, aiId);
            ToastResultCode.SYS_PERMISSION_DENIED.check(userHeartbeatLevel == null);
            //判断等级是否满足
            List<HeartbeatLevelEnum> unlockList = heartbeatLevelDictService.getUnlockListByCode(userHeartbeatLevel);
            ToastResultCode.SYS_PERMISSION_DENIED.check(CollectionUtils.isNotEmpty(unlockList) && !unlockList.contains(needHeartbeatLevel));
        }
        //是否会员礼物，检测是否是会员
        Boolean isMember = subscribeClient.queryUserIsSubscribe(currentUserId);
        ToastResultCode.SYS_PERMISSION_DENIED.check(giftDict.getIsMemberGift() && (isMember == null || !isMember));

        Long totalAmount = 0L;
        if (giftDict.getPrice() != null && giftDict.getPrice() > 0) {
            totalAmount = Long.valueOf(giftDict.getPrice() * num);
        }

        //平台抽取50%作为手续费,向下取整，平台少收服务费，自己给自己ai打赏抽成比例为0.5
        Long platformFee = new BigDecimal(totalAmount).multiply(PLATFORM_RATE).divide(new BigDecimal(100), 0, RoundingMode.FLOOR).multiply(new BigDecimal(100)).longValue();
        //生成订单编号
        String orderNo = KeyGenerator.instance().generatorUniqueKey("");
        //调用支付服务扣款
        BalanceCheckoutInput balanceCheckoutInput = BalanceCheckoutInput.builder()
                .platform("Balance")
                .outTradeNo(orderNo)
//                .bizType(aiUser.getIsDelete() ? BizType.GIFT_TO_P : BizType.GIFT)
                .bizType(BizType.GIFT)
                .name("礼物支付")
                //付款人
                .srcAccountId(currentUserId)
                //收款人
                .desAccountId(aiUser.getUserId())
                //礼物总金额
                .productAmount(totalAmount)
                //平台抽取的金额
                .platformFee(isDelete ? totalAmount : platformFee)
                //折扣金额
                .promoAmount(0L)
                .extend(JSON.toJSONString(input))
                .build();
        payClient.checkoutToUser(balanceCheckoutInput);
        //添加礼物记录
        giftRewardRecordService.addGiftRewardRecord(giftDict, orderNo, currentUserId, aiId, num);
        //增加AI收到该礼物的数量
        aiUserGiftDao.increaseGiftNum(aiId, giftId, num);

        boolean isMeet = false;
        //home发送礼物场景
        if (SendGiftSceneEnum.HOME == scene) {
            //绑定meet关系(直接写到数据库中)
            userAiMeetService.addMeet(currentUserId, input.getAiId());
        }
        //IM发送礼物场景
        if (SendGiftSceneEnum.IM == scene) {
            //心动值 0.2心动值 = 1CrushCoin
            BigDecimal heartbeatVal = ONE_COIN_HEARTBEAT_VAL.multiply(new BigDecimal(totalAmount)).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
            //计算总价，保留2位小数
            BigDecimal totalAmountBigDecimal = new BigDecimal(totalAmount).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            //发送IM礼物消息
//            String imContent = String.format("送你%s个%s礼物", num, giftDict.getName());
            String imContent = String.format(ImMessageTypeEnum.IM_SEND_GIFT.getContent(), num, giftDict.getName());
            Map<String, Object> extra = new HashMap<>();
            extra.put("giftNum", num);
            extra.put("giftName", giftDict.getName());
            extra.put("giftId", giftId);
            extra.put("giftIcon", giftDict.getIcon());
            extra.put("type", ImMessageTypeEnum.IM_SEND_GIFT.name());
            extra.put("title", imContent);
            SendAiCustomerMessageInput sendAiCustomerMessageInput = SendAiCustomerMessageInput.builder()
                    .fromUserId(currentUserId)
                    .toUserId(aiId)
                    .content(imContent)
                    .attachment(JSON.toJSONString(extra))
                    .extension(JSONObject.toJSONString(ScoreExtension.builder().score(heartbeatVal).build()))
                    .build();
            imMessageClient.sendUserToAiCustomerMessage(sendAiCustomerMessageInput);
            //改写文本内容
//            imContent = String.format("送你%s个%s礼物,价值%s【这是真实付费礼物，不是说说而已】", num, giftDict.getName(), totalAmountBigDecimal);
            imContent = String.format("I'm sending you %s %s gifts, worth %s. （These are real paid gifts, not just empty words.）", num, giftDict.getName(), totalAmountBigDecimal);
            //发送AI消息回复MQ
            commonSendMqService.sendAiChatMq(currentUserId, aiId, imContent, MessageTypeEnum.TEXT, null, AiChatPayload.SourceType.GIFT);
            //发送礼物消息进行心动值计算MQ
            if (totalAmount > 0) {
                commonSendMqService.calHeartbeatLevelSendMq(CalcHeartbeatLevelPayload.builder()
                        .userId(currentUserId)
                        .aiId(aiId)
                        .heartbeatVal(heartbeatVal)
                        .type(CalcHeartbeatLevelPayload.Type.SEND_GIFT)
                        .build());
            }
        }

        //ai未删除才发送系统通知,ai Coin数统计
        if (!isDelete) {
            //发送系统通知 通知创作者,自己给自己的ai打赏时，不用发送系统通知
            if (!currentUserId.equals(aiUser.getUserId())) {
                commonMessageService.aiGiftSendMessage(currentUserId, aiId, giftDict.getName(), num, totalAmount);
            }
            //发送ai Coin数统计
            commonSendMqService.aiUserStatMq(aiId, AiUserStatPayload.Type.GIFT, totalAmount);
        }
    }
}