package com.ylx.giftCard.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.ylx.common.core.domain.model.WxLoginUser;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.DateUtils;
import com.ylx.giftCard.domain.GiftCard;
import com.ylx.giftCard.domain.GiftCardOrder;
import com.ylx.giftCard.domain.dto.GiftCardOrderQueryDTO;
import com.ylx.giftCard.domain.dto.UserShoppingFundsDetailQueryDTO;
import com.ylx.giftCard.domain.vo.*;
import com.ylx.giftCard.enums.GiftCardOrderStatusEnum;
import com.ylx.giftCard.mapper.GiftCardOrderMapper;
import com.ylx.giftCard.service.IGiftCardOrderService;
import com.ylx.massage.domain.MaTechnician;
import com.ylx.massage.domain.TWxUser;
import com.ylx.massage.service.IMaTechnicianService;
import com.ylx.massage.service.TWxUserService;
import com.ylx.shopingfundsdetail.domain.vo.ShoppingFundsDetailAddDto;
import com.ylx.shopingfundsdetail.enums.ShoppingFundsExpenseTypeEnum;
import com.ylx.shopingfundsdetail.mapper.ShoppingFundsDetailMapper;
import com.ylx.shopingfundsdetail.service.ShoppingFundsDetailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

@Slf4j
@Service
public class GiftCardOrderServiceImpl extends ServiceImpl<GiftCardOrderMapper, GiftCardOrder> implements IGiftCardOrderService {

    @Resource
    private IMaTechnicianService maTechnicianService;
    @Resource
    private TWxUserService wxUserService;
    @Resource
    private ShoppingFundsDetailService shoppingFundsDetailService;
    @Resource
    private ShoppingFundsDetailMapper shoppingFundsDetailMapper;

    private static final int DETAIL_TYPE_PURCHASE = 0;
    private static final int DETAIL_TYPE_EXPENSE = 1;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public GiftCardOrder buildOrder(GiftCard card, Integer quantity, String merchantId, WxLoginUser wxLoginUser) {

        // 1. 参数校验
        if (ObjectUtil.isNull(card)) {
            throw new ServiceException("购物卡信息不能为空");
        }
        if (ObjectUtil.isNull(quantity) || quantity <= 0) {
            throw new ServiceException("购买数量必须大于0");
        }

        // 2. 创建订单对象
        GiftCardOrder order = new GiftCardOrder();

        // 4. 生成唯一订单号（使用更安全的方式）
        String orderNo = generateUniqueOrderNo();
        order.setOrderNo(orderNo);

        // 5. 设置购物卡信息
        setGiftCardInfo(order, card);

        // 6. 设置用户信息
        setUserInfo(order, wxLoginUser);

        // 7. 设置商户信息
        setMerchantInfo(order, merchantId);

        // 8. 计算金额
        calculateAmount(order, card, quantity);
        order.setPurchaseQuantity(quantity);

        // 9. 设置订单状态和时间
        order.setStatus(GiftCardOrderStatusEnum.WAIT_PAY.getCode()); // 待支付
        order.setCreateTime(DateUtils.getNowDate());
        order.setUpdateTime(order.getCreateTime());
        int rowsAffected = this.baseMapper.insert(order);
        if (rowsAffected <= 0) {
            log.warn("购物卡订单创建失败，购物卡ID: {}，下单人ID: {}", card.getId(), wxLoginUser.getId());
            return null;
        }
        return order;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(Long id) {
        // 1. 查询订单
        GiftCardOrder order = this.getById(id);
        if (ObjectUtil.isNull(order)) {
            throw new ServiceException("订单不存在");
        }
        // 仅待支付订单可取消
        if (!GiftCardOrderStatusEnum.PAID.getCode().equals(order.getStatus())) {
            throw new ServiceException("当前订单状态不支持取消");
        }
        // 2. 修改订单状态为已取消
        order.setStatus(GiftCardOrderStatusEnum.CANCEL.getCode());
        order.setUpdateTime(DateUtils.getNowDate());
        boolean update = this.updateById(order);
        if (!update) {
            log.error("订单取消失败，订单号:{}", order.getOrderNo());
            throw new ServiceException("订单取消失败");
        }
        log.info("订单取消成功，订单号:{},购物卡ID:{}", order.getOrderNo(), order.getGiftCardId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processGiftCardPayment(WxPayOrderNotifyV3Result.DecryptNotifyResult result, TWxUser wxUser,GiftCardOrder cardOrder) {

        // 更新订单状态
        this.lambdaUpdate()
                .set(GiftCardOrder::getStatus, GiftCardOrderStatusEnum.PAID.getCode())
                .eq(GiftCardOrder::getId, cardOrder.getId())
                .update();

        // 计算充值金额
        Integer totalCent = result.getAmount().getTotal();
        BigDecimal payAmount = new BigDecimal(totalCent).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP);

        // 更新用户余额
        BigDecimal oldBalance = wxUser.getdBalance();
        BigDecimal newBalance = oldBalance.add(payAmount);
        this.wxUserService.lambdaUpdate()
                .set(TWxUser::getdBalance, newBalance)
                .eq(TWxUser::getId, wxUser.getId())
                .update();

        // 记录购物金明细
        ShoppingFundsDetailAddDto dto = new ShoppingFundsDetailAddDto();
        dto.setUserId(wxUser.getId());
        dto.setAmount(payAmount);
        dto.setOrderNo(result.getOutTradeNo());
        dto.setExpenseType(ShoppingFundsExpenseTypeEnum.RECHARGE.getCode());
        dto.setBalance(newBalance);
        dto.setGiftCardId(cardOrder.getGiftCardId());
        shoppingFundsDetailService.addShoppingFundsDetail(dto);
    }

    @Override
    public Page<GiftCardOrderPageVO> getAdminGiftCardOrderPage(Page<GiftCardOrderPageVO> page, GiftCardOrderQueryDTO dto) {
        GiftCardOrderQueryDTO query = dto == null ? new GiftCardOrderQueryDTO() : dto;
        normalizeOrderTimeRange(query);
        return baseMapper.selectAdminGiftCardOrderPage(page, query);
    }

    @Override
    public List<GiftCardOrderExportVO> getAdminGiftCardOrderExportList(GiftCardOrderQueryDTO dto) {
        GiftCardOrderQueryDTO query = dto == null ? new GiftCardOrderQueryDTO() : dto;
        normalizeOrderTimeRange(query);
        return baseMapper.selectAdminGiftCardOrderExportList(query);
    }

    @Override
    public UserShoppingFundsDetailVO getPcUserShoppingFundsDetail(Page<UserShoppingFundsDetailItemVO> page, UserShoppingFundsDetailQueryDTO dto) {
        validateShoppingFundsDetailQuery(dto);
        normalizeTimeRange(dto);

        TWxUser user = wxUserService.getById(dto.getUserId());
        if (ObjectUtil.isNull(user)) {
            throw new IllegalArgumentException("用户不存在");
        }

        UserShoppingFundsSummaryVO summary;
        Page<UserShoppingFundsDetailItemVO> detailPage;
        // 支出
        if (DETAIL_TYPE_EXPENSE == dto.getDetailType()) {
            summary = shoppingFundsDetailMapper.selectPcExpenseShoppingFundsSummary(dto);
            detailPage = shoppingFundsDetailMapper.selectPcExpenseShoppingFundsDetail(page, dto);
        } else {
            // 购买
            summary = baseMapper.selectPcPurchaseShoppingFundsSummary(dto);
            detailPage = baseMapper.selectPcPurchaseShoppingFundsDetail(page, dto);
        }

        UserShoppingFundsDetailVO vo = new UserShoppingFundsDetailVO();
        vo.setShoppingFundsBalance(defaultAmount(user.getdBalance()));
        vo.setTotalAmount(defaultAmount(summary == null ? null : summary.getTotalAmount()));
        vo.setTotalCount(summary == null || summary.getTotalCount() == null ? 0L : summary.getTotalCount());
        vo.setPage(detailPage);
        return vo;
    }

    /**
     * 校验购物金明细查询参数
     * @param dto
     */
    private void validateShoppingFundsDetailQuery(UserShoppingFundsDetailQueryDTO dto) {
        if (dto.getDetailType() == null) {
            dto.setDetailType(DETAIL_TYPE_PURCHASE);
        }
        if (dto.getDetailType() != DETAIL_TYPE_PURCHASE && dto.getDetailType() != DETAIL_TYPE_EXPENSE) {
            throw new IllegalArgumentException("明细类型不正确");
        }
    }

    /**
     * 格式化时间范围
     * @param dto
     */
    private void normalizeTimeRange(UserShoppingFundsDetailQueryDTO dto) {
        if (StringUtils.isNotBlank(dto.getStartTime()) && dto.getStartTime().trim().length() == 10) {
            dto.setStartTime(dto.getStartTime().trim() + " 00:00:00");
        }
        if (StringUtils.isNotBlank(dto.getEndTime()) && dto.getEndTime().trim().length() == 10) {
            dto.setEndTime(dto.getEndTime().trim() + " 23:59:59");
        }
    }

    /**
     * 格式化购物卡订单查询时间范围
     * @param dto
     */
    private void normalizeOrderTimeRange(GiftCardOrderQueryDTO dto) {
        if (StringUtils.isNotBlank(dto.getStartTime()) && dto.getStartTime().trim().length() == 10) {
            dto.setStartTime(dto.getStartTime().trim() + " 00:00:00");
        }
        if (StringUtils.isNotBlank(dto.getEndTime()) && dto.getEndTime().trim().length() == 10) {
            dto.setEndTime(dto.getEndTime().trim() + " 23:59:59");
        }
    }

    private BigDecimal defaultAmount(BigDecimal amount) {
        return amount == null ? BigDecimal.ZERO : amount;
    }

    /**
     * 生成唯一订单号
     */
    private String generateUniqueOrderNo() {
        // 使用时间戳 + 随机数 + 更多信息避免冲突
        long timestamp = System.currentTimeMillis();
        String randomNum = RandomUtil.randomNumbers(6);
        // 可以加入用户ID后几位、线程ID等进一步降低冲突概率
        String suffix = String.valueOf(timestamp % 1000000).substring(0, 3); // 取时间戳后3位
        return "GC" + timestamp + randomNum + suffix;
    }

    /**
     * 设置购物卡信息
     */
    private void setGiftCardInfo(GiftCardOrder order, GiftCard card) {
        order.setGiftCardId(card.getId());
        order.setGiftCardName(card.getName());
        order.setGiftCardAmount(card.getAmount());
        order.setCommissionRate(card.getCommissionRate());
    }

    /**
     * 设置用户信息
     */
    private void setUserInfo(GiftCardOrder order, WxLoginUser wxLoginUser) {
        order.setUserId(wxLoginUser.getId());
        order.setUserName(wxLoginUser.getCNickName());
        order.setUserPhone(wxLoginUser.getCPhone());
    }

    /**
     * 设置商户信息
     */
    private void setMerchantInfo(GiftCardOrder order, String merchantId) {
        if (StrUtil.isEmpty(merchantId)) {
            log.warn("商户ID为空，跳过商户信息查询");
            return;
        }

        MaTechnician maTechnician = this.maTechnicianService.getById(merchantId);
        if (ObjectUtil.isNotNull(maTechnician)) {
            order.setMerchantId(merchantId);
            order.setMerchantName(maTechnician.getTeName());
            order.setMerchantNickName(maTechnician.getTeNickName());
            // 注意：如果 TJs 表有收款账号字段，可以在这里设置
            // order.setMerchantAccount(merchant.getAccount());
        }
    }

    /**
     * 计算金额
     */
    private void calculateAmount(GiftCardOrder order, GiftCard card, Integer quantity) {
        BigDecimal payAmount = card.getAmount()
                .multiply(new BigDecimal(quantity))
                .setScale(2, RoundingMode.HALF_UP); // 保留两位小数

        order.setPayAmount(payAmount);

        BigDecimal commissionAmount = payAmount
                .multiply(card.getCommissionRate())
                .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);

        order.setCommissionAmount(commissionAmount);
    }
}
