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.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.info.hospital.domain.vo.HospitalStatisticsVo;
import com.ruoyi.info.hospital.service.IHospitalDepartmentService;
import com.ruoyi.info.hospital.service.IHospitalService;
import com.ruoyi.info.order.domain.Order;
import com.ruoyi.info.order.domain.bo.OrderBo;
import com.ruoyi.info.order.domain.vo.OrderVo;
import com.ruoyi.info.order.enums.CancellationMethod;
import com.ruoyi.info.order.enums.OrderStatus;
import com.ruoyi.info.order.exception.OrderExceptionEnum;
import com.ruoyi.info.order.mapper.OrderMapper;
import com.ruoyi.info.order.service.IOrderService;
import com.ruoyi.info.patient.service.IPatientService;
import com.ruoyi.info.service.domain.ServiceProduct;
import com.ruoyi.info.service.domain.vo.ServiceProductVo;
import com.ruoyi.info.service.service.IServiceProductService;
import com.ruoyi.system.enums.SequencePrefixEnum;
import com.ruoyi.system.service.ISysSequenceService;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author ruoyi
 * @date 2025-09-20
 */
@RequiredArgsConstructor
@Service
public class OrderServiceImpl implements IOrderService {

    private final OrderMapper baseMapper;
    private final ISysSequenceService sysSequenceService;
    private final IServiceProductService serviceProductService;
    private final IHospitalService hospitalService;
    private final IHospitalDepartmentService hospitalDepartmentService;
    private final IPatientService patientService;
    private final IUserService userService;

    /**
     * 查询订单分页
     *
     * @param bo 订单
     * @return 订单
     */
    @Override
    public TableDataInfo<OrderVo> queryPageList(OrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Order> lqw = buildQueryWrapper(bo);
        Page<OrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.setRecords(convertList(result.getRecords()));
        return TableDataInfo.build(result);
    }

    /**
     * 查询订单列表
     *
     * @param bo 订单
     * @return 订单
     */
    @Override
    public List<OrderVo> queryList(OrderBo bo) {
        LambdaQueryWrapper<Order> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Order> buildQueryWrapper(OrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Order> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getOrderNo()), Order::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getUserId() != null, Order::getUserId, bo.getUserId());
        lqw.eq(bo.getStatus() != null, Order::getStatus, bo.getStatus());
        lqw.eq(bo.getHospitalId() != null, Order::getHospitalId, bo.getHospitalId());
        lqw.eq(bo.getHospitalDepartmentId() != null, Order::getHospitalDepartmentId, bo.getHospitalDepartmentId());
        lqw.eq(StringUtils.isNotBlank(bo.getRoomNumber()), Order::getRoomNumber, bo.getRoomNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), Order::getRemarks, bo.getRemarks());
        lqw.eq(bo.getPatientId() != null, Order::getPatientId, bo.getPatientId());
        lqw.eq(bo.getServiceId() != null, Order::getServiceId, bo.getServiceId());
        lqw.eq(bo.getExpectedTime() != null, Order::getExpectedTime, bo.getExpectedTime());
        lqw.eq(bo.getOrderNum() != null, Order::getOrderNum, bo.getOrderNum());
        lqw.eq(bo.getSellingPrice() != null, Order::getSellingPrice, bo.getSellingPrice());
        lqw.eq(bo.getTotalPrice() != null, Order::getTotalPrice, bo.getTotalPrice());
        lqw.orderByDesc(Order::getCreateTime);
        return lqw;
    }

    private List<OrderVo> convertList(List<OrderVo> list) {
        return list.stream().map(this::convert).collect(Collectors.toList());
    }

    private OrderVo convert(OrderVo vo) {
        if (ObjectUtil.isNull(vo)) {
            return vo;
        }
        //医院
        vo.setHospitalVo(hospitalService.queryDelById(vo.getHospitalId()));
        //科室
        vo.setHospitalDepartmentName(hospitalDepartmentService.queryNameById(vo.getHospitalDepartmentId()));
        //就诊人
        vo.setPatientVo(patientService.queryDelById(vo.getPatientId()));
        //服务
        ServiceProductVo serviceProductVo = serviceProductService.queryDelById(vo.getServiceId());
        if (ObjectUtil.isNotNull(serviceProductVo)) {
            vo.setServiceName(serviceProductVo.getName());
        }
        //用户
        User user = userService.getById(vo.getUserId(), false);
        if (ObjectUtil.isNotNull(user)) {
            vo.setUserName(user.getNickname());
            vo.setUserMobile(user.getMobile());
        }
        return vo;
    }

    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public OrderVo queryById(Long id){
        return convert(baseMapper.selectVoById(id));
    }

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

    /**
     * 新增订单
     *
     * @param bo 订单
     * @return 结果
     */
    @Transactional
    @Override
    public Boolean insertByBo(OrderBo bo) {
        Order add = BeanUtil.toBean(bo, Order.class);
        add.setOrderNo(sysSequenceService.generateSequence(SequencePrefixEnum.PRE_ORDER, DateUtil.format(new Date(), "yyMMdd"), 6));
        add.setStatus(OrderStatus.wait_confirmed);
        //服务
        ServiceProduct serviceProduct = serviceProductService.loadById(add.getServiceId(), true);
        add.setSellingPrice(serviceProduct.getSellingPrice());
        add.setTotalPrice(serviceProduct.getSellingPrice().multiply(new BigDecimal(add.getOrderNum())));
        add.setServiceUnit(serviceProduct.getServiceUnit());
        add.setServiceUnitDuration(serviceProduct.getServiceUnitDuration());
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            //更新订单数
            userService.addNum(add.getUserId());
        }
        return flag;
    }

    /**
     * 修改订单
     *
     * @param bo 订单
     * @return 结果
     */
    @Override
    public Boolean updateByBo(OrderBo bo) {
        Order order = baseMapper.selectById(bo.getId());
        Order update = BeanCopyUtils.copy(bo, order);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Order entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除订单
     *
     * @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, Long userId) {
        Order order = loadById(id, true);
        if (!order.getUserId().equals(userId)) {
            throw new ServiceException(OrderExceptionEnum.Order_IS_NOT_YOURS);
        }
        if (!OrderStatus.wait_confirmed.equals(order.getStatus())) {
            throw new ServiceException(OrderExceptionEnum.Order_STATUS_ERROR);
        }
        order.setStatus(OrderStatus.canceled);
        order.setCancellationMethod(CancellationMethod.user_canceled);
        order.setCancellationTime(new Date());
        return baseMapper.updateById(order) > 0;
    }

    @Override
    public TableDataInfo<OrderVo> queryAllPageList(OrderBo bo, PageQuery pageQuery) {
        Page<OrderVo> result = baseMapper.queryAllPageList(bo, pageQuery.build());
        result.setRecords(convertAllList(result.getRecords()));
        return TableDataInfo.build(result);
    }

    @Override
    public List<OrderVo> queryAllList(OrderBo bo) {
        return convertAllList(baseMapper.queryAllList(bo));
    }

    @Override
    public Integer querySumForHome() {
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<Order>());
        return count.intValue();
    }

    @Override
    public List<HospitalStatisticsVo> queryHospitalOrderStatistics() {
        //按医院分组 订单数top10
        List<HospitalStatisticsVo> hospitalStatistics = baseMapper.queryHospitalOrderStatistics();
        return hospitalStatistics.stream().map(h -> {
            h.setName(hospitalService.queryNameById(h.getHospitalId()));
            return h;
        }).collect(Collectors.toList());
    }

    private List<OrderVo> convertAllList(List<OrderVo> list) {
        return list.stream().map(o -> {
            o.setHospitalName(hospitalService.queryNameById(o.getHospitalId()));
            o.setHospitalDepartmentName(hospitalDepartmentService.queryNameById(o.getHospitalDepartmentId()));
            return o;
        }).collect(Collectors.toList());
    }
}
