package com.zksy.base.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.zksy.base.domain.WorkOrder;
import com.zksy.base.domain.WorkOrderLog;
import com.zksy.base.mapper.WorkOrderLogMapper;
import com.zksy.base.mapper.WorkOrderMapper;
import com.zksy.base.service.BusinessWorkOrderService;
import com.zksy.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 业务工单管理 Service 实现
 */
@Slf4j
@Service
public class BusinessWorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements BusinessWorkOrderService {

    @Autowired
    private WorkOrderLogMapper workOrderLogMapper;

    @Override
    public IPage<WorkOrder> selectWorkOrderList(Integer orderType, Integer orderLevel, Integer orderStatus, String deviceCode, String keyword, String equipmentType, Integer pageNum, Integer pageSize) {
        Page<WorkOrder> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<WorkOrder> wrapper = new LambdaQueryWrapper<>();
        // 按设备类型过滤工单：gas-燃气（父类别ID=3），drainage-排水（typeId为drainage的顶级分类）
        if (StringUtils.isNotEmpty(equipmentType)) {
            if ("gas".equals(equipmentType)) {
                wrapper.inSql(WorkOrder::getDeviceId, "SELECT eb.equipment_id FROM app_user.equipment_base eb " + "INNER JOIN app_user.equipment_type et ON eb.equipment_type_id = et.id " + "WHERE et.parent_type_id = '3'");
            } else if ("drainage".equals(equipmentType)) {
                // 排水：typeId为drainage的顶级分类及其全部子类型
                wrapper.inSql(WorkOrder::getDeviceId, "SELECT eb.equipment_id FROM app_user.equipment_base eb " + "INNER JOIN app_user.equipment_type et ON eb.equipment_type_id = et.id " + "WHERE et.id IN (SELECT id FROM app_user.equipment_type WHERE type_id = 'drainage' AND parent_type_id = '0' " + "UNION SELECT id FROM app_user.equipment_type WHERE parent_type_id = (SELECT id FROM app_user.equipment_type WHERE type_id = 'drainage' AND parent_type_id = '0'))");
            }
        } else {
            // 默认只查询燃气设备类工单（兼容旧逻辑）
            wrapper.inSql(WorkOrder::getDeviceId, "SELECT eb.equipment_id FROM app_user.equipment_base eb " + "INNER JOIN app_user.equipment_type et ON eb.equipment_type_id = et.id " + "WHERE et.parent_type_id = '3'");
        }
        if (orderType != null) wrapper.eq(WorkOrder::getOrderType, orderType);
        if (orderLevel != null) wrapper.eq(WorkOrder::getOrderLevel, orderLevel);
        if (orderStatus != null) wrapper.eq(WorkOrder::getOrderStatus, orderStatus);
        if (StringUtils.isNotEmpty(deviceCode)) wrapper.eq(WorkOrder::getDeviceCode, deviceCode);
        if (StringUtils.isNotEmpty(keyword)) {
            wrapper.and(w -> w.like(WorkOrder::getOrderNo, keyword).or().like(WorkOrder::getDeviceCode, keyword).or().like(WorkOrder::getOrderDesc, keyword));
        }
        wrapper.orderByAsc(WorkOrder::getOrderLevel, WorkOrder::getOrderStatus);
        wrapper.orderByDesc(WorkOrder::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    public WorkOrder getWorkOrderDetail(Long orderId) {
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        return order;
    }

    @Override
    public List<WorkOrderLog> getWorkOrderLogs(Long orderId) {
        LambdaQueryWrapper<WorkOrderLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WorkOrderLog::getOrderId, orderId);
        wrapper.orderByDesc(WorkOrderLog::getOperTime);
        return workOrderLogMapper.selectList(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean dispatchOrder(Long orderId, Long handlerId, String remarks, Long operUserId, String operUserName) {
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        if (order.getOrderStatus() != 1) throw new ServiceException("当前工单状态不允许派单");

        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(2);
        entity.setDispatchUser(operUserId);
        entity.setDispatchTime(new Date());
        entity.setReceiveUser(handlerId.toString());
        this.updateById(entity);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(2);
        logEntry.setOperDesc("派单给处理人ID:" + handlerId + "，备注:" + (remarks != null ? remarks : ""));
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        workOrderLogMapper.insert(logEntry);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDispatchOrder(Long orderId, List<Long> handlerIds, String remarks, Long operUserId, String operUserName) {
        if (handlerIds == null || handlerIds.isEmpty()) {
            throw new ServiceException("派单人员不能为空");
        }
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        if (order.getOrderStatus() != 1) throw new ServiceException("当前工单状态不允许派单");

        // 更新工单状态（只更新一次）
        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(2);
        entity.setDispatchUser(operUserId);
        entity.setDispatchTime(new Date());
        // 多个处理人用逗号分隔存储
        String receiveUserStr = handlerIds.stream()
            .map(String::valueOf)
            .collect(Collectors.joining(","));
        entity.setReceiveUser(receiveUserStr);
        this.updateById(entity);

        // 为每个 handler 写入操作日志
        for (Long handlerId : handlerIds) {
            WorkOrderLog logEntry = new WorkOrderLog();
            logEntry.setOrderId(orderId);
            logEntry.setOperType(2);
            logEntry.setOperDesc("派单给处理人ID:" + handlerId + "，备注:" + (remarks != null ? remarks : ""));
            logEntry.setOperUserId(operUserId);
            logEntry.setOperUserName(operUserName);
            workOrderLogMapper.insert(logEntry);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean verifyOrder(Long orderId, String handleResult, String solution, Long operUserId, String operUserName) {
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        if (!Arrays.asList(2, 3).contains(order.getOrderStatus())) throw new ServiceException("当前工单状态不允许核查");

        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(3);
        entity.setRepairResult(solution);
        this.updateById(entity);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(3);
        logEntry.setOperDesc("核查结果:" + handleResult + "，说明:" + solution);
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        workOrderLogMapper.insert(logEntry);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processOrder(Long orderId, String handleResult, String solution, Long operUserId, String operUserName) {
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        if (!Arrays.asList(3, 4).contains(order.getOrderStatus())) throw new ServiceException("当前工单状态不允许处理");

        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(4);
        entity.setRepairResult(solution);
        this.updateById(entity);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(4);
        logEntry.setOperDesc("处理结果:" + handleResult + "，说明:" + solution);
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        workOrderLogMapper.insert(logEntry);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeOrder(Long orderId, String result, Long operUserId, String operUserName) {
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        if (order.getOrderStatus() != 4)
            throw new ServiceException("当前工单状态不允许提交验收");

        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(5);
        entity.setRepairResult(result);
        this.updateById(entity);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(5);
        logEntry.setOperDesc("提交验收，结果:" + result);
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        workOrderLogMapper.insert(logEntry);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(Long orderId, Long operUserId, String operUserName) {
        WorkOrder order = this.getById(orderId);
        if (order == null) throw new ServiceException("工单不存在");
        if (order.getOrderStatus() == 6) throw new ServiceException("已结案工单不可取消");

        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(7);
        this.updateById(entity);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(7);
        logEntry.setOperDesc("取消工单");
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        workOrderLogMapper.insert(logEntry);
        return true;
    }
}
