package com.sonic.cow.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.sonic.cow.client.AsrV2Client;
import com.sonic.cow.client.TtsV3Client;
import com.sonic.cow.domain.input.VoiceAsrInput;
import com.sonic.cow.domain.input.VoiceTtsV2Input;
import com.sonic.cow.domain.output.AsrOutput;
import com.sonic.cow.enums.DeductionTypeEnum;
import com.sonic.cow.enums.ToastResultCode;
import com.sonic.cow.event.outer.payload.UserDeductionStatPayload;
import com.sonic.cow.service.CommonSendMqService;
import com.sonic.cow.service.VoiceService;
import com.sonic.cow.utils.LimitUtils;
import com.sonic.cow.utils.RedisKeyUtils;
import com.sonic.lion.lib.client.PayClient;
import com.sonic.lion.lib.output.AccountBuffOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;

import static com.sonic.cow.utils.Constant.VOICE_DEDUCTION_AMOUNT;

/**
 * @description: 语音通话实现类
 * @author: mzc
 * @date: 2025-07-30 11:24
 **/
@Slf4j
@Service
public class VoiceServiceImpl implements VoiceService {

    @Autowired
    private AsrV2Client asrV2Client;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private PayClient payClient;
    @Autowired
    private LimitUtils limitUtils;
    @Autowired
    private RedisKeyUtils redisKeyUtils;
    @Autowired
    private TtsV3Client ttsV3Client;

    @Override
    public AsrOutput asr(Long userId, VoiceAsrInput input) throws UnirestException, InterruptedException {
        //检测余额是否不足
        boolean balanceIsInsufficient = checkBalanceIsInsufficient(userId, VOICE_DEDUCTION_AMOUNT);
        if (balanceIsInsufficient) {
            //余额不足，发送MQ，余额不足处理
            commonSendMqService.userBalanceInsufficientCheckoutMq(userId);
            ToastResultCode.USER_BALANCE_INSUFFICIENT.check(true);
        }
        //调用语音识别服务
        AsrOutput output = asrV2Client.asr(userId.toString(), input);
        //发送语音预扣费统计MQ
        input.setAiId(input.getAiId() != null ? input.getAiId() : userId);
        HashMap<Object, Object> extraMap = Maps.newHashMap();
        extraMap.put("url", input.getUrl());
        extraMap.put("asr", true);
        //异步扣费处理
        userDeductionStatSendMq(userId, input.getAiId(), extraMap);
        return output;
    }

    @Override
    public String tts(Long userId, VoiceTtsV2Input input) {
        String tts = "";
        if (input.getAiId() != null) {
            //检测余额是否不足
            boolean balanceIsInsufficient = checkBalanceIsInsufficient(userId, VOICE_DEDUCTION_AMOUNT);
            if (balanceIsInsufficient) {
                //余额不足，发送MQ，余额不足处理
                commonSendMqService.userBalanceInsufficientCheckoutMq(userId);
                ToastResultCode.USER_BALANCE_INSUFFICIENT.check(true);
            }
            //调用文本转语音服务
            tts = ttsV3Client.tts(userId.toString(), input);
            //发送语音使用统计MQ
            input.setAiId(input.getAiId() != null ? input.getAiId() : userId);
            HashMap<Object, Object> extraMap = Maps.newHashMap();
            extraMap.put("text", input.getText());
            extraMap.put("tts", true);
            userDeductionStatSendMq(userId, input.getAiId(), extraMap);
        } else {
            //创建，编辑语音合成，1分钟内20次的限制
            boolean b = limitUtils.defaultLimitCheckByKey(redisKeyUtils.ttsMinuteLimitKey(userId), 20, 60);
            ToastResultCode.REQUEST_LIMIT_ERROR.check(b);
            //调用文本转语音服务
            tts = ttsV3Client.tts(userId.toString(), input);
        }
        return tts;
    }

    @Override
    public void ttsDeAmount(Long userId, Long aiId) {
        if(aiId == null) {
            //做一个限流，防刷(24小时内最多只能有20次免费调用次数)
            boolean bl = limitUtils.defaultLimitCheckByKey(redisKeyUtils.ttsDeAmountLimitKey(userId), 20, 60 * 60 * 24);
            ToastResultCode.USER_BALANCE_INSUFFICIENT.check(bl);
            return;
        }
        //检测余额是否不足
        boolean balanceIsInsufficient = checkBalanceIsInsufficient(userId, VOICE_DEDUCTION_AMOUNT);
        if (balanceIsInsufficient) {
            //余额不足，发送MQ，余额不足处理
            commonSendMqService.userBalanceInsufficientCheckoutMq(userId);
            ToastResultCode.USER_BALANCE_INSUFFICIENT.check(true);
        }
    }


    /**
     * 发送用户语音使用统计MQ
     *
     * @param userId
     * @param aiId
     * @param extraMap
     */
    private void userDeductionStatSendMq(Long userId, Long aiId, HashMap<Object, Object> extraMap) {
        commonSendMqService.userDeductionStatSendMq(UserDeductionStatPayload.builder()
                .userId(userId)
                .aiId(aiId)
                .deductionType(DeductionTypeEnum.VOICE)
                .bizTime(LocalDateTime.now())
                .extra(JSON.toJSONString(extraMap))
                .build());
    }


    /**
     * 检测余额是否不足
     *
     * @param userId
     * @param amount 本次金额
     * @return
     */
    @Override
    public boolean checkBalanceIsInsufficient(Long userId, Long amount) {
        try {
            AccountBuffOutput accountBuff = payClient.getAccountBuff(userId);
            Long balance = accountBuff != null && accountBuff.getBalance() > 0 ? accountBuff.getBalance() : 0;
            log.info("checkBalanceIsInsufficient balance:{},totalDeductionAmount:{}", balance,  amount);
            if (balance < amount) {
                return true;
            }
        } catch (Exception e) {
            log.error("checkBalanceIsInsufficient error:", e);
        }
        return false;
    }
}