/**
 * 后端管理系统 路由
 */

import asyncHandler from "express-async-handler";
import * as reportBiz from "../biz/report";
import * as regionBiz from "../biz/region";
import * as scheduleBiz from "../biz/schedule";
import * as deviceBiz from "../biz/device";
import * as alertWorkOrderBiz from "../biz/deviceFault";
import { reloadScheduleTasks } from "../biz/scheduleExecutor";
import { eccReqParamater } from "../util/verificationParam";

export function setRouter(httpServer) {
    /** 获取周报告JSON数据 */
    httpServer.get("/api/qdm/report/weekly/data", asyncHandler(getReportData));
    /** 获取九合一环境监测指标 7 天均值（A/B/C馆） */
    httpServer.get("/api/qdm/report/env/weekly/avg", asyncHandler(getEnvWeeklyAvg));
    /** 获取近 7 天故障信息（按 fault_code 分组） */
    httpServer.get("/api/qdm/report/fault/weekly", asyncHandler(getFaultInfo));

    /** 区域设备树 */
    httpServer.get("/api/qdm/admin/region/device", asyncHandler(getRegionDevices));
    /** 日程管理列表 */
    httpServer.get("/api/qdm/admin/schedule/list", asyncHandler(getScheduleList));
    /** 日程管理详情 */
    httpServer.get("/api/qdm/admin/schedule/detail", asyncHandler(getScheduleDetail));
    /** 日程管理新增 */
    httpServer.post("/api/qdm/admin/schedule/add", asyncHandler(addSchedule));
    /** 日程管理编辑 */
    httpServer.post("/api/qdm/admin/schedule/edit", asyncHandler(editSchedule));
    /** 日程管理删除 */
    httpServer.post("/api/qdm/admin/schedule/delete", asyncHandler(deleteSchedule));

    /** 设备管理列表 */
    httpServer.get("/api/qdm/admin/device/list", asyncHandler(getDeviceList));
    /** 设备管理 - 编辑空调控制参数 */
    httpServer.post("/api/qdm/admin/device/edit", asyncHandler(editDevice));
    /** 设备管理 - 批量编辑设备 */
    httpServer.post("/api/qdm/admin/device/edit_batch", asyncHandler(batchEditDevices));
    /** 设备管理 - 编辑设备信息 */
    httpServer.post("/api/qdm/admin/device/editDevice", asyncHandler(editLocalDevice));
    /** 设备管理 - 批量编辑设备信息 */
    httpServer.post("/api/qdm/admin/device/editDevice_batch", asyncHandler(batchEditLocalDevices));

    /** 预警工单列表 */
    httpServer.get("/api/qdm/admin/fault/list", asyncHandler(getDeviceFaultList));
}

/**
 * GET /api/qdm/report/weekly/data?weekOffset=0
 * 返回周报告 JSON 数据供前端页面渲染
 */
async function getReportData(req, res) {
    const weekOffset = Number(req.query?.weekOffset) || 0;
    const data = await reportBiz.getWeeklyReportData(weekOffset);
    res.success(data);
}

/**
 * GET /api/qdm/report/env/weekly/avg
 * 返回九合一环境监测指标 7 天均值（A馆 / B馆 / C馆）
 */
async function getEnvWeeklyAvg(req, res) {
    const data = await reportBiz.getEnvIndicatorsWeeklyAvg();
    res.success(data);
}

/**
 * GET /api/qdm/report/fault/weekly
 * 返回近 7 天故障信息，按 fault_code 分组
 */
async function getFaultInfo(req, res) {
    const data = await reportBiz.getFaultInfoLast7Days();
    res.success(data);
}

// ======================= 区域设备 =======================

/**
 * GET /api/qdm/admin/region/device
 * 获取区域设备树（馆 → 层 → 区域 → 设备）
 */
async function getRegionDevices(req, res) {
    const data = await regionBiz.getRegionDevices();
    res.success(data);
}

// ======================= 日程管理 =======================

/**
 * GET /api/qdm/admin/schedule/list
 * 日程列表（分页 + 有效期 + 区域过滤）
 * query: pageNumber, pageSize, startDate, endDate, regionKey
 */
async function getScheduleList(req, res) {
    const data = await scheduleBiz.getScheduleList({
        pageNumber: Number(req.query?.pageNumber) || 1,
        pageSize: Number(req.query?.pageSize) || 10,
        startDate: req.query && req.query.startDate?req.query.startDate:'',
        endDate: req.query && req.query.endDate?req.query.endDate:'',
        deviceIds: req.query?.deviceIds ? req.query.deviceIds : undefined,
        regionKeys: req.query?.regionKeys ? req.query.regionKeys : undefined,
    });
    res.success(data);
}

/**
 * GET /api/qdm/admin/schedule/detail
 * 日程详情（含关联区域/设备）
 * query: scheduleId
 */
async function getScheduleDetail(req, res) {
    const scheduleId = Number(req.query?.scheduleId);
    if (!scheduleId) {
        res.error("缺少参数 scheduleId");
        return;
    }
    const data = await scheduleBiz.getScheduleDetail(scheduleId);
    if (!data) {
        res.error("日程不存在");
        return;
    }
    res.success(data);
}

/**
 * POST /api/qdm/admin/schedule/add
 * 新增日程
 * body: title, scheduleTime, acControl, beginValidity, endValidity, regionKeys
 */
async function addSchedule(req, res) {
    let reqConf = { title: 'String', scheduleTime: 'String', acControl: 'String', beginValidity: 'Date', endValidity: 'Date', deviceIds: 'Array', regionKeys: 'Array' };
    const NotMustHaveKeys = ["deviceIds", "regionKeys"];
    let { title, scheduleTime, acControl, beginValidity, endValidity, deviceIds, regionKeys } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
    if (!title || !scheduleTime || !acControl) {
        res.error("缺少必填参数：title, scheduleTime, acControl");
        return;
    }
    if ((!deviceIds && !regionKeys) || (!deviceIds.length && !regionKeys.length)) {
        res.error("至少选择一个区域");
        return;
    }
    const data = await scheduleBiz.addSchedule({
        title,
        schedule_time: scheduleTime,
        ac_control: acControl,
        begin_validity: beginValidity || undefined,
        end_validity: endValidity || undefined,
        deviceIds: deviceIds ?? [],
        regionKeys: regionKeys ?? []
    });
    res.success(data);
    // 新增日程后重载执行器
    reloadScheduleTasks().catch((err) => console.error("[日程重载] 新增后重载失败:", err));
}

/**
 * POST /api/qdm/admin/schedule/edit
 * 编辑日程
 * body: scheduleId, title, scheduleTime, acControl, beginValidity, endValidity, regionKeys
 */
async function editSchedule(req, res) {
    let reqConf = { scheduleId: 'Number', title: 'String', scheduleTime: 'String', acControl: 'String', beginValidity: 'Date', endValidity: 'Date', deviceIds: 'Array', regionKeys: 'Array' };
    const NotMustHaveKeys = ["deviceIds", "regionKeys"];
    let { scheduleId, title, scheduleTime, acControl, beginValidity, endValidity, deviceIds, regionKeys } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
    if (!scheduleId || !title || !scheduleTime || !acControl) {
        res.error("缺少必填参数：title, scheduleTime, acControl");
        return;
    }
    if ((!deviceIds && !regionKeys) || (!deviceIds.length && !regionKeys.length)) {
        res.error("至少选择一个区域");
        return;
    }
    const data = await scheduleBiz.editSchedule({
        scheduleId,
        title,
        schedule_time: scheduleTime,
        ac_control: acControl,
        begin_validity: beginValidity || undefined,
        end_validity: endValidity || undefined,
        deviceIds: deviceIds ?? [],
        regionKeys: regionKeys ?? []
    });
    res.success(data);
    // 编辑日程后重载执行器
    reloadScheduleTasks().catch((err) => console.error("[日程重载] 编辑后重载失败:", err));
}

/**
 * POST /api/qdm/admin/schedule/delete
 * 删除日程
 * body: scheduleId
 */
async function deleteSchedule(req, res) {
    const { scheduleId } = req.body || {};
    if (!scheduleId) {
        res.error("缺少参数 scheduleId");
        return;
    }
    const data = await scheduleBiz.deleteSchedule(Number(scheduleId));
    res.success(data);
    // 删除日程后重载执行器
    reloadScheduleTasks().catch((err) => console.error("[日程重载] 删除后重载失败:", err));
}

// ======================= 设备管理 =======================

/**
 * GET /api/qdm/admin/device/list
 * 设备列表
 * query: pageNumber, pageSize, regionKeys, deviceName, power, state, deviceMode
 */
async function getDeviceList(req, res) {
    const data = await deviceBiz.getDeviceList({
        pageNumber: Number(req.query?.pageNumber) || 1,
        pageSize: Number(req.query?.pageSize) || 10,
        regionKeys: req.query?.regionKeys || undefined,
        deviceName: req.query?.deviceName || undefined,
        power: req.query?.power || undefined,
        state: req.query?.state || undefined,
        deviceMode: req.query?.deviceMode || undefined,
    });
    res.success(data);
}

/**
 * POST /api/qdm/admin/device/edit
 * 设备管理 - 编辑空调控制参数
 * body: { deviceId, power, setTemp, fanSpeed, deviceMode }
 */
async function editDevice(req, res) {
    let reqConf = { deviceId: 'String', power: 'String', setTemp: 'Number', fanSpeed: 'String', deviceMode: 'String', lock: 'String' };
    const NotMustHaveKeys = ["fanSpeed", "deviceMode", "lock"];
    let { deviceId, power, setTemp, fanSpeed, deviceMode, lock } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
    if (!deviceId || !power) {
        res.error("缺少必填参数：deviceId, power");
        return;
    }
    const data = await deviceBiz.editAcDeviceControl({ deviceId, power, setTemp, fanSpeed, deviceMode, lock });
    res.success(data);
}

/**
 * POST /api/qdm/admin/device/batch_edit
 * 设备管理 - 批量编辑设备
 * body: { regionKeys, deviceName?, power?, state?, deviceMode?, startDate?, endDate?, edits }
 * edits: { power?, setTemp?, linkageStart? }
 */
async function batchEditDevices(req, res) {
    let reqConf = {
        regionKeys: 'Array',
        deviceName: 'String',
        power: 'String',
        state: 'String',
        deviceMode: 'String',
        startDate: 'String',
        endDate: 'String',
        edits: 'Object',
    };
    const NotMustHaveKeys = ["deviceName", "power", "state", "deviceMode", "startDate", "endDate"];
    let { regionKeys, deviceName, power, state, deviceMode, startDate, endDate, edits } =
        eccReqParamater(reqConf, req.body, NotMustHaveKeys);

    if (!regionKeys || !regionKeys.length) {
        res.error("缺少必填参数：regionKeys");
        return;
    }
    if (!edits || typeof edits !== 'object') {
        res.error("缺少必填参数：edits");
        return;
    }
    if (edits.power === undefined && edits.setTemp === undefined && edits.linkageStart === undefined) {
        res.error("edits 中至少需要 power / setTemp / linkageStart 其中之一");
        return;
    }
    // 校验 edits.power 值合法性
    if (edits.power !== undefined && !['开', '关'].includes(edits.power)) {
        res.error("edits.power 只能为 开 或 关");
        return;
    }
    // 校验 edits.setTemp 值合法性
    if (edits.setTemp !== undefined && (typeof edits.setTemp !== 'number' || edits.setTemp < 16 || edits.setTemp > 30)) {
        res.error("edits.setTemp 必须为 16~30 之间的数值");
        return;
    }
    // 校验 edits.linkageStart 值合法性
    if (edits.linkageStart !== undefined && !['on', 'off'].includes(edits.linkageStart)) {
        res.error("edits.linkageStart 只能为 on 或 off");
        return;
    }

    const data = await deviceBiz.batchEditDevices({
        regionKeys,
        deviceName: deviceName || undefined,
        power: power || undefined,
        state: state || undefined,
        deviceMode: deviceMode || undefined,
        startDate: startDate || undefined,
        endDate: endDate || undefined,
        edits,
    });
    res.success(data);
}

/**
 * POST /api/qdm/admin/device/editDevice
 * 设备管理 - 编辑单台设备表信息
 * body: { deviceId, deviceName?, regionKey?, deviceType?, linkageStart?, deviceState? }
 */
async function editLocalDevice(req, res) {
    let reqConf = {
        deviceId: 'String',
        deviceName: 'String',
        regionKey: 'Number',
        deviceType: 'String',
        deviceState: 'String',
        linkageStart: 'String',
    };
    const NotMustHaveKeys = ["deviceName", "regionKey", "deviceType", "deviceState", "linkageStart"];
    let { deviceId, deviceName, regionKey, deviceType, deviceState, linkageStart } =
        eccReqParamater(reqConf, req.body, NotMustHaveKeys);
    if (!deviceId) {
        res.error("缺少必填参数：deviceId");
        return;
    }
    const hasEdit = deviceName !== undefined || regionKey !== undefined
        || deviceType !== undefined || deviceState !== undefined || linkageStart !== undefined;
    if (!hasEdit) {
        res.error("至少需要提供一个编辑字段（deviceName/regionKey/deviceType/linkageStart/deviceState）");
        return;
    }
    const data = await deviceBiz.editLocalDevice({ deviceId, deviceName, regionKey, deviceType, deviceState, linkageStart });
    res.success(data);
}

/**
 * POST /api/qdm/admin/device/editDevice_batch
 * 设备管理 - 批量编辑设备表信息
 * body: { regionKeys?, deviceName?, edits: { deviceName?, regionKey?, deviceType?, linkageStart?, deviceState? } }
 */
async function batchEditLocalDevices(req, res) {
    let reqConf = {
        regionKeys: 'Array',
        deviceName: 'String',
        edits: 'Object',
    };
    const NotMustHaveKeys = ["regionKeys", "deviceName"];
    let { regionKeys, deviceName, edits } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
    if (!edits || typeof edits !== 'object') {
        res.error("缺少必填参数：edits");
        return;
    }
    if ((!regionKeys || regionKeys.length === 0) && !deviceName) {
        res.error("至少需要提供 regionKeys 或 deviceName 筛选条件");
        return;
    }
    const validEditKeys = ["deviceName", "regionKey", "deviceType", "deviceState", "linkageStart"];
    const hasEdit = validEditKeys.some(k => edits[k] !== undefined);
    if (!hasEdit) {
        res.error("edits 中至少需要一个编辑字段（deviceName/regionKey/deviceType/linkageStart/deviceState）");
        return;
    }
    const data = await deviceBiz.batchEditLocalDevices({ regionKeys, deviceName, edits });
    res.success(data);
}

// ======================= 预警工单 =======================

/**
 * GET /api/qdm/admin/alertWorkOrder/list
 * 预警工单列表（分页）
 * query: pageNumber, pageSize, level, fault_code, device_id, startTime, endTime
 */
async function getDeviceFaultList(req, res) {
    const data = await alertWorkOrderBiz.getDeviceFaultList({
        pageNumber: Number(req.query?.pageNumber) || 1,
        pageSize: Number(req.query?.pageSize) || 10,
        level: req.query?.level ? Number(req.query.level) : undefined,
        fault_code: req.query?.fault_code || undefined,
        device_id: req.query?.device_id || undefined,
        startTime: req.query?.startTime || undefined,
        endTime: req.query?.endTime || undefined,
    });
    res.success(data);
}
