package com.seer.teach.mall.order.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.seer.teach.common.PageListBean;
import com.seer.teach.common.enums.AfterSaleStatusEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.enums.pay.PayChannelEnum;
import com.seer.teach.common.enums.pay.RefundTypeEnum;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.MoneyUtil;
import com.seer.teach.mall.entity.OrderEntity;
import com.seer.teach.mall.entity.TradeAfterSaleEntity;
import com.seer.teach.mall.order.service.IAdminTradeAfterSaleService;
import com.seer.teach.mall.request.AfterSaleDisagreeReq;
import com.seer.teach.mall.request.AfterSalePageReq;
import com.seer.teach.mall.request.AfterSaleRefuseReq;
import com.seer.teach.mall.response.AfterSaleResp;
import com.seer.teach.mall.service.IAfterSaleService;
import com.seer.teach.mall.service.IOrderService;
import com.seer.teach.pay.api.refund.RefundOrderServiceApi;
import com.seer.teach.pay.api.refund.dto.RefundOrderRequestDTO;
import com.seer.teach.pay.api.refund.dto.RefundResponseDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.validation.Valid;
import java.math.BigDecimal;

/**
 * <p>
 * 售后服务实现类
 * </p>
 *
 * @author Captain
 * @since 2025-06-21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminTradeAfterSaleServiceImpl implements IAdminTradeAfterSaleService {

    private final IAfterSaleService afterSaleService;


    private final RefundOrderServiceApi refundOrderServiceApi;

    private final IOrderService orderService;

    @Override
    public PageListBean<AfterSaleResp> queryPageList(@Valid AfterSalePageReq pageVO) {
        return afterSaleService.queryPageList(pageVO);
    }

    @Override
    public AfterSaleResp getTradeAfterSaleOrderDetail(Integer id, Integer merchantUserId) {
        log.info("查询售后详情，ID: {}, 商户用户ID: {}", id, merchantUserId);
        AfterSaleResp result = afterSaleService.getTradeAfterSaleOrderDetail(id, merchantUserId);
        log.info("查询售后详情完成，售后单号: {}", result != null ? result.getAfterSaleSn() : "未找到");
        return result;
    }

    /**
     * 管理员同意售后申请
     *
     * @param id 售后申请的标识符，用于指定要同意的申请
     * @param userId 售后申请人的标识符
     * @return true表示是否成功同意了售后申请
     */
    @Override
    public boolean agreeAfterSaleApply(Integer id, Integer userId) {
        log.info("管理员同意售后申请，ID: {}, 用户ID: {}", id, userId);

        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(id);

        AssertUtils.isTrue(afterSale.getStatus().intValue() == AfterSaleStatusEnum.APPLY.getStatus().intValue(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);

        boolean update = afterSaleService.handlerAfterSaleApply(afterSale.getId(), userId, AfterSaleStatusEnum.SELLER_AGREE, null);
        log.info("管理员同意售后申请售后单状态结果：{}", update);
        log.info("管理员同意售后申请完成，ID: {}, 用户ID: {}, 结果: {}", id, userId, update);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(id, "管理员同意售后申请", "管理员同意售后申请，结果:" + (update ? "成功" : "失败"));
        return update;
    }

    /**
     * 商家同意售后申请
     *
     * @param id 售后申请的标识符，用于指定要同意的申请
     * @param merchantUserId 售后申请人的标识符
     * @return true表示是否成功同意了售后申请
     */
    @Override
    public boolean agreeAfterSaleApplyMerchant(Integer id, Integer merchantUserId) {
        log.info("商家同意售后申请，ID: {}, 商户用户ID: {}", id, merchantUserId);

        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(id);

        AssertUtils.isTrue(afterSale.getMerchantUserId().intValue() == merchantUserId, ResultCodeEnum.AFTER_SALE_NO_UNAUTHORIZED);
        AssertUtils.isTrue(afterSale.getStatus().intValue() == AfterSaleStatusEnum.APPLY.getStatus().intValue(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);
        boolean update = afterSaleService.handlerAfterSaleApply(afterSale.getId(), merchantUserId, AfterSaleStatusEnum.SELLER_AGREE, null);
        log.info("商家同意售后申请售后单状态结果：{}", update);
        log.info("商家同意售后申请完成，ID: {}, 商户用户ID: {}, 结果: {}", id, merchantUserId, update);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(id, "商家同意售后申请", "商家同意售后申请，结果:" + (update ? "成功" : "失败"));
        return update;
    }

    /**
     * 管理员拒绝售后申请
     *
     * @param disagreeReq 售后申请拒绝参数
     * @param userId 售后申请人的标识符
     * @return true表示是否成功拒绝了售后申请
     */
    @Override
    public boolean disagreeAfterSaleApply(AfterSaleDisagreeReq disagreeReq, Integer userId) {
        log.info("管理员拒绝售后申请，请求参数: {}", disagreeReq);

        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(disagreeReq.getId());
        AssertUtils.isTrue(afterSale.getStatus().intValue() == AfterSaleStatusEnum.APPLY.getStatus().intValue(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);
        boolean update = afterSaleService.handlerAfterSaleApply(afterSale.getId(), userId, AfterSaleStatusEnum.SELLER_AGREE, disagreeReq.getAuditReason());
        log.info("更新售后单状态结果：{}", update);
        log.info("管理员拒绝售后申请完成，ID: {}, 用户ID: {}, 结果: {}", disagreeReq.getId(), userId, update);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(disagreeReq.getId(), "管理员拒绝售后申请", "管理员拒绝售后申请，结果:" + (update ? "成功" : "失败"));
        return update;
    }

    /**
     * 商家拒绝售后申请
     *
     * @param disagreeReq 售后申请拒绝参数
     * @param merchantUserId 售后申请人的标识符
     * @return true表示是否成功拒绝了售后申请
     */
    @Override
    public boolean disagreeAfterSaleApplyMerchant(AfterSaleDisagreeReq disagreeReq, Integer merchantUserId) {
        log.info("商家拒绝售后申请，请求参数: {}", disagreeReq);

        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(disagreeReq.getId());
        AssertUtils.isTrue(afterSale.getMerchantUserId().intValue() == merchantUserId, ResultCodeEnum.AFTER_SALE_NO_UNAUTHORIZED);
        AssertUtils.isTrue(afterSale.getStatus().intValue() == AfterSaleStatusEnum.APPLY.getStatus().intValue(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);
        boolean update = afterSaleService.handlerAfterSaleApply(afterSale.getId(), merchantUserId, AfterSaleStatusEnum.SELLER_REFUSE_APPLY, disagreeReq.getAuditReason());
        log.info("商家更新售后单状态结果：{}", update);
        log.info("商家拒绝售后申请完成，ID: {}, 商户用户ID: {}, 结果: {}", disagreeReq.getId(), merchantUserId, update);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(disagreeReq.getId(), "商家拒绝售后申请", "商家拒绝售后申请，结果:" + (update ? "成功" : "失败"));
        return update;
    }

    /**
     * 管理员确认收货
     *
     * @param id 售后申请标识符
     * @param userId 售后申请人的标识符
     * @return true表示是否成功确认了收货
     */
    @Override
    public boolean confirmReceive(Integer id, Integer userId) {
        log.info("管理员确认收货，ID: {}, 用户ID: {}", id, userId);
        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(id);
        AssertUtils.isTrue(afterSale.getStatus().intValue() == AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);

        boolean result = afterSaleService.confirmReceive(id, userId);
        log.info("管理员确认收货完成，ID: {}, 用户ID: {}, 结果: {}", id, userId, result);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(id, "管理员确认收货", "管理员确认收货，结果:" + (result ? "成功" : "失败"));
        return result;
    }

    /**
     * 商家确认收货
     *
     * @param id 售后申请标识符
     * @param merchantUserId 售后申请人的标识符
     * @return true表示是否成功确认了收货
     */
    @Override
    public boolean confirmReceiveMerchant(Integer id, Integer merchantUserId) {
        log.info("商家确认收货，ID: {}, 商户用户ID: {}", id, merchantUserId);
        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(id);

        AssertUtils.isTrue(afterSale.getStatus().intValue() == AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);
        AssertUtils.isTrue(afterSale.getMerchantUserId().intValue() == merchantUserId, ResultCodeEnum.AFTER_SALE_NO_UNAUTHORIZED);
        boolean result = afterSaleService.confirmReceive(id, merchantUserId);
        log.info("商家确认收货完成，ID: {}, 商户用户ID: {}, 结果: {}", id, merchantUserId, result);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(id, "商家确认收货", "商家确认收货，结果:" + (result ? "成功" : "失败"));
        return result;
    }

    /**
     * 管理员拒绝收货
     *
     * @param refuseReqVO 售后申请拒绝参数
     * @return true表示是否成功拒绝了收货
     */
    @Override
    public boolean confirmRejection(AfterSaleRefuseReq refuseReqVO) {
        log.info("管理员拒绝收货，请求参数: {}", refuseReqVO);
        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(refuseReqVO.getId());

        AssertUtils.isTrue(AfterSaleStatusEnum.WAIT_REFUND.getStatus().intValue() == afterSale.getStatus(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);
        int userId = StpUtil.getLoginIdAsInt();
        boolean result = afterSaleService.confirmRejection(afterSale.getId(), userId, refuseReqVO.getAuditReason());
        log.info("管理员拒绝收货完成，ID: {}, 用户ID: {}, 结果: {}", refuseReqVO.getId(), userId, result);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(refuseReqVO.getId(), "管理员拒绝收货", "管理员拒绝收货，结果:" + (result ? "成功" : "失败"));
        return result;
    }

    /**
     * 商家拒绝收货
     *
     * @param refuseReqVO 售后申请拒绝参数
     * @param merchantUserId 售后申请人的标识符
     * @return true表示是否成功拒绝了收货
     */
    @Override
    public boolean confirmRejectionMerchant(AfterSaleRefuseReq refuseReqVO, Integer merchantUserId) {
        log.info("商家拒绝收货，请求参数: {}", refuseReqVO);
        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(refuseReqVO.getId());
        AssertUtils.isTrue(AfterSaleStatusEnum.WAIT_REFUND.getStatus().intValue() == afterSale.getStatus(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);
        AssertUtils.isTrue(afterSale.getMerchantUserId().intValue() == refuseReqVO.getMerchantUserId(), ResultCodeEnum.AFTER_SALE_NO_UNAUTHORIZED);
        boolean result = afterSaleService.confirmRejection(afterSale.getId(), merchantUserId, refuseReqVO.getAuditReason());
        log.info("商家拒绝收货完成，ID: {}, 商户用户ID: {}, 结果: {}", refuseReqVO.getId(), merchantUserId, result);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(refuseReqVO.getId(), "商家拒绝收货", "商家拒绝收货，结果:" + (result ? "成功" : "失败"));
        return result;
    }

    /**
     * 管理员退款处理（目前仅管理员能处理退款）
     *
     * @param id 售后申请标识符
     * @return true表示是否成功处理了退款
     */
    @Transactional(rollbackFor = Exception.class, timeout = 120)
    @Override
    public boolean refundAfterSale(Integer id) {
        int userId = StpUtil.getLoginIdAsInt();
        log.info("管理员确认退款，ID: {}, 用户ID: {}", id, userId);
        TradeAfterSaleEntity afterSale = afterSaleService.checkAfterSaleOrder(id);
        log.info("管理员[{}]确认退款的售后单[{}]的状态：{}", userId,afterSale.getAfterSaleSn(), afterSale.getStatus());
        AssertUtils.isTrue( AfterSaleStatusEnum.WAIT_REFUND.getStatus() == afterSale.getStatus().intValue()
                || AfterSaleStatusEnum.REFUND_FAILED.getStatus() == afterSale.getStatus().intValue(), ResultCodeEnum.AFTER_SALE_STATUS_ERROR);

        boolean update = afterSaleService.update(new LambdaUpdateWrapper<>(TradeAfterSaleEntity.class)
                .set(TradeAfterSaleEntity::getStatus, AfterSaleStatusEnum.COMPLETE.getStatus())
                .eq(TradeAfterSaleEntity::getId, id));

        log.info("用户[{}]确认退款的更新结果：{}", userId, update);

        if (update) {
            handlerAfterSaleRefund(afterSale);
        }
        log.info("管理员确认退款完成，ID: {}, 用户ID: {}, 结果: {}", id, userId, update);
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(id, "管理员确认退款", "管理员确认退款，结果:" + (update ? "成功" : "失败"));
        return update;
    }

    private void handlerAfterSaleRefund(TradeAfterSaleEntity afterSale) {
        log.info("处理售后退款，售后单号: {}", afterSale.getAfterSaleSn());
        // 获取订单信息
        OrderEntity order = orderService.getById(afterSale.getOrderId());
        AssertUtils.notNull(order, ResultCodeEnum.ORDER_NOT_FOUND);

        String payChannelCode = afterSale.getPayChannelCode();

        Long refundAmount = 0L;
        if (PayChannelEnum.COIN.getCode().equalsIgnoreCase(payChannelCode)) {
            refundAmount = afterSale.getRefundCoin().longValue();
        }else{
            refundAmount = MoneyUtil.yuanToCent(afterSale.getRefundPrice());
        }
        // 调用统一退款接口
        RefundOrderRequestDTO refundRequest = RefundOrderRequestDTO.builder()
                .merchantOrderSn(order.getOrderSn())
                .refundReason(afterSale.getApplyReason())
                .refundAmount(refundAmount)
                .totalAmount(afterSale.getRefundPrice().longValue())
                .userId(afterSale.getUserId())
                .merchantRefundSn(afterSale.getAfterSaleSn())
                .refundType(RefundTypeEnum.AFTER_SALE)
                .channelCode(payChannelCode)
                .build();

        // 调用统一退款接口
        RefundResponseDTO refundResponse = refundOrderServiceApi.submitRefund(refundRequest);
        log.info("调用统一退款接口结果：{}", refundResponse);
        log.info("处理售后退款完成，售后单号: {}", afterSale.getAfterSaleSn());
        // 记录操作日志
        afterSaleService.logAfterSaleOperation(afterSale.getId(), "处理售后退款", "处理售后退款完成，调用统一退款接口结果:" + refundResponse);

    }
}