package com.aucma.production.controller;

import com.aucma.common.annotation.Anonymous;
import com.aucma.common.constant.AnDonConstants;
import com.aucma.common.core.domain.AjaxResult;
import com.aucma.common.utils.DateUtils;
import com.aucma.production.domain.AndonBoardConfig;
import com.aucma.production.domain.AndonEvent;
import com.aucma.production.service.IAndonBoardConfigService;
import com.aucma.production.service.IAndonEventService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 安灯看板展示接口（对外展示使用）
 */
@RestController
@RequestMapping("/production/andonBoard")
public class AndonBoardController {

    /** 安灯看板配置服务 */
    @Autowired
    private IAndonBoardConfigService andonBoardConfigService;

    /** 安灯事件服务 */
    @Autowired
    private IAndonEventService andonEventService;

    /**
     * 根据看板编码获取看板配置与事件数据。
     *
     * 说明：
     * - boardCode 作为对外展示的“唯一入口参数”；
     * - 事件范围由看板配置的 productLineCode / stationCode 决定；
     * - 返回 activeEvents（待处理/处理中）与 closedEvents（已解决/已取消）两组数据，便于大屏展示。
     * - 接口使用 @Anonymous 标记，可免登录访问（大屏/外部展示使用）。
     */
    @Anonymous
    @GetMapping("/view")
    public AjaxResult view(@RequestParam String boardCode) {
        // 1) 参数校验：boardCode 必填
        if (boardCode == null || boardCode.trim().isEmpty()) {
            return AjaxResult.error("boardCode不能为空");
        }

        // 2) 查询启用的看板配置（同一编码可能存在多条记录，取最新一条）
        AndonBoardConfig config = selectActiveBoardConfig(boardCode.trim());
        if (config == null) {
            return AjaxResult.error("看板配置不存在或未启用：" + boardCode);
        }

        // 3) 根据看板配置的范围（产线/工位）查询事件
        List<AndonEvent> allEvents = selectEventsByConfig(config);

        // 4) 统计数量 + 拆分进行中/已关闭事件
        Map<String, Long> stats = buildStats(allEvents);
        List<AndonEvent> activeEvents = filterByStatus(allEvents, true);
        List<AndonEvent> closedEvents = filterByStatus(allEvents, false);

        // 5) 排序：进行中按状态/优先级/创建时间；已关闭按结束时间/更新时间
        sortActiveEvents(activeEvents);
        sortClosedEvents(closedEvents);

        // 为大屏限制历史记录数量（避免数据过多影响渲染）
        if (closedEvents.size() > 20) {
            closedEvents = new ArrayList<>(closedEvents.subList(0, 20));
        }

        // 6) 组装返回数据（大屏依赖 config / stats / activeEvents / closedEvents / serverTime）
        Map<String, Object> data = new HashMap<>();
        data.put("config", config);
        data.put("stats", stats);
        data.put("activeEvents", activeEvents);
        data.put("closedEvents", closedEvents);
        data.put("serverTime", DateUtils.getNowDate());
        return AjaxResult.success(data);
    }

    /**
     * 查询指定看板编码下启用的配置记录。
     * 若存在多条启用记录，则按更新时间（优先）/创建时间倒序取最新一条。
     */
    private AndonBoardConfig selectActiveBoardConfig(String boardCode) {
        AndonBoardConfig q = new AndonBoardConfig();
        q.setBoardCode(boardCode);
        q.setIsFlag(AnDonConstants.FLAG_VALID);
        List<AndonBoardConfig> list = andonBoardConfigService.selectAndonBoardConfigList(q);
        if (list == null || list.isEmpty()) {
            return null;
        }

        // 按更新时间优先、否则按创建时间，倒序排序，取第一条（最新配置）
        list.sort((a, b) -> {
            Date ta = (a.getUpdateTime() != null ? a.getUpdateTime() : a.getCreateTime());
            Date tb = (b.getUpdateTime() != null ? b.getUpdateTime() : b.getCreateTime());
            if (ta == null && tb == null) return 0;
            if (ta == null) return 1;
            if (tb == null) return -1;
            return tb.compareTo(ta);
        });
        return list.get(0);
    }

    /**
     * 根据看板配置的作用域查询事件列表。
     * 仅当配置字段非空时才作为过滤条件；为空表示不按该维度过滤。
     */
    private List<AndonEvent> selectEventsByConfig(AndonBoardConfig config) {
        AndonEvent q = new AndonEvent();
        q.setIsFlag(AnDonConstants.FLAG_VALID);
        // 产线范围过滤
        if (config.getProductLineCode() != null && !config.getProductLineCode().trim().isEmpty()) {
            q.setProductLineCode(config.getProductLineCode());
        }
        // 工位/工序范围过滤
        if (config.getStationCode() != null && !config.getStationCode().trim().isEmpty()) {
            q.setStationCode(config.getStationCode());
        }
        return andonEventService.selectAndonEventList(q);
    }

    /**
     * 构建看板统计数据。
     * 返回字段：pending / processing / resolved / cancelled / active / total。
     */
    private Map<String, Long> buildStats(List<AndonEvent> events) {
        long pending = 0;
        long processing = 0;
        long resolved = 0;
        long cancelled = 0;
        if (events != null) {
            for (AndonEvent e : events) {
                if (e == null) continue;
                String s = e.getEventStatus();
                if (AnDonConstants.EventStatus.PENDING.equals(s)) pending++;
                else if (AnDonConstants.EventStatus.PROCESSING.equals(s)) processing++;
                else if (AnDonConstants.EventStatus.RESOLVED.equals(s)) resolved++;
                else if (AnDonConstants.EventStatus.CANCELLED.equals(s)) cancelled++;
            }
        }
        Map<String, Long> m = new HashMap<>();
        m.put("pending", pending);
        m.put("processing", processing);
        m.put("resolved", resolved);
        m.put("cancelled", cancelled);
        m.put("active", pending + processing);
        m.put("total", events == null ? 0L : (long) events.size());
        return m;
    }

    /**
     * 按状态将事件分为“进行中”和“已关闭”两组。
     * active=true：待处理/处理中；active=false：已解决/已取消（以及其他未知状态）。
     */
    private List<AndonEvent> filterByStatus(List<AndonEvent> events, boolean active) {
        List<AndonEvent> list = new ArrayList<>();
        if (events == null) return list;
        for (AndonEvent e : events) {
            if (e == null) continue;
            String s = e.getEventStatus();
            // 待处理/处理中 视为进行中
            boolean isActive = AnDonConstants.EventStatus.PENDING.equals(s) || AnDonConstants.EventStatus.PROCESSING.equals(s);
            if (active == isActive) {
                list.add(e);
            }
        }
        return list;
    }

    /**
     * 进行中事件排序：
     * 1) 状态（待处理优先于处理中）
     * 2) 优先级（数值越小越紧急；空值排最后）
     * 3) 创建时间（越早越靠前；空值排最后）
     */
    private void sortActiveEvents(List<AndonEvent> events) {
        if (events == null) return;
        events.sort(Comparator
                .comparingInt((AndonEvent e) -> statusOrder(e.getEventStatus()))
                .thenComparing(e -> e.getPriority() == null ? Long.MAX_VALUE : e.getPriority())
                .thenComparing(AndonEvent::getCreateTime, Comparator.nullsLast(Date::compareTo))
        );
    }

    /**
     * 已关闭事件排序：
     * 1) 解决/结束时间 responseEndTime 倒序（最近关闭的在前；空值排最后）
     * 2) 更新时间 updateTime 倒序（空值排最后）
     */
    private void sortClosedEvents(List<AndonEvent> events) {
        if (events == null) return;
        events.sort(Comparator
                .comparing(AndonEvent::getResponseEndTime, Comparator.nullsLast(Comparator.reverseOrder()))
                .thenComparing(AndonEvent::getUpdateTime, Comparator.nullsLast(Comparator.reverseOrder()))
        );
    }

    /**
     * 状态排序权重：待处理(0) < 处理中(1) < 已解决(2) < 已取消(3)。
     */
    private int statusOrder(String status) {
        if (AnDonConstants.EventStatus.PENDING.equals(status)) return 0;
        if (AnDonConstants.EventStatus.PROCESSING.equals(status)) return 1;
        if (AnDonConstants.EventStatus.RESOLVED.equals(status)) return 2;
        if (AnDonConstants.EventStatus.CANCELLED.equals(status)) return 3;
        return 99;
    }
}
