package com.izouma.nineth.service;

import com.alibaba.fastjson.JSONObject;
import com.izouma.nineth.config.GeneralProperties;
import com.izouma.nineth.domain.*;
import com.izouma.nineth.enums.MintOrderStatus;
import com.izouma.nineth.enums.OrderStatus;
import com.izouma.nineth.enums.PayMethod;
import com.izouma.nineth.event.OrderNotifyEvent;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.*;
import com.izouma.nineth.utils.DateTimeUtils;
import com.izouma.nineth.utils.SnowflakeIdWorker;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;

@Service
@Slf4j
@AllArgsConstructor
public class OrderPayService {
    private static String PAY_CHANNEL = "sandPay";

    private final OrderRepo          orderRepo;
    private final MintOrderRepo      mintOrderRepo;
    private final GiftOrderRepo      giftOrderRepo;
    private final SandPayService     sandPayService;
    private final HMPayService       hmPayService;
    private final GeneralProperties  generalProperties;
    private final UserBalanceService userBalanceService;
    private final RocketMQTemplate   rocketMQTemplate;
    private final GiftOrderService   giftOrderService;
    private final MintOrderService   mintOrderService;
    private final UserRepo           userRepo;
    private final SnowflakeIdWorker  snowflakeIdWorker;
    private final RechargeOrderRepo  rechargeOrderRepo;
    private final SysConfigService   sysConfigService;

    public static void setPayChannel(String payChannel) {
        if ("hmPay".equals(payChannel) || "sandPay".equals(payChannel)) {
            PAY_CHANNEL = payChannel;
        }
    }

    @Cacheable(value = "payOrder", key = "'order#'+#orderId")
    public String payOrder(Long orderId) {
        Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
        if (order.getStatus() != OrderStatus.NOT_PAID) {
            throw new BusinessException("订单状态错误");
        }
        switch (PAY_CHANNEL) {
            case "sandPay":
                return sandPayService.requestAlipay(orderId + "", order.getTotalPrice(), order.getName(),
                        order.getName(), SandPayService.getTimeout(order.getCreatedAt(), 180),
                        "{\"type\":\"order\",\"id\":\"" + orderId + "\"}");
            case "hmPay":
                return hmPayService.requestAlipay(orderId + "", order.getTotalPrice(), order.getName(),
                        HMPayService.getTimeout(order.getCreatedAt(), 180),
                        "order", generalProperties.getHost() + "/9th/orderDetail?id=" + orderId);
        }
        throw new BusinessException("绿洲宇宙冷却系统已启动，请稍后支付");
    }

    public void payOrderBalance(Long orderId, Long userId, String tradeCode) {
        Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
        if (order.getStatus() != OrderStatus.NOT_PAID) {
            throw new BusinessException("订单状态错误");
        }
        if (!Objects.equals(order.getUserId(), userId)) {
            throw new BusinessException("订单不属于该用户");
        }
        if (!Objects.equals(userRepo.findTradeCode(userId), tradeCode)) {
            throw new BusinessException("交易码错误");
        }
        BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getTotalPrice(), orderId, order.getName());
        rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
                new OrderNotifyEvent(orderId, PayMethod.BALANCE, record.getId().toString(), System.currentTimeMillis()));
    }

    @Cacheable(value = "payOrder", key = "'gift#'+#orderId")
    public String payGiftOrder(Long orderId) {
        GiftOrder order = giftOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
        if (order.getStatus() != OrderStatus.NOT_PAID) {
            throw new BusinessException("订单状态错误");
        }
        switch (PAY_CHANNEL) {
            case "sandPay":
                return sandPayService.requestAlipay(orderId + "", order.getGasPrice(),
                        "转赠" + order.getAssetId(), "转赠" + order.getAssetId(),
                        SandPayService.getTimeout(order.getCreatedAt(), 180),
                        "{\"type\":\"gift\",\"id\":\"" + orderId + "\"}");
            case "hmPay":
                return hmPayService.requestAlipay(orderId + "", order.getGasPrice(),
                        "转赠" + order.getAssetId(),
                        HMPayService.getTimeout(order.getCreatedAt(), 180),
                        "gift", generalProperties.getHost() + "/9th/home");
        }
        throw new BusinessException("绿洲宇宙冷却系统已启动，请稍后支付");
    }

    public void payGiftBalance(Long orderId, Long userId, String tradeCode) {
        GiftOrder order = giftOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
        if (order.getStatus() != OrderStatus.NOT_PAID) {
            throw new BusinessException("订单状态错误");
        }
        if (!Objects.equals(order.getUserId(), userId)) {
            throw new BusinessException("订单不属于该用户");
        }
        if (!Objects.equals(userRepo.findTradeCode(userId), tradeCode)) {
            throw new BusinessException("交易码错误");
        }
        BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getGasPrice(), orderId, "转赠");
        giftOrderService.giftNotify(orderId, PayMethod.BALANCE, record.getId().toString());
    }

    @Cacheable(value = "payOrder", key = "'mintOrder#'+#orderId")
    public String payMintOrder(Long orderId) {
        MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
        if (order.getStatus() != MintOrderStatus.NOT_PAID) {
            throw new BusinessException("订单状态错误");
        }
        switch (PAY_CHANNEL) {
            case "sandPay":
                return sandPayService.requestAlipay(orderId + "", order.getGasPrice(),
                        "铸造活动:" + order.getMintActivityId(), "铸造活动:" + order.getMintActivityId(),
                        SandPayService.getTimeout(order.getCreatedAt(), 180),
                        "{\"type\":\"mintOrder\",\"id\":\"" + orderId + "\"}");
            case "hmPay":
                return hmPayService.requestAlipay(orderId + "", order.getGasPrice(),
                        "铸造活动:" + order.getMintActivityId(),
                        HMPayService.getTimeout(order.getCreatedAt(), 180),
                        "mintOrder", generalProperties.getHost() + "/9th/home");
        }
        throw new BusinessException("绿洲宇宙冷却系统已启动，请稍后支付");
    }

    public void payMintOrderBalance(Long orderId, Long userId, String tradeCode) {
        MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
        if (order.getStatus() != MintOrderStatus.NOT_PAID) {
            throw new BusinessException("订单状态错误");
        }
        if (!Objects.equals(order.getUserId(), userId)) {
            throw new BusinessException("订单不属于该用户");
        }
        if (!Objects.equals(userRepo.findTradeCode(userId), tradeCode)) {
            throw new BusinessException("交易码错误");
        }
        BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getGasPrice(), orderId, "铸造活动");
        giftOrderService.giftNotify(orderId, PayMethod.BALANCE, record.getId().toString());
    }

    public String recharge(Long userId, BigDecimal amount) {
        BigDecimal minAmount = sysConfigService.getBigDecimal("min_recharge_amount");
        if (amount.compareTo(minAmount) < 0) {
            throw new BusinessException("充值金额不能小于" + minAmount);
        }
        RechargeOrder order = RechargeOrder.builder()
                .id(snowflakeIdWorker.nextId())
                .userId(userId)
                .amount(amount)
                .status(OrderStatus.NOT_PAID)
                .build();
        rechargeOrderRepo.save(order);
        switch (PAY_CHANNEL) {
            case "sandPay":
                return sandPayService.requestAlipay(order.getId() + "", order.getAmount(),
                        "余额充值", "余额充值",
                        SandPayService.getTimeout(order.getCreatedAt(), 180),
                        "{\"type\":\"recharge\",\"id\":\"" + order.getId() + "\"}");
            case "hmPay":
                return hmPayService.requestAlipay(order.getId() + "", order.getAmount(),
                        "余额充值",
                        HMPayService.getTimeout(order.getCreatedAt(), 180),
                        "recharge", generalProperties.getHost() + "/9th/home");
        }
        throw new BusinessException("绿洲宇宙冷却系统已启动，请稍后支付");
    }
}
