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

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.utils.AssertUtils;
import com.seer.teach.common.utils.PageConverterUtils;
import com.seer.teach.mall.convert.AfterSaleConvert;
import com.seer.teach.mall.convert.OrderGoodsConverter;
import com.seer.teach.mall.entity.OrderGoodsEntity;
import com.seer.teach.mall.entity.TradeAfterSaleEntity;
import com.seer.teach.mall.entity.TradeAfterSaleLogEntity;
import com.seer.teach.mall.mapper.TradeAfterSaleMapper;
import com.seer.teach.mall.request.AfterSalePageReq;
import com.seer.teach.mall.response.AfterSaleResp;
import com.seer.teach.mall.response.OrderItemResp;
import com.seer.teach.mall.service.IAfterSaleService;
import com.seer.teach.mall.service.IOrderGoodsService;
import com.seer.teach.mall.service.ITradeAfterSaleLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;


@RequiredArgsConstructor
@Slf4j
@Service
public class AfterSaleServiceImpl extends ServiceImpl<TradeAfterSaleMapper, TradeAfterSaleEntity> implements IAfterSaleService {

    private final IOrderGoodsService orderGoodsService;
    private final ITradeAfterSaleLogService tradeAfterSaleLogService;

    @Override
    public TradeAfterSaleEntity checkAfterSaleOrder(Integer id) {
        TradeAfterSaleEntity afterSale = super.getById(id);

        AssertUtils.notNull(afterSale, ResultCodeEnum.AFTER_SALE_NOT_FOUND);

        return afterSale;
    }

    @Override
    public PageListBean<AfterSaleResp> queryPageList(@Valid AfterSalePageReq pageVO) {
        int userId = StpUtil.getLoginIdAsInt();
        IPage<TradeAfterSaleEntity> pageParams = new Page<>(pageVO.getPageNo(), pageVO.getPageSize());
        IPage<TradeAfterSaleEntity> iPage = super.page(pageParams, new LambdaQueryWrapper<TradeAfterSaleEntity>()
                .eq(Objects.nonNull(pageVO.getStatus()), TradeAfterSaleEntity::getStatus, pageVO.getStatus())
                .eq(TradeAfterSaleEntity::getUserId, userId)
                .eq(Objects.nonNull(pageVO.getMerchantUserId()), TradeAfterSaleEntity::getMerchantUserId, pageVO.getMerchantUserId())
                .in(CollectionUtil.isNotEmpty(pageVO.getStatuses()), TradeAfterSaleEntity::getStatus, pageVO.getStatuses())
                .orderByDesc(TradeAfterSaleEntity::getId));
        List<TradeAfterSaleEntity> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageListBean<>();
        }
        List<Integer> orderIds = records.stream().map(TradeAfterSaleEntity::getOrderId).collect(Collectors.toList());
        log.debug("用户[{}]查询到订单ID列表: {}", userId, orderIds);
        Set<Integer> skuIds = records.stream().map(TradeAfterSaleEntity::getSkuId).collect(Collectors.toSet());
        List<OrderGoodsEntity> goodsEntities = orderGoodsService.list(new LambdaQueryWrapper<OrderGoodsEntity>()
                .in(OrderGoodsEntity::getOrderId, orderIds)
                .in(OrderGoodsEntity::getSkuId, skuIds));
        if (CollectionUtils.isEmpty(goodsEntities)) {
            log.warn("用户[{}]订单商品为空", userId);
            return new PageListBean<>();
        }

        Map<Integer, OrderItemResp> goodsMaps = OrderGoodsConverter.INSTANCE.list(goodsEntities).stream().collect(Collectors.toMap(OrderItemResp::getSkuId, Function.identity(), (old, newOne) -> newOne));

        PageListBean<AfterSaleResp> afterSaleRespPageListBean = PageConverterUtils.convertPageListBean(iPage, AfterSaleConvert.INSTANCE::list);
        afterSaleRespPageListBean.getList().forEach(afterSaleResp -> {
            // 使用getOrDefault避免空指针异常
            afterSaleResp.setOrderItem(goodsMaps.getOrDefault(afterSaleResp.getSkuId(), null));
        });
        return afterSaleRespPageListBean;
    }


    @Override
    public AfterSaleResp getTradeAfterSaleOrderDetail(Integer id, Integer merchantUserId) {
        TradeAfterSaleEntity afterSaleEntity = super.getById(id);
        AssertUtils.notNull(afterSaleEntity, ResultCodeEnum.AFTER_SALE_NOT_FOUND);
        if (Objects.nonNull(merchantUserId)) {
            AssertUtils.isTrue(afterSaleEntity.getMerchantUserId().intValue() == merchantUserId, ResultCodeEnum.AFTER_SALE_NO_UNAUTHORIZED);
        }
        OrderGoodsEntity item = orderGoodsService.getOne(new LambdaQueryWrapper<OrderGoodsEntity>()
                .eq(OrderGoodsEntity::getOrderId, afterSaleEntity.getOrderId())
                .eq(OrderGoodsEntity::getChildOrderId, afterSaleEntity.getChildOrderId())
                .eq(Objects.nonNull(afterSaleEntity.getSkuId()), OrderGoodsEntity::getSkuId, afterSaleEntity.getSkuId()));
        if (Objects.isNull(item)) {
            return new AfterSaleResp();
        }
        return OrderGoodsConverter.INSTANCE.one(afterSaleEntity, item);
    }

    @Override
    public TradeAfterSaleEntity getListBySkuIdAndOrderId(Integer skuId, Integer orderId) {
        return super.getOne(new LambdaQueryWrapper<>(TradeAfterSaleEntity.class).eq(TradeAfterSaleEntity::getSkuId, skuId)
                .eq(TradeAfterSaleEntity::getOrderId, orderId));
    }

    @Override
    public boolean handlerAfterSaleApply(Integer id, Integer userId, AfterSaleStatusEnum status, String auditReason) {
        return super.update(new LambdaUpdateWrapper<>(TradeAfterSaleEntity.class)
                .set(TradeAfterSaleEntity::getAuditTime, LocalDateTime.now())
                .set(TradeAfterSaleEntity::getAuditUserId, userId)
                .set(StringUtils.isNotBlank(auditReason), TradeAfterSaleEntity::getAuditReason, auditReason)
                .set(TradeAfterSaleEntity::getStatus, status.getStatus())
                .eq(TradeAfterSaleEntity::getId, id));
    }

    @Override
    public boolean confirmReceive(Integer id, Integer userId) {
        boolean update = super.update(new LambdaUpdateWrapper<>(TradeAfterSaleEntity.class)
                .set(TradeAfterSaleEntity::getStatus, AfterSaleStatusEnum.WAIT_REFUND.getStatus())
                .set(TradeAfterSaleEntity::getAuditTime, LocalDateTime.now())
                .set(TradeAfterSaleEntity::getAuditUserId, userId)
                .eq(TradeAfterSaleEntity::getId, id));
        log.info(" 用户[{}]确认收获 [{}] 更新结果：{}", userId, id, update);
        return update;
    }

    @Override
    public boolean confirmRejection(Integer id, Integer userId, String auditReason) {
        boolean update = super.update(new LambdaUpdateWrapper<>(TradeAfterSaleEntity.class)
                .set(TradeAfterSaleEntity::getStatus, AfterSaleStatusEnum.SELLER_DISAGREE.getStatus())
                .set(TradeAfterSaleEntity::getAuditReason, auditReason)
                .set(TradeAfterSaleEntity::getAuditTime, LocalDateTime.now())
                .eq(TradeAfterSaleEntity::getId, id));
        log.info("用户 {} 拒绝收获更新结果：{}", userId, update);
        return update;
    }

    @Override
    public TradeAfterSaleEntity getOneByAfterSaleSn(String afterSaleSn) {
        return super.getOne(new LambdaQueryWrapper<TradeAfterSaleEntity>()
                .eq(TradeAfterSaleEntity::getAfterSaleSn, afterSaleSn));
    }

    @Override
    public boolean updateAfterSaleStatus(Integer id, Integer status) {
        return super.update(new LambdaUpdateWrapper<TradeAfterSaleEntity>()
                .set(TradeAfterSaleEntity::getStatus, status)
                .eq(TradeAfterSaleEntity::getId, id));
    }

    @Override
    public boolean handleRefundSuccessNotify(String afterSaleSn, Integer afterSaleStatus) {
        log.info("处理售后单退款成功通知，售后单号:{}，目标状态:{}", afterSaleSn, afterSaleStatus);

        // 根据售后单号查询售后单
        TradeAfterSaleEntity afterSale = this.getOneByAfterSaleSn(afterSaleSn);
        if (Objects.isNull(afterSale)) {
            log.warn("处理售后单退款成功通知失败，未找到售后单，售后单号:{}", afterSaleSn);
            return false;
        }

        // 更新售后单状态
        boolean result = this.updateAfterSaleStatus(afterSale.getId(), afterSaleStatus);
        log.info("更新售后单状态结果:{}，售后单号:{}，目标状态:{}", result, afterSaleSn, afterSaleStatus);

        // 记录售后日志
        this.logAfterSaleOperation(afterSale.getId(), "退款成功通知", "收到退款成功通知，更新售后单状态为:" + afterSaleStatus);

        return result;
    }

    @Override
    public boolean handleRefundFailNotify(String afterSaleSn, Integer afterSaleStatus) {
        log.info("处理售后单退款失败通知，售后单号:{}，目标状态:{}", afterSaleSn, afterSaleStatus);

        // 根据售后单号查询售后单
        TradeAfterSaleEntity afterSale = this.getOneByAfterSaleSn(afterSaleSn);
        if (Objects.isNull(afterSale)) {
            log.warn("处理售后单退款失败通知失败，未找到售后单，售后单号:{}", afterSaleSn);
            return false;
        }

        // 更新售后单状态
        boolean result = this.updateAfterSaleStatus(afterSale.getId(), afterSaleStatus);
        log.info("更新售后单状态结果:{}，售后单号:{}，目标状态:{}", result, afterSaleSn, afterSaleStatus);

        // 记录售后日志
        this.logAfterSaleOperation(afterSale.getId(), "退款失败通知", "收到退款失败通知，更新售后单状态为:" + afterSaleStatus);

        return result;
    }

    /**
     * 记录售后操作日志
     *
     * @param afterSaleId   售后单ID
     * @param operationType 操作类型
     * @param description   操作描述
     */
    @Override
    public void logAfterSaleOperation(Integer afterSaleId, String operationType, String description) {
        log.info("售后单操作日志，售后单ID:{}，操作类型:{}，描述:{}", afterSaleId, operationType, description);

        try {
            TradeAfterSaleLogEntity logEntity = new TradeAfterSaleLogEntity();
            logEntity.setAfterSaleId(afterSaleId);
            logEntity.setOperationType(operationType);
            logEntity.setDescription(description);
            // 尝试获取当前操作人ID，如果获取不到则设置为-1
            try {
                logEntity.setOperatorId(StpUtil.getLoginIdAsInt());
            } catch (Exception e) {
                logEntity.setOperatorId(-1);
            }

            boolean saved = tradeAfterSaleLogService.save(logEntity);
            if (saved) {
                log.info("售后操作日志保存成功，日志ID:{}", logEntity.getId());
            } else {
                log.warn("售后操作日志保存失败，售后单ID:{}", afterSaleId);
            }
        } catch (Exception e) {
            log.error("保存售后操作日志时发生异常，售后单ID:{}", afterSaleId, e);
        }
    }
}