package com.aucma.production.service.impl;

import com.aucma.common.utils.DateUtils;
import com.aucma.production.domain.AndonEvent;
import com.aucma.production.domain.AndonEventAssignment;
import com.aucma.production.domain.AndonEventLog;
import com.aucma.production.domain.AndonRule;
import com.aucma.production.mapper.AndonEventAssignmentMapper;
import com.aucma.production.mapper.AndonEventLogMapper;
import com.aucma.production.mapper.AndonEventMapper;
import com.aucma.production.mapper.AndonRuleMapper;
import com.aucma.production.service.IAndonEventAssignmentService;
import com.aucma.common.constant.AnDonConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 安灯派工记录（派工即通知/待办）Service业务层处理
 * 
 * @author Yinq
 * @date 2025-10-28
 */
@Service
public class AndonEventAssignmentServiceImpl implements IAndonEventAssignmentService 
{
    @Autowired
    private AndonEventAssignmentMapper andonEventAssignmentMapper;

    @Autowired
    private AndonEventMapper andonEventMapper;

    @Autowired
    private AndonEventLogMapper andonEventLogMapper;

    @Autowired
    private AndonRuleMapper andonRuleMapper;

    /**
     * 查询安灯派工记录（派工即通知/待办）
     * 
     * @param assignmentId 安灯派工记录（派工即通知/待办）主键
     * @return 安灯派工记录（派工即通知/待办）
     */
    @Override
    public AndonEventAssignment selectAndonEventAssignmentByAssignmentId(Long assignmentId)
    {
        return andonEventAssignmentMapper.selectAndonEventAssignmentByAssignmentId(assignmentId);
    }

    /**
     * 查询安灯派工记录（派工即通知/待办）列表
     * 
     * @param andonEventAssignment 安灯派工记录（派工即通知/待办）
     * @return 安灯派工记录（派工即通知/待办）
     */
    @Override
    public List<AndonEventAssignment> selectAndonEventAssignmentList(AndonEventAssignment andonEventAssignment)
    {
        return andonEventAssignmentMapper.selectAndonEventAssignmentList(andonEventAssignment);
    }

    /**
     * 新增安灯派工记录（派工即通知/待办）
     * 
     * @param andonEventAssignment 安灯派工记录（派工即通知/待办）
     * @return 结果
     */
    @Override
    public int insertAndonEventAssignment(AndonEventAssignment andonEventAssignment)
    {
        andonEventAssignment.setCreateTime(DateUtils.getNowDate());
        return andonEventAssignmentMapper.insertAndonEventAssignment(andonEventAssignment);
    }

    /**
     * 修改安灯派工记录（派工即通知/待办）
     * 
     * @param andonEventAssignment 安灯派工记录（派工即通知/待办）
     * @return 结果
     */
    @Override
    public int updateAndonEventAssignment(AndonEventAssignment andonEventAssignment)
    {
        andonEventAssignment.setUpdateTime(DateUtils.getNowDate());
        // 根据状态补充派工自身的里程碑时间
        if (andonEventAssignment.getStatus() != null) {
            String status = andonEventAssignment.getStatus();
            // 当状态变为已接单时，自动设置接单时间
            if (AnDonConstants.AssignmentStatus.ACCEPTED.equals(status) && andonEventAssignment.getAcceptTime() == null) {
                andonEventAssignment.setAcceptTime(DateUtils.getNowDate());
            }
            // 当状态变为已完成时，自动设置完成时间
            if (AnDonConstants.AssignmentStatus.DONE.equals(status) && andonEventAssignment.getFinishTime() == null) {
                andonEventAssignment.setFinishTime(DateUtils.getNowDate());
            }
        }
        int ret = andonEventAssignmentMapper.updateAndonEventAssignment(andonEventAssignment);
        // 派工状态联动事件状态与里程碑，并记录日志
        try {
            if (andonEventAssignment.getEventId() != null && andonEventAssignment.getStatus() != null) {
                String status = andonEventAssignment.getStatus();
                AndonEvent e = andonEventMapper.selectAndonEventByEventId(andonEventAssignment.getEventId());
                if (e != null) {
                    if (AnDonConstants.AssignmentStatus.ACCEPTED.equals(status)) {
                        if (e.getResponseStartTime() == null) {
                            e.setResponseStartTime(DateUtils.getNowDate());
                        }
                        e.setEventStatus(AnDonConstants.EventStatus.PROCESSING);
                        andonEventMapper.updateAndonEvent(e);
                        logEvent(e.getEventId(), AnDonConstants.Operation.ACCEPT, "派工已接受，事件进入处理中");
                    } else if (AnDonConstants.AssignmentStatus.DONE.equals(status)) {
                        if (e.getResponseEndTime() == null) {
                            e.setResponseEndTime(DateUtils.getNowDate());
                        }
                        e.setEventStatus(AnDonConstants.EventStatus.RESOLVED);
                        andonEventMapper.updateAndonEvent(e);
                        logEvent(e.getEventId(), AnDonConstants.Operation.RESOLVE, "派工已完成，事件标记已解决");
                        // 完成时根据策略可取消其他派工
                        if (shouldCancelOthers(e)) {
                            cancelOtherAssignments(e.getEventId(), andonEventAssignment.getAssignmentId());
                        }
                    } else if (AnDonConstants.AssignmentStatus.CANCELLED.equals(status)) {
                        logEvent(e.getEventId(), AnDonConstants.Operation.CANCEL_ASSIGNMENT, "派工已取消");
                    } else if (AnDonConstants.AssignmentStatus.REJECTED.equals(status)) {
                        logEvent(e.getEventId(), AnDonConstants.Operation.REJECT, "派工被拒绝");
                    }
                }
            }
        } catch (Exception ignore) { }
        return ret;
    }

    /**
     * 批量删除安灯派工记录（派工即通知/待办）
     * 
     * @param assignmentIds 需要删除的安灯派工记录（派工即通知/待办）主键
     * @return 结果
     */
    @Override
    public int deleteAndonEventAssignmentByAssignmentIds(Long[] assignmentIds)
    {
        return andonEventAssignmentMapper.deleteAndonEventAssignmentByAssignmentIds(assignmentIds);
    }

    /**
     * 删除安灯派工记录（派工即通知/待办）信息
     * 
     * @param assignmentId 安灯派工记录（派工即通知/待办）主键
     * @return 结果
     */
    @Override
    public int deleteAndonEventAssignmentByAssignmentId(Long assignmentId)
    {
        return andonEventAssignmentMapper.deleteAndonEventAssignmentByAssignmentId(assignmentId);
    }

    private void logEvent(Long eventId, String operation, String content) {
        if (eventId == null || operation == null || operation.trim().isEmpty()) return;
        AndonEventLog log = new AndonEventLog();
        log.setEventId(eventId);
        log.setOperation(operation);
        log.setContent(content);
        log.setOperationTime(DateUtils.getNowDate());
        andonEventLogMapper.insertAndonEventLog(log);
    }

    /** 是否应取消其他派工：从规则 remark 读取 cancelOthers（默认 true）。 */
    private boolean shouldCancelOthers(AndonEvent e) {
        if (e == null) return false;
        AndonRule q = new AndonRule();
        q.setCallTypeCode(e.getCallTypeCode());
        q.setIsFlag(AnDonConstants.FLAG_VALID);
        AndonRule bestRule = pickBestRule(andonRuleMapper.selectAndonRuleList(q), e);
        if (bestRule == null) return false;
        String remark = bestRule.getRemark();
        if (remark == null || remark.trim().isEmpty()) return true;
        try {
            com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
            com.fasterxml.jackson.databind.JsonNode node = mapper.readTree(remark);
            com.fasterxml.jackson.databind.JsonNode co = node.get("cancelOthers");
            if (co == null) return true;
            return co.asBoolean(true);
        } catch (Exception ex) {
            return true;
        }
    }

    /**
     * 选择匹配度最高的规则：与 AndonEventServiceImpl 保持同一算法，避免派工侧逻辑偏差。
     * 计算方式：对产线/工位/班组/触发源类型进行精确匹配，每命中一项得 1 分，得分最高的规则被选中（先到先得处理并列）。
     */
    private AndonRule pickBestRule(List<AndonRule> rules, AndonEvent e) {
        if (rules == null || rules.isEmpty() || e == null) return null;
        AndonRule best = null;
        int bestScore = -1;
        for (AndonRule r : rules) {
            int score = 0;
            if (r.getProductLineCode() != null && r.getProductLineCode().equals(e.getProductLineCode())) score++;
            if (r.getStationCode() != null && r.getStationCode().equals(e.getStationCode())) score++;
            if (r.getTeamCode() != null && r.getTeamCode().equals(e.getTeamCode())) score++;
            if (r.getSourceType() != null && r.getSourceType().equals(e.getSourceType())) score++;
            if (score > bestScore) {
                bestScore = score;
                best = r;
            }
        }
        return best;
    }

    /** 取消同一事件下除当前派工外的其他派工。 */
    private void cancelOtherAssignments(Long eventId, Long currentAssignmentId) {
        if (eventId == null) return;
        AndonEventAssignment filter = new AndonEventAssignment();
        filter.setEventId(eventId);
        List<AndonEventAssignment> list = andonEventAssignmentMapper.selectAndonEventAssignmentList(filter);
        if (list == null) return;
        Date now = DateUtils.getNowDate();
        for (AndonEventAssignment a : list) {
            if (a == null) continue;
            if (currentAssignmentId != null && currentAssignmentId.equals(a.getAssignmentId())) continue;
            // 仅取消未完成/未取消的派工
            String st = a.getStatus();
            if (st == null || AnDonConstants.AssignmentStatus.ASSIGNED.equals(st) || AnDonConstants.AssignmentStatus.ACCEPTED.equals(st)) {
                a.setStatus(AnDonConstants.AssignmentStatus.CANCELLED);
                a.setUpdateTime(now);
                andonEventAssignmentMapper.updateAndonEventAssignment(a);
            }
        }
        logEvent(eventId, AnDonConstants.Operation.CANCEL_OTHERS, "策略要求取消该事件的其他并行派工");
    }
}
