package com.ylx.massage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.core.domain.model.WxLoginUser;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.SecurityUtils;
import com.ylx.massage.domain.AfterSaleOrder;
import com.ylx.massage.domain.ProductOrderInfo;
import com.ylx.massage.domain.ProductOrderPayment;
import com.ylx.massage.domain.dto.AfterSaleOrderDTO;
import com.ylx.massage.domain.dto.AfterSaleOrderUpdateDTO;
import com.ylx.massage.domain.vo.OrderAfterSaleVo;
import com.ylx.massage.enums.AfterSaleStatusEnum;
import com.ylx.massage.enums.AfterSaleTypeEnum;
import com.ylx.massage.enums.ProductOrderStatusEnum;
import com.ylx.massage.mapper.AfterSaleOrderMapper;
import com.ylx.massage.mapper.ProductOrderPaymentMapper;
import com.ylx.massage.service.IAfterSaleOrderService;
import com.ylx.massage.service.IProductOrderInfoService;
import com.ylx.massage.service.TRechargeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Service
@Slf4j
public class AfterSaleOrderServiceImpl extends ServiceImpl<AfterSaleOrderMapper, AfterSaleOrder> implements IAfterSaleOrderService {

    @Resource
    private AfterSaleOrderMapper afterSaleOrderMapper;
    @Resource
    private IProductOrderInfoService productOrderInfoService;
    @Resource
    private ProductOrderPaymentMapper productOrderPaymentMapper;
    @Resource
    private TRechargeService rechargeService;
    @Resource
    private com.ylx.point.service.IPointAccountService pointAccountService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(AfterSaleOrderDTO dto) {
        // 1. 获取当前登录用户（公共方法提取）
        WxLoginUser loginUser = getCurrentWxLoginUser();

        // 2. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = this.productOrderInfoService.getAndCheckOrder(dto.getOrderId(), loginUser.getCOpenid());

        // 3. 校验订单状态是否允许售后
        Integer orderStatus = productOrderInfo.getOrderStatus();
        log.info("订单状态：{}", orderStatus);
        // 明确不允许的状态
        if (orderStatus == 0) {
            throw new ServiceException("待付款订单请直接取消");
        }
        if (orderStatus == 1) {
            throw new ServiceException("待发货订单请申请取消");
        }
        if (orderStatus == 4) {
            throw new ServiceException("售后申请已在处理中");
        }
        if (orderStatus == 11) {
            throw new ServiceException("已取消订单不支持售后");
        }
        // 只允许 2（待收货）或者3（已收货）发起售后
        if (orderStatus != 2 && orderStatus != 3) {
            throw new ServiceException("当前订单状态不支持发起售后");
        }

        // 4. 添加售后订单
        AfterSaleOrder entity = new AfterSaleOrder();
        BeanUtil.copyProperties(dto, entity);
        entity.setOpenId(loginUser.getCOpenid());
        entity.setCreateTime(LocalDateTime.now());
        entity.setAfterSaleStatus(AfterSaleStatusEnum.WAIT_AUDIT.getCode());
        // 生成售后单号
        entity.setAfterSaleNo(generateAfterSaleNo(dto.getOrderId()));

        boolean insertResult = super.save(entity);
        if (!insertResult) {
            throw new ServiceException("创建售后订单失败");
        }

        // 5. 更新订单状态
        ProductOrderInfo updateInfo = new ProductOrderInfo();
        updateInfo.setId(productOrderInfo.getId());
        // 修改订单状态：售后中
        updateInfo.setOrderStatus(ProductOrderStatusEnum.AFTER_SALES.getCode());
        updateInfo.setUpdateTime(LocalDateTime.now());

        boolean updateResult = this.productOrderInfoService.updateById(updateInfo);
        if (!updateResult) {
            throw new ServiceException("订单状态变更失败");
        }
    }

    @Override
    public OrderAfterSaleVo getOrderAfterSaleVo(Long orderId) {
        return this.afterSaleOrderMapper.selectAfterSaleVoByOrderId(orderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(AfterSaleOrderUpdateDTO dto) {

        // 1. 校验参数
        Long id = dto.getAfterSaleOrderId();
        if (ObjectUtil.isNull(id)) {
            throw new IllegalArgumentException("售后单ID不能为空");
        }

        // 2. 获取“等待用户寄回”的售后单
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getId, id)
                .eq(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.WAITING_USER_RETURN.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("等待用户寄回售后单不存在");
        }

        AfterSaleOrder updateInfo = new AfterSaleOrder();
        updateInfo.setId(id);
        updateInfo.setLogisticsNo(dto.getLogisticsNo());
        updateInfo.setUpdateTime(LocalDateTime.now());
        updateInfo.setAfterSaleStatus(AfterSaleStatusEnum.WAITING_MERCHANT_RECEIVE.getCode());

        boolean updateResult = this.updateById(updateInfo);
        if (!updateResult) {
            throw new ServiceException("取消售后单填写物流单号失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long orderId) {

        // 1. 获取当前登录用户（公共方法提取）
        WxLoginUser loginUser = getCurrentWxLoginUser();

        // 2. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = this.productOrderInfoService.getAndCheckOrder(orderId, loginUser.getCOpenid());

        // 3. 状态校验：必须是 售后中 才能取消
        if (!ProductOrderStatusEnum.AFTER_SALES.getCode().equals(productOrderInfo.getOrderStatus())) {
            throw new ServiceException("订单状态异常，仅售后中状态可取消售后");
        }

        // 4. 取消售后订单(待审核 或 等待用户寄回)
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, orderId)
                .eq(AfterSaleOrder::getOpenId, loginUser.getCOpenid())
                .in(AfterSaleOrder::getAfterSaleStatus,
                        AfterSaleStatusEnum.WAIT_AUDIT.getCode(),
                        AfterSaleStatusEnum.WAITING_USER_RETURN.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("未找到可取消的售后订单");
        }

        // 更新售后订单状态为已取消
        afterSaleOrder.setAfterSaleStatus(AfterSaleStatusEnum.CANCELLED.getCode());
        afterSaleOrder.setUpdateTime(LocalDateTime.now());
        boolean afterSaleUpdateResult = this.updateById(afterSaleOrder);
        if (!afterSaleUpdateResult) {
            throw new ServiceException("取消售后订单失败");
        }

        // 5. 更新订单状态
        ProductOrderInfo updateInfo = new ProductOrderInfo();
        updateInfo.setId(productOrderInfo.getId());
        updateInfo.setOrderStatus(ProductOrderStatusEnum.WAIT_RECEIVE.getCode());
        updateInfo.setUpdateTime(LocalDateTime.now());

        boolean orderUpdateResult = this.productOrderInfoService.updateById(updateInfo);
        if (!orderUpdateResult) {
            throw new ServiceException("订单状态变更失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editByWechat(AfterSaleOrderUpdateDTO dto) {

        Long orderId = dto.getOrderId();

        if (ObjectUtil.isNull(orderId)) {
            throw new IllegalArgumentException("订单ID不能为空");
        }

        // 1. 获取当前登录用户（公共方法提取）
        WxLoginUser loginUser = getCurrentWxLoginUser();

        // 2. 查询并校验订单（公共方法提取）
        this.productOrderInfoService.getAndCheckOrder(orderId, loginUser.getCOpenid());

        // 3. 获取“同意退货/换货”的售后单
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, orderId)
                .eq(AfterSaleOrder::getOpenId, loginUser.getCOpenid())
                .eq(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.WAITING_USER_RETURN.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("等待用户寄回售后单不存在");
        }

        // 4. 更新售后单信息
        AfterSaleOrder updateInfo = new AfterSaleOrder();
        updateInfo.setId(afterSaleOrder.getId());
        updateInfo.setLogisticsNo(dto.getLogisticsNo());
        updateInfo.setUpdateTime(LocalDateTime.now());
        updateInfo.setAfterSaleStatus(AfterSaleStatusEnum.WAITING_MERCHANT_RECEIVE.getCode());

        boolean updateResult = this.updateById(updateInfo);
        if (!updateResult) {
            throw new ServiceException("取消售后单填写物流单号失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreeReturn(Long orderId) {

        // 1. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = this.productOrderInfoService.getAndCheckOrder(orderId, null);

        // 2. 状态校验：必须是 售后中 才能同意退货
        if (!ProductOrderStatusEnum.AFTER_SALES.getCode().equals(productOrderInfo.getOrderStatus())) {
            throw new ServiceException("订单状态异常，仅售后中状态可同意退货");
        }

        // 3. 判断售后单的状态为退货
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, orderId)
                .eq(AfterSaleOrder::getAfterSaleType, AfterSaleTypeEnum.RETURN_GOODS.getCode())
                .eq(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.WAIT_AUDIT.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("未找到待审核的退货的售后单");
        }

        // 4. 更新售后订单状态为等待用户寄回
        afterSaleOrder.setAfterSaleStatus(AfterSaleStatusEnum.WAITING_USER_RETURN.getCode());
        afterSaleOrder.setUpdateTime(LocalDateTime.now());
        boolean afterSaleUpdateResult = this.updateById(afterSaleOrder);
        if (!afterSaleUpdateResult) {
            throw new ServiceException("更新售后单失败");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreeExchange(Long orderId) {
        // 1. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = this.productOrderInfoService.getAndCheckOrder(orderId, null);

        // 2. 状态校验：必须是 售后中 才能同意退货
        if (!ProductOrderStatusEnum.AFTER_SALES.getCode().equals(productOrderInfo.getOrderStatus())) {
            throw new ServiceException("订单状态异常，仅售后中状态可同意换货");
        }

        // 3. 判断售后单的状态为换货
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, orderId)
                .eq(AfterSaleOrder::getAfterSaleType, AfterSaleTypeEnum.EXCHANGE_GOODS.getCode())
                .eq(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.WAIT_AUDIT.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("未找到待审核的换货的售后单");
        }

        // 4. 更新售后订单状态为等待用户寄回
        afterSaleOrder.setAfterSaleStatus(AfterSaleStatusEnum.WAITING_USER_RETURN.getCode());
        afterSaleOrder.setUpdateTime(LocalDateTime.now());
        boolean afterSaleUpdateResult = this.updateById(afterSaleOrder);
        if (!afterSaleUpdateResult) {
            throw new ServiceException("更新售后单失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreeRefund(Long orderId) {
        // 1. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = this.productOrderInfoService.getAndCheckOrder(orderId, null);

        // 2. 获取待审核或者等待商家收货的售后单
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, orderId)
                .in(AfterSaleOrder::getAfterSaleStatus,
                        AfterSaleStatusEnum.WAIT_AUDIT.getCode(),
                        AfterSaleStatusEnum.WAITING_MERCHANT_RECEIVE.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("未找到可审核的售后单");
        }
        // 售后类型
        AfterSaleTypeEnum typeEnum = AfterSaleTypeEnum.valueOf(afterSaleOrder.getAfterSaleType());
        AfterSaleStatusEnum statusEnum = AfterSaleStatusEnum.valueOf(afterSaleOrder.getAfterSaleStatus());

        // 判断售后单的售后类型
        switch (typeEnum) {
            // 未收到货
            case NOT_RECEIVED:
                // ====================== 未收到货 → 仅退款 ======================
                if (statusEnum != AfterSaleStatusEnum.WAIT_AUDIT) {
                    throw new ServiceException("仅退款单状态异常，无法审核");
                }
                break;
            // 已收到货,退货
            case RETURN_GOODS:
                // ====================== 已收到货 → 退货退款 ======================
                if (statusEnum != AfterSaleStatusEnum.WAITING_MERCHANT_RECEIVE) {
                    throw new ServiceException("退货单需用户寄回、商家收货后才能审核退款");
                }
                break;
            default:
                throw new ServiceException("不支持的售后类型");
        }

        // 4. 判断售后单的售后类型
        if (ObjectUtil.notEqual(AfterSaleTypeEnum.RETURN_GOODS.getCode(), afterSaleOrder.getAfterSaleType())) {
            throw new ServiceException("售后单类型异常，仅退货的售后单可退货");
        }

        // 5. 查询支付记录获取微信交易流水号
        ProductOrderPayment payment = productOrderPaymentMapper.selectOne(
                new LambdaQueryWrapper<ProductOrderPayment>()
                        .eq(ProductOrderPayment::getOrderId, String.valueOf(productOrderInfo.getId()))
                        .eq(ProductOrderPayment::getPayStatus, "1"));
        if (ObjectUtil.isNull(payment)) {
            throw new ServiceException("未找到支付记录，无法退款");
        }

        // 6. 处理积分退款（如果订单使用了积分）
        if (productOrderInfo.getPointsUsed() != null && productOrderInfo.getPointsUsed() > 0) {
            // 判断支付类型
            Integer payType = productOrderInfo.getPayType();
            if (payType == 1 || payType == 3) {
                // 1-纯积分支付 或 3-积分+金额支付，需要退回积分
                String refundOrderNo = "REFUND_POINT_" + productOrderInfo.getOrderNo();
                Integer pointsToRefund = productOrderInfo.getPointsUsed();

                try {
                    Integer newBalance = pointAccountService.refundPoints(
                        productOrderInfo.getOpenId(),
                        pointsToRefund,
                        refundOrderNo,
                        "积分商品退款"
                    );
                    log.info("积分退款成功，退款积分：{}，退款后余额：{}", pointsToRefund, newBalance);
                } catch (Exception e) {
                    log.error("积分退款失败", e);
                    throw new ServiceException("积分退款失败：" + e.getMessage());
                }
            }
        }

        // 7. 调用微信退款接口
        // 生成退款单号
        String outRefundNo = generateRefundNo();
        // 退款金额
        BigDecimal refundAmount = new BigDecimal(afterSaleOrder.getApplyAmount());
        String refundResult = rechargeService.refund(outRefundNo, payment.getThirdPaymentNo(), productOrderInfo.getOrderNo(), refundAmount);
        log.info("退款结果：{}", refundResult);
        if (refundResult == null || refundResult.contains("\"code\":\"FAIL\"")) {
            throw new ServiceException("退款失败：" + refundResult);
        }

        // 7. 更新售后单数据
        afterSaleOrder.setAfterSaleStatus(AfterSaleStatusEnum.REFUND_COMPLETED.getCode());
        afterSaleOrder.setUpdateTime(LocalDateTime.now());
        boolean afterSaleUpdateResult = this.updateById(afterSaleOrder);
        if (!afterSaleUpdateResult) {
            throw new ServiceException("更新售后单失败");
        }

        // TODO 7.更新库存信息

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmReceive(Long orderId) {

        // 1. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = this.productOrderInfoService.getAndCheckOrder(orderId, null);

        // 2. 状态校验：必须是 售后中 才能确认收货
        if (!ProductOrderStatusEnum.AFTER_SALES.getCode().equals(productOrderInfo.getOrderStatus())) {
            throw new ServiceException("订单状态异常，仅售后中状态可确认收货");
        }

        // 3. 获取等待商家收货的售后单
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, orderId)
                .eq(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.WAITING_MERCHANT_RECEIVE.getCode());

        AfterSaleOrder afterSaleOrder = this.afterSaleOrderMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(afterSaleOrder)) {
            throw new ServiceException("未找到等待商家收货的售后单");
        }

        // 4. 判断售后单的售后类型
        if (ObjectUtil.notEqual(AfterSaleTypeEnum.EXCHANGE_GOODS.getCode(), afterSaleOrder.getAfterSaleType())) {
            throw new ServiceException("售后单类型异常，仅换货的售后单可换货");
        }

        // 5. 更新售后单数据
        afterSaleOrder.setAfterSaleStatus(AfterSaleStatusEnum.WAITING_MERCHANT_SHIP.getCode());
        afterSaleOrder.setUpdateTime(LocalDateTime.now());
        boolean afterSaleUpdateResult = this.updateById(afterSaleOrder);
        if (!afterSaleUpdateResult) {
            throw new ServiceException("更新售后单失败");
        }

    }

    private WxLoginUser getCurrentWxLoginUser() {
        WxLoginUser loginUser = SecurityUtils.getWxLoginUser();
        if (ObjectUtil.isNull(loginUser)) {
            throw new ServiceException("用户未登录或登录已过期");
        }
        return loginUser;
    }

    /**
     * 生成售后单号
     *
     * @param orderId 订单ID
     * @return String 售后单号
     */
    private String generateAfterSaleNo(Long orderId) {
        return "AFTERSALE" + orderId + System.currentTimeMillis();
    }

    /**
     * 生成退款单号
     *
     * @return String 退款单号
     */
    private String generateRefundNo() {
        return "REFUND" + System.currentTimeMillis();
    }

}
