package com.sonic.lion.service.impl;

import com.sonic.common.exception.BizExceptionUtils;
import com.sonic.common.exception.SysExceptionUtils;
import com.sonic.common.rpc.Result;
import com.sonic.lion.domain.entity.PayCallChannelRecord;
import com.sonic.lion.domain.entity.PayTrade;
import com.sonic.lion.domain.enums.CallChannelStatus;
import com.sonic.lion.domain.input.CheckoutInput;
import com.sonic.lion.domain.output.SyncChannelOutput;
import com.sonic.lion.domain.req.CheckoutReq;
import com.sonic.lion.domain.req.TradeQueryReq;
import com.sonic.lion.domain.resp.CheckoutResp;
import com.sonic.lion.domain.resp.QueryResp;
import com.sonic.lion.enums.BizType;
import com.sonic.lion.enums.PaymentType;
import com.sonic.lion.enums.ToastResultCode;
import com.sonic.lion.enums.TradeStatus;
import com.sonic.lion.service.CashierService;
import com.sonic.lion.service.PayCallChannelService;
import com.sonic.lion.service.PayConfigService;
import com.sonic.lion.service.PayTradeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CashierServiceImpl implements CashierService {

    @Autowired
    private PayTradeService payTradeService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private PayConfigService payConfigService;
    @Autowired
    private PayCallChannelService payCallChannelService;
    @Autowired
    private TradeHandler tradeHandler;

    @Override
    public CheckoutResp checkout(Long userId, CheckoutReq req) {
        SysExceptionUtils.check(req.getPaymentType() == PaymentType.CHANNEL && req.getPayChannel() == null, "", "渠道支付时payChannel不能为null");
        //支付渠道开关控制
        String errorMessage = stringRedisTemplate.opsForValue().get("charge:enable:tips:" + req.getPayChannel().getValue());
        BizExceptionUtils.check(StringUtils.isNotEmpty(errorMessage), "99990001", errorMessage);

        //校验渠道开关是否打开
        boolean channelSwitchBl = payConfigService.paymentChannelSwitchCheckPass(userId, req.getPayChannel());
        ToastResultCode.CHANNEL_NOT_OPEN.check(!channelSwitchBl);

        //结账扣款
        CheckoutInput input = CheckoutInput.builder()
                .uid(userId)
                .tradeNo(req.getTradeNo())
                .payChannel(req.getPayChannel())
                .paymentType(req.getPaymentType())
                .returnUrl(req.getReturnUrl())
                .cancelUrl(req.getCancelUrl())
                .build();
        return payTradeService.checkout(input);
    }

    @Override
    public Result<QueryResp> query(TradeQueryReq req) {
        QueryResp resp = new QueryResp();
        //查询渠道表是否存在
        PayCallChannelRecord payCallChannelRecord = payCallChannelService.get(req.getSubmitId());
        if (payCallChannelRecord == null) {
            return Result.success(resp);
        }
        PayTrade payTrade = payTradeService.getByTradeNo(payCallChannelRecord.getTradeNo());
        if (payTrade == null) {
            return Result.success(resp);
        }

        if (StringUtils.isNotBlank(payTrade.getPaymentTradeNo())) {
            PayTrade paymentTrade = payTradeService.getByTradeNo(payTrade.getPaymentTradeNo());
            if (paymentTrade != null && TradeStatus.WAITPAY.equals(paymentTrade.getStatus()) && TradeStatus.FINISHED.equals(payTrade.getStatus())) {

                ToastResultCode.GAME_PAY_FAIL.check(true);
            }
        }

        if (BizType.CHARGE.equals(payTrade.getBizType())) {
            resp.setChargeAmount(payTrade.getAmount());
        }
        resp.setTradeNo(payTrade.getTradeNo());
        resp.setTradeStatus(payTrade.getStatus());
        if (payTrade.getPaymentTradeNo() != null) {
            PayTrade paymentTrade = payTradeService.getByTradeNo(payTrade.getPaymentTradeNo());
            resp.setPaymentTradeNo(paymentTrade.getTradeNo());
            resp.setPaymentTradeOrderNo(paymentTrade.getOutTradeNo());
            resp.setPaymentBizType(paymentTrade.getBizType());
        }

        //交易关闭 返回相关信息
        if (payTrade.getStatus().equals(TradeStatus.CLOSED)) {
            String errorMessage =payTrade.getErrorMessage() ;
            Result result = Result.error("00000000",errorMessage);
            result.setContent(resp);
            return result;
        }
        if (payTrade.getStatus().equals(TradeStatus.REFUNDED)) {
            Result result = Result.error("00000000", payTrade.getErrorMessage());
            result.setContent(resp);
            return result;
        }

        //如果渠道调用状态是 处理中 同步查询调用状态
        if (payCallChannelRecord.getStatus().equals(CallChannelStatus.PROCESSING) || payCallChannelRecord.getStatus().equals(CallChannelStatus.INIT)) {
            try{
                SyncChannelOutput syncChannelOutput = tradeHandler.syncOrder(payCallChannelRecord);
                resp.setTradeStatus(CallChannelStatus.toTradeStatus(syncChannelOutput.getCallChannelStatus()));
                if (resp.getTradeStatus().equals(TradeStatus.CLOSED)) {
                    Result result = Result.error("00000000", payTrade.getErrorMessage());
                    result.setContent(resp);
                    return result;
                }
            }catch (Exception e){
                payTrade = payTradeService.getByTradeNo(payCallChannelRecord.getTradeNo());
                resp.setTradeNo(payTrade.getTradeNo());
                resp.setTradeStatus(payTrade.getStatus());
                if (payTrade.getPaymentTradeNo() != null) {
                    PayTrade paymentTrade = payTradeService.getByTradeNo(payTrade.getPaymentTradeNo());
                    resp.setPaymentTradeNo(paymentTrade.getTradeNo());
                    resp.setPaymentTradeOrderNo(paymentTrade.getOutTradeNo());
                    resp.setPaymentBizType(paymentTrade.getBizType());
                }
                return Result.success(resp);
            }
        }
        return Result.success(resp);
    }

}
