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

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seer.teach.common.enums.OperateTypeEnum;
import com.seer.teach.common.enums.OrderStatusEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.enums.ShippingStatusEnum;
import com.seer.teach.common.enums.pay.PayStatusEnum;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.mall.annotation.OrderLog;
import com.seer.teach.mall.api.req.OrderPayNotifyReq;
import com.seer.teach.mall.entity.OrderChildEntity;
import com.seer.teach.mall.entity.OrderEntity;
import com.seer.teach.mall.entity.OrderGoodsEntity;
import com.seer.teach.mall.mapper.OrderMapper;
import com.seer.teach.mall.request.OrderConsigneeUpdateReq;
import com.seer.teach.mall.service.IGoodsService;
import com.seer.teach.mall.service.IOrderChildService;
import com.seer.teach.mall.service.IOrderGoodsService;
import com.seer.teach.mall.service.IOrderService;
import com.seer.teach.mall.util.OrderLogUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements IOrderService {

    private final IGoodsService goodsService;

    private final IOrderGoodsService orderGoodsService;

    private final IOrderChildService orderChildService;

    @Override
    public OrderEntity checkOrderBySn(String orderSn) {
        OrderEntity order = super.getOne(new LambdaQueryWrapper<>(OrderEntity.class).eq(OrderEntity::getOrderSn, orderSn));
        AssertUtils.notNull(order, ResultCodeEnum.ORDER_NOT_FOUND);
        return order;
    }

    @Override
    public OrderEntity checkOrderByOrderId(Integer orderId) {
        OrderEntity order = super.getById(orderId);
        AssertUtils.notNull(order, ResultCodeEnum.ORDER_NOT_FOUND);
        return order;
    }

    @Override
    public boolean updatePayOrderIdById(Integer id, Integer payOrderId) {
        return super.update(new LambdaUpdateWrapper<>(OrderEntity.class).eq(OrderEntity::getId, id).set(OrderEntity::getPayOrderId, payOrderId));
    }

    @Override
    public OrderEntity getOneByOrderSn(String orderSn) {
        return super.getOne(new LambdaQueryWrapper<>(OrderEntity.class).eq(OrderEntity::getOrderSn, orderSn));
    }

    @Override
    public boolean deliveryOrder(Integer orderId, String logisticsCode, String shippingNo, Integer userId) {
        boolean updateOrderStatusResult = super.update(new LambdaUpdateWrapper<OrderEntity>()
                .eq(OrderEntity::getId, orderId)
                .set(OrderEntity::getOrderStatus, OrderStatusEnum.SHIPPED.getCode())
                .set(OrderEntity::getShippingStatus, ShippingStatusEnum.SHIPPED.getCode())
                .set(OrderEntity::getDeliveryTime, LocalDateTime.now())
                .set(OrderEntity::getDeliveryUserId, userId)
                .set(OrderEntity::getLogisticsCode, logisticsCode)
                .set(OrderEntity::getShippingNo, shippingNo));
        log.info("更新订单状态结果: {}", updateOrderStatusResult);
        return updateOrderStatusResult;
    }

    @Override
    public boolean deliveryPartOrder(Integer orderId) {
        return super.update(new LambdaUpdateWrapper<OrderEntity>()
                .eq(OrderEntity::getId, orderId)
                .set(OrderEntity::getOrderStatus, OrderStatusEnum.PART_ORDER_SHIPPED.getCode()));
    }

    @Override
    public List<OrderEntity> getListByOrderIds(Collection<Integer> orderIds) {
        return super.list(new LambdaQueryWrapper<OrderEntity>()
                .in(OrderEntity::getId, orderIds));
    }

    @Override
    public boolean cancelOrder(Integer orderId, OrderStatusEnum orderStatusEnum, int userId) {
        return super.update(new LambdaUpdateWrapper<>(OrderEntity.class).set(OrderEntity::getOrderStatus, orderStatusEnum.getCode()).eq(OrderEntity::getId, orderId).eq(OrderEntity::getUserId, userId));
    }

    @Override
    public boolean receiveOrder(Integer orderId, String childOrderSn, int userId) {
        List<OrderChildEntity> parentIdOrderList = orderChildService.getListByParentId(orderId);
        OrderStatusEnum orderStatusEnum = null;
        ShippingStatusEnum shippingStatusEnum = null;
        Set<OrderChildEntity> orderChildEntities = parentIdOrderList.stream().filter(childOrder ->
                ShippingStatusEnum.SIGNED.getCode() != childOrder.getShippingStatus() && !childOrder.getChildOrderSn().equals(childOrderSn)
        ).collect(Collectors.toSet());
        if (orderChildEntities.isEmpty()) {
            orderStatusEnum = OrderStatusEnum.COMPLETED;
            shippingStatusEnum = ShippingStatusEnum.SIGNED;
        } else {
            orderStatusEnum = OrderStatusEnum.PART_COMPLETED;
            shippingStatusEnum = ShippingStatusEnum.PART_SIGNED;
        }
        boolean confirmResult = super.update(new LambdaUpdateWrapper<>(OrderEntity.class).
                set(OrderEntity::getOrderStatus, orderStatusEnum.getCode())
                .set(OrderEntity::getConfirmTime, LocalDateTime.now())
                .set(OrderEntity::getShippingStatus, shippingStatusEnum.getCode())
                .eq(OrderEntity::getId, orderId).eq(OrderEntity::getUserId, userId));
        log.info("用户[{}]订单确认收货结果：{}", userId, confirmResult ? "成功" : "失败");
        boolean childOrderUpdated = orderChildService.update(new LambdaUpdateWrapper<>(OrderChildEntity.class).
                set(OrderChildEntity::getOrderStatus, OrderStatusEnum.COMPLETED.getCode())
                .set(OrderChildEntity::getShippingStatus, ShippingStatusEnum.SIGNED.getCode())
                .eq(OrderChildEntity::getChildOrderSn, childOrderSn));
        log.info("用户[{}]子订单确认收货结果：{}", userId, childOrderUpdated ? "成功" : "失败");
        return confirmResult;
    }

    @Override
    public boolean deleteOrder(Integer orderId, Integer userId) {
        boolean removeOrderGoodResult = super.update(new LambdaUpdateWrapper<>(OrderEntity.class).eq(OrderEntity::getId, orderId)
                .set(OrderEntity::getOrderStatus, OrderStatusEnum.DELETED.getCode())
                .set(OrderEntity::getUserId, userId));
        log.info("订单商品删除结果：{}", removeOrderGoodResult ? "成功" : "失败");
        return removeOrderGoodResult;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW, timeout = 120)
    @OrderLog(operateType = OperateTypeEnum.UPDATE, content = "用户支付订单")
    @Override
    public boolean orderPayAfterSuccessNotify(OrderPayNotifyReq orderPayNotifyReq) {
        OrderEntity order = this.checkOrderBySn(orderPayNotifyReq.getOrderSn());

        // 更新订单主表状态
        LambdaUpdateWrapper<OrderEntity> updateWrapper = new LambdaUpdateWrapper<>(OrderEntity.class);
        if (orderPayNotifyReq.getPayStatus() != null) {
            updateWrapper.set(OrderEntity::getPayStatus, orderPayNotifyReq.getPayStatus());
            if (orderPayNotifyReq.getPayStatus() == PayStatusEnum.SUCCESS.getCode()) {
                updateWrapper.set(OrderEntity::getPayTime, orderPayNotifyReq.getPayTime());
                updateWrapper.set(OrderEntity::getPayChannelCode, orderPayNotifyReq.getPayChannelCode());
                updateWrapper.set(OrderEntity::getOrderStatus, OrderStatusEnum.PAID.getCode());
            }
        }
        if (orderPayNotifyReq.getPayChannelCode() != null) {
            updateWrapper.set(OrderEntity::getPayChannelCode, orderPayNotifyReq.getPayChannelCode());
        }
        if (orderPayNotifyReq.getPayTime() != null) {
            updateWrapper.set(OrderEntity::getPayTime, orderPayNotifyReq.getPayTime());
        }
        boolean mainOrderUpdated = super.update(updateWrapper.eq(OrderEntity::getOrderSn, orderPayNotifyReq.getOrderSn()));
        log.info("订单主表状态更新结果: {}", mainOrderUpdated);

        // 更新子订单状态
        List<OrderChildEntity> childOrders = orderChildService.getListByParentId(order.getId());
        if (CollectionUtil.isNotEmpty(childOrders)) {
            orderChildService.update(new LambdaUpdateWrapper<OrderChildEntity>()
                    .in(OrderChildEntity::getId, childOrders.stream().map(OrderChildEntity::getId).collect(Collectors.toList()))
                    .set(OrderChildEntity::getPayStatus, orderPayNotifyReq.getPayStatus())
                    .set(OrderChildEntity::getPayTime, orderPayNotifyReq.getPayTime())
                    .set(OrderChildEntity::getOrderStatus, orderPayNotifyReq.getPayStatus() == PayStatusEnum.SUCCESS.getCode() ? OrderStatusEnum.PAID.getCode() : OrderStatusEnum.PENDING_PAYMENT.getCode())
                    .set(OrderChildEntity::getPayChannelCode, orderPayNotifyReq.getPayChannelCode()));
        }
        handlePaymentSuccess(order);
        //添加订单日志
        OrderLogUtils.setPayOrderInfo(order.getId(), null, order.getUserId());
        log.info("订单支付完成，订单ID: {}", order.getId());
        return mainOrderUpdated;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW, timeout = 120)
    @OrderLog(operateType = OperateTypeEnum.UPDATE, content = "用户支付订单失败")
    @Override
    public boolean orderPayAfterFailNotify(OrderPayNotifyReq orderPayNotifyReq) {
        OrderEntity order = this.checkOrderBySn(orderPayNotifyReq.getOrderSn());

        // 更新订单主表状态
        LambdaUpdateWrapper<OrderEntity> updateWrapper = new LambdaUpdateWrapper<>(OrderEntity.class);
        if (orderPayNotifyReq.getPayStatus() != null) {
            updateWrapper.set(OrderEntity::getPayStatus, orderPayNotifyReq.getPayStatus());
        }

        if (orderPayNotifyReq.getPayChannelCode() != null) {
            updateWrapper.set(OrderEntity::getPayChannelCode, orderPayNotifyReq.getPayChannelCode());
        }
        if (orderPayNotifyReq.getPayTime() != null) {
            updateWrapper.set(OrderEntity::getPayTime, orderPayNotifyReq.getPayTime());
        }

        boolean mainOrderUpdated = super.update(updateWrapper.eq(OrderEntity::getOrderSn, orderPayNotifyReq.getOrderSn()));
        log.info("订单主表支付失败状态更新结果: {}", mainOrderUpdated);

        // 更新子订单状态
        List<OrderChildEntity> childOrders = orderChildService.getListByParentId(order.getId());
        if (CollectionUtil.isNotEmpty(childOrders)) {
            orderChildService.update(new LambdaUpdateWrapper<OrderChildEntity>()
                    .in(OrderChildEntity::getId, childOrders.stream().map(OrderChildEntity::getId).collect(Collectors.toList()))
                    .set(OrderChildEntity::getPayStatus, orderPayNotifyReq.getPayStatus())
                    .set(OrderChildEntity::getPayTime, orderPayNotifyReq.getPayTime())
                    .set(OrderChildEntity::getPayChannelCode, orderPayNotifyReq.getPayChannelCode()));
        }

        //添加订单日志
        OrderLogUtils.setPayOrderInfo(order.getId(), null, order.getUserId());
        log.info("订单支付失败处理完成，订单ID: {}", order.getId());
        return mainOrderUpdated;
    }

    @Override
    public boolean updateOrderConsigneeInfo(OrderConsigneeUpdateReq orderReq) {
        // 更新子订单信息
        boolean result = super.update(new LambdaUpdateWrapper<OrderEntity>()
                .set(StringUtils.isNotBlank(orderReq.getConsignee()), OrderEntity::getConsignee, orderReq.getConsignee())
                .set(StringUtils.isNotBlank(orderReq.getMobile()), OrderEntity::getMobile, orderReq.getMobile())
                .set(StringUtils.isNotBlank(orderReq.getAddress()), OrderEntity::getAddress, orderReq.getAddress())
                .set(StringUtils.isNotBlank(orderReq.getCity()), OrderEntity::getCity, orderReq.getCity())
                .set(StringUtils.isNotBlank(orderReq.getProvince()), OrderEntity::getProvince, orderReq.getProvince())
                .set(StringUtils.isNotBlank(orderReq.getDistrict()), OrderEntity::getDistrict, orderReq.getDistrict())
                .set(Objects.nonNull(orderReq.getAddressId()), OrderEntity::getAddressId, orderReq.getAddressId())
                .set(StringUtils.isNotBlank(orderReq.getRemark()), OrderEntity::getRemark, orderReq.getRemark())
                .eq(OrderEntity::getId, orderReq.getOrderId()));
        log.info("子订单更新结果：{}", result ? "成功" : "失败");

        AssertUtils.isTrue(result, ResultCodeEnum.ORDER_UPDATE_ERROR);
        return true;
    }

    /**
     * 处理支付成功的后续逻辑
     *
     * @param order 订单信息
     */
    private void handlePaymentSuccess(OrderEntity order) {
        log.info("开始处理订单[{}]支付成功后的逻辑", order.getOrderSn());
        // 1. 更新商品库存和销量
        List<OrderGoodsEntity> list = orderGoodsService.list(new LambdaQueryWrapper<OrderGoodsEntity>().eq(OrderGoodsEntity::getOrderId, order.getId()));
        Set<Integer> goodsIdList = list.stream().map(OrderGoodsEntity::getGoodsId).collect(Collectors.toSet());
        log.debug("开始更新商品销售数量和库存，商品ID列表: {}", goodsIdList);
        goodsService.updateSellVolumeAndStock(goodsIdList, 1);
        // 2. 发送支付成功通知
        log.info("发送支付成功通知，订单号：{}，支付金额：{}，支付时间：{}", order.getOrderSn(), order.getActualPrice(), order.getPayTime());

        OrderLogUtils.setPayOrderInfo(order.getId(), null, order.getUserId());
        log.info("订单[{}]支付成功，订单金额：{}，支付时间：{}",
                order.getOrderSn(), order.getActualPrice(), order.getPayTime());
    }

}