package com.ruoyi.info.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.info.management.domain.vo.ManagementTeacherVo;
import com.ruoyi.info.management.service.IManagementTeacherService;
import com.ruoyi.info.order.domain.Order;
import com.ruoyi.info.order.domain.OrderRefund;
import com.ruoyi.info.order.domain.bo.OrderRefundBo;
import com.ruoyi.info.order.domain.bo.OrderRefundCountBo;
import com.ruoyi.info.order.domain.vo.OrderRefundVo;
import com.ruoyi.info.order.enums.OrderOperatorType;
import com.ruoyi.info.order.enums.OrderStatus;
import com.ruoyi.info.order.enums.RefundStatus;
import com.ruoyi.info.order.exception.OrderRefundExceptionEnum;
import com.ruoyi.info.order.mapper.OrderRefundMapper;
import com.ruoyi.info.order.service.IOrderRefundService;
import com.ruoyi.info.order.service.IOrderService;
import com.ruoyi.system.enums.SequencePrefixEnum;
import com.ruoyi.system.service.ISysSequenceService;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 售后订单Service业务层处理
 *
 * @author ruoyi
 * @date 2025-09-29
 */
@RequiredArgsConstructor
@Service
public class OrderRefundServiceImpl implements IOrderRefundService {

    private final OrderRefundMapper baseMapper;
    private final IOrderService orderService;
    private final ISysSequenceService sysSequenceService;
    private final ISysUserService sysUserService;
    private final IManagementTeacherService managementTeacherService;

    /**
     * 查询售后订单分页
     *
     * @param bo 售后订单
     * @return 售后订单
     */
    @Override
    public TableDataInfo<OrderRefundVo> queryPageList(OrderRefundBo bo, PageQuery pageQuery) {
        Page<OrderRefundVo> result = baseMapper.selectListPage(pageQuery.build(), bo);
        result.setRecords(result.getRecords().stream().map(orv -> {
            if (ObjectUtil.isNotNull(orv.getOrderVo())) {
                orv.setOrderVo(orderService.convertAllVo(orv.getOrderVo(), true, null));
            }
            return orv;
        }).collect(Collectors.toList()));
        return TableDataInfo.build(result);
    }

    /**
     * 查询售后订单列表
     *
     * @param bo 售后订单
     * @return 售后订单
     */
    @Override
    public List<OrderRefundVo> queryList(OrderRefundBo bo) {
        return baseMapper.selectOrderRefundList(bo);
    }

    private LambdaQueryWrapper<OrderRefund> buildQueryWrapper(OrderRefundBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OrderRefund> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getOrderId() != null, OrderRefund::getOrderId, bo.getOrderId());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundReason()), OrderRefund::getRefundReason, bo.getRefundReason());
        lqw.eq(bo.getRefundQuantity() != null, OrderRefund::getRefundQuantity, bo.getRefundQuantity());
        lqw.eq(bo.getRefundAmount() != null, OrderRefund::getRefundAmount, bo.getRefundAmount());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundWay()), OrderRefund::getRefundWay, bo.getRefundWay());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundDesc()), OrderRefund::getRefundDesc, bo.getRefundDesc());
        lqw.eq(bo.getRefundStatus() != null, OrderRefund::getRefundStatus, bo.getRefundStatus());
        lqw.eq(bo.getActualRefundAmount() != null, OrderRefund::getActualRefundAmount, bo.getActualRefundAmount());
        lqw.eq(StringUtils.isNotBlank(bo.getOperationReason()), OrderRefund::getOperationReason, bo.getOperationReason());
        lqw.eq(bo.getOperationTime() != null, OrderRefund::getOperationTime, bo.getOperationTime());
        lqw.eq(bo.getOperatorId() != null, OrderRefund::getOperatorId, bo.getOperatorId());
        return lqw;
    }

    /**
     * 查询售后订单
     *
     * @param id 售后订单主键
     * @return 售后订单
     */
    @Override
    public OrderRefundVo queryById(Long id){
        OrderRefundVo orderRefundVo = baseMapper.selectVoById(id);
        if(ObjectUtil.isEmpty(orderRefundVo)){
            return null;
        }
        orderRefundVo.setOrderVo(orderService.queryById(orderRefundVo.getOrderId()));
        if (OrderOperatorType.platform.getCode().equals(orderRefundVo.getOperatorType())) {
            SysUser sysUser = sysUserService.selectBaseUserById(orderRefundVo.getOperatorId());
            if (ObjectUtil.isNotNull(sysUser)) {
                orderRefundVo.setOperatorName(sysUser.getNickName());
                orderRefundVo.setOperatorMobile(sysUser.getPhonenumber());
            }
        } else if (OrderOperatorType.teacher.getCode().equals(orderRefundVo.getOperatorType())) {
            ManagementTeacherVo managementTeacherVo = managementTeacherService.queryDelById(orderRefundVo.getOperatorId());
            if (ObjectUtil.isNotNull(managementTeacherVo)) {
                orderRefundVo.setOperatorName(managementTeacherVo.getName());
                orderRefundVo.setOperatorMobile(managementTeacherVo.getPhoneNumber());
            }
        }
        return orderRefundVo;
    }

    /**
     * 详情售后订单
     *
     * @param id 售后订单主键
     * @return 售后订单
     */
    @Override
    public OrderRefund loadById(Long id, Boolean tw){
        OrderRefund info = this.baseMapper.selectById(id);
        if(ObjectUtil.isEmpty(info) && tw){
            throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_IS_NOT_EXISTS);
        }
        return info;
    }

    /**
     * 新增售后订单
     *
     * @param bo 售后订单
     * @return 结果
     */
    @Override
    public Boolean insertByBo(OrderRefundBo bo) {
        //判断订单状态
        Order order = orderService.loadById(bo.getOrderId(), true);
        if (!OrderStatus.wait_service.equals(order.getStatus()) && !OrderStatus.in_progress.equals(order.getStatus())) {
            throw new ServiceException(OrderRefundExceptionEnum.Order_STATUS_ERROR);
        }
        if (!order.getUserId().equals(bo.getUserId())) {
            throw new ServiceException(OrderRefundExceptionEnum.Order_USER_ERROR);
        }
        if (bo.getRefundQuantity() > order.getOrderNum()) {
            throw new ServiceException(OrderRefundExceptionEnum.Order_QUANTITY_ERROR);
        }
        OrderRefund add = BeanUtil.toBean(bo, OrderRefund.class);
        validEntityBeforeSave(add);
        add.setRefundStatus(RefundStatus.wait);
        add.setOrderRefundNo(sysSequenceService.generateSequence(SequencePrefixEnum.PRE_ORDER_REFUND, DateUtil.format(new Date(), "yyMMdd"), 6));
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改售后订单
     *
     * @param bo 售后订单
     * @return 结果
     */
    @Override
    public Boolean updateByBo(OrderRefundBo bo) {
        OrderRefund orderRefund = baseMapper.selectById(bo.getId());
        OrderRefund update = BeanCopyUtils.copy(bo, orderRefund);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(OrderRefund entity){
        //TODO 做一些数据校验,如唯一约束
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<OrderRefund>().eq(OrderRefund::getOrderId, entity.getOrderId())
            .in(OrderRefund::getRefundStatus, Arrays.asList(RefundStatus.wait, RefundStatus.complete))
            .ne(ObjectUtil.isNotNull(entity.getId()), OrderRefund::getId, entity.getId())
        );
        if (count > 0) {
            throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_HAS_REFUND);
        }
    }

    /**
     * 批量删除售后订单
     *
     * @param ids 需要删除的售后订单主键
     * @return 结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public boolean cancel(Long id) {
        OrderRefund orderRefund = loadById(id, true);
        if (!orderRefund.getRefundStatus().equals(RefundStatus.wait)) {
            throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_STATUS_ERROR);
        }
        orderRefund.setRefundStatus(RefundStatus.cancel);
        return baseMapper.updateById(orderRefund) > 0;
    }

    @Override
    public Integer queryOrderRefundCount(OrderRefundCountBo bo) {

        return baseMapper.selectOrderRefundCount(bo);
    }

    @Override
    public boolean hasRefund(Long id) {
        return baseMapper.selectCount(new LambdaQueryWrapper<OrderRefund>().eq(OrderRefund::getOrderId, id)) > 0;
    }

    @Override
    public boolean agreeOrRefuse(OrderRefundBo bo) {
        OrderRefund orderRefund = loadById(bo.getId(), true);
        if (!orderRefund.getRefundStatus().equals(RefundStatus.wait)) {
            throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_STATUS_ERROR);
        }
        if (!RefundStatus.complete.equals(bo.getRefundStatus()) && !RefundStatus.fail.equals(bo.getRefundStatus())) {
            throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_OPERATION_STATUS_ERROR);
        }
        // 保存前的数据校验
        validEntityBeforeSave(orderRefund);
        orderRefund.setRefundStatus(bo.getRefundStatus());
        if (RefundStatus.complete.equals(bo.getRefundStatus())) {
            if (bo.getActualRefundAmount() == null) {
                throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_OPERATION_AMOUNT_ERROR);
            }
            orderRefund.setActualRefundAmount(bo.getActualRefundAmount());
        }
        if (StringUtils.isEmpty(bo.getOperationReason())) {
            throw new ServiceException(OrderRefundExceptionEnum.OrderRefund_OPERATION_REASON_ERROR);
        }
        orderRefund.setOperationReason(bo.getOperationReason());
        orderRefund.setOperationTime(new Date());
        orderRefund.setOperatorType(bo.getOperatorType());
        orderRefund.setOperatorId(bo.getOperatorId());
        return baseMapper.updateById(orderRefund) > 0;
    }

    @Override
    public OrderRefundVo querySuccessByOrder(Long orderId) {
        return baseMapper.selectVoOne(new LambdaQueryWrapper<OrderRefund>().eq(OrderRefund::getOrderId, orderId)
            .eq(OrderRefund::getRefundStatus, RefundStatus.complete)
            .last("limit 1")
        );
    }

}
