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.EquipmentBase;
import com.zksy.base.domain.EquipmentStatus;
import com.zksy.base.domain.HazardHiddenAccount;
import com.zksy.base.domain.WorkOrder;
import com.zksy.base.domain.WorkOrderLog;
import com.zksy.base.mapper.EquipmentBaseMapper;
import com.zksy.base.mapper.EquipmentStatusMapper;
import com.zksy.base.mapper.HazardHiddenAccountMapper;
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.time.LocalDateTime;
import java.util.stream.Collectors;

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

    @Autowired
    private WorkOrderLogMapper workOrderLogMapper;

    @Autowired
    private EquipmentBaseMapper equipmentBaseMapper;

    @Autowired
    private HazardHiddenAccountMapper hazardHiddenAccountMapper;

    @Autowired
    private EquipmentStatusMapper equipmentStatusMapper;

    @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 if ("water".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.id IN (SELECT id FROM app_user.equipment_type WHERE type_name = '供水' 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_name = '供水' 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);
        logEntry.setOperTime(new Date());
        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);
            logEntry.setOperTime(new Date());
            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);
        logEntry.setOperTime(new Date());
        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);

        // 工单处理中 → 同步隐患状态为"整改中"
        syncHazardStatus(order, "整改中", solution);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(4);
        logEntry.setOperDesc("处理结果:" + handleResult + "，说明:" + solution);
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        logEntry.setOperTime(new Date());
        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);
        logEntry.setOperTime(new Date());
        workOrderLogMapper.insert(logEntry);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createWorkOrderFromHazard(String hazardId, String hazardNo, String hazardDesc, String equipmentId, String hazardLevel, String hazardImages, Date planFinishTime) {
        // 隐患等级映射到工单优先级：0-重大→紧急(1) 1-较大→一般(2) 2-一般→一般(2) 3-轻微→低(3)
        Integer orderLevel;
        if ("0".equals(hazardLevel)) {
            orderLevel = 1;
        } else if ("3".equals(hazardLevel)) {
            orderLevel = 3;
        } else {
            orderLevel = 2;
        }

        WorkOrder workOrder = new WorkOrder();
        workOrder.setOrderNo(generateOrderNo());
        workOrder.setHazardId(hazardId);
        workOrder.setHazardNo(hazardNo);
        workOrder.setDeviceId(equipmentId);
        // 查询设备信息，填充设备编码
        if (StringUtils.isNotEmpty(equipmentId)) {
            EquipmentBase equipment = equipmentBaseMapper.selectById(equipmentId);
            if (equipment != null) {
                workOrder.setDeviceCode(equipment.getEquipmentCode());
            }
        }
        workOrder.setOrderType(1); // 默认故障维修
        workOrder.setOrderLevel(orderLevel);
        workOrder.setOrderDesc(hazardDesc);
        workOrder.setOrderStatus(1); // 待派单
        workOrder.setWorkImage(hazardImages);
        workOrder.setPlanFinishTime(planFinishTime);
        workOrder.setCreateTime(new Date());
        this.save(workOrder);

        // 写入操作日志
        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(workOrder.getOrderId());
        logEntry.setOperType(1);
        logEntry.setOperDesc("由隐患[" + hazardId + "]自动创建工单");
        logEntry.setOperTime(new Date());
        workOrderLogMapper.insert(logEntry);

        log.info("从隐患[{}]创建工单成功，工单ID={}", hazardId, workOrder.getOrderId());
        return workOrder.getOrderId();
    }

    /**
     * 生成工单编号：WO-yyyyMMddHHmmssSSS
     */
    private String generateOrderNo() {
        return "WO-" + new java.text.SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
    }

    @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);
        logEntry.setOperTime(new Date());
        workOrderLogMapper.insert(logEntry);
        return true;
    }

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

        WorkOrder entity = new WorkOrder();
        entity.setOrderId(orderId);
        entity.setOrderStatus(6);
        entity.setRealFinishTime(new Date());
        this.updateById(entity);

        // 工单已结案 → 同步隐患状态为"已整改"
        syncHazardStatus(order, "已整改", result);

        // 工单验收通过 → 重置关联设备报警状态为正常
        resetEquipmentAlarmStatus(order);

        WorkOrderLog logEntry = new WorkOrderLog();
        logEntry.setOrderId(orderId);
        logEntry.setOperType(6);
        logEntry.setOperDesc("验收通过，结果:" + result);
        logEntry.setOperUserId(operUserId);
        logEntry.setOperUserName(operUserName);
        logEntry.setOperTime(new Date());
        workOrderLogMapper.insert(logEntry);
        return true;
    }

    /**
     * 同步隐患状态：根据工单处理结果更新关联隐患记录的状态和整改反馈
     * @param order 工单对象
     * @param hazardStatus 隐患状态：整改中/已整改
     * @param rectifyFeedback 整改反馈（说明/方案）
     */
    private void syncHazardStatus(WorkOrder order, String hazardStatus, String rectifyFeedback) {
        if (StringUtils.isEmpty(order.getHazardNo())) {
            return;
        }
        try {
            LambdaQueryWrapper<HazardHiddenAccount> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(HazardHiddenAccount::getHazardNo, order.getHazardNo());
            HazardHiddenAccount hazard = hazardHiddenAccountMapper.selectOne(wrapper);
            if (hazard != null) {
                HazardHiddenAccount update = new HazardHiddenAccount();
                update.setHazardId(hazard.getHazardId());
                update.setHazardStatus(hazardStatus);
                if (StringUtils.isNotEmpty(rectifyFeedback)) {
                    update.setRectifyFeedback(rectifyFeedback);
                }
                hazardHiddenAccountMapper.updateById(update);
                log.info("工单[{}]关联隐患[{}]状态同步为:{}, 整改反馈:{}",
                        order.getOrderNo(), order.getHazardNo(), hazardStatus, rectifyFeedback);
            }
        } catch (Exception e) {
            log.error("工单[{}]同步隐患状态失败", order.getOrderNo(), e);
        }
    }

    /**
     * 工单验收通过后，重置关联设备的报警状态为正常（0）
     * 参考 EquipmentStatusApiServiceImpl.updateAlarmStatus 逻辑
     */
    private void resetEquipmentAlarmStatus(WorkOrder order) {
        if (StringUtils.isEmpty(order.getDeviceId())) {
            return;
        }
        try {
            LambdaQueryWrapper<EquipmentStatus> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EquipmentStatus::getEquipmentId, order.getDeviceId()).last("LIMIT 1");
            EquipmentStatus existingStatus = equipmentStatusMapper.selectOne(wrapper);
            if (existingStatus != null) {
                // 更新已有记录
                existingStatus.setAlarmStatus(0);
                existingStatus.setStatusUpdateTime(LocalDateTime.now());
                equipmentStatusMapper.updateById(existingStatus);
                log.info("工单[{}]验收通过，设备[{}]报警状态已重置为正常",
                        order.getOrderNo(), order.getDeviceCode());
            } else {
                // 不存在则创建新记录
                EquipmentStatus newStatus = new EquipmentStatus();
                newStatus.setEquipmentId(order.getDeviceId());
                newStatus.setAlarmStatus(0);
                newStatus.setCurrentStatus(1); // 默认在用
                newStatus.setOnlineStatus(1);  // 默认在线
                newStatus.setStatusUpdateTime(LocalDateTime.now());
                newStatus.setCreateTime(LocalDateTime.now());
                equipmentStatusMapper.insert(newStatus);
                log.info("工单[{}]验收通过，创建设备状态记录，设备[{}]报警状态为正常",
                        order.getOrderNo(), order.getDeviceCode());
            }
        } catch (Exception e) {
            log.error("工单[{}]重置设备报警状态失败", order.getOrderNo(), e);
        }
    }
}
