/**
 * 日程管理 业务逻辑
 */

import { selectDataListByParam, selectDataListToPageByParam, selectDataCountByParam } from "../data/findData";
import { addData } from "../data/addData";
import { delData } from "../data/delData";
import { updateManyData } from "../data/updateData";
import { TABLENAME } from "../config/dbEnum";
import { clearOffPeriodCache } from "./scheduleStatus";

// ======================= 公共工具 =======================

/** 格式化为本地时间字符串 YYYY-MM-DD HH:mm:ss */
function formatLocalTime(d: Date): string {
    const pad = (n: number) => String(n).padStart(2, "0");
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
}

// ======================= 日程列表 =======================

/**
 * 查询日程列表（分页 + 按有效期/区域过滤）
 */
export async function getScheduleList(params: {
    pageNumber?: number;
    pageSize?: number;
    startDate?: string;
    endDate?: string;
    deviceIds?: any;
    regionKeys?: any;
}): Promise<any> {
    const pageNumber = params.pageNumber || 1;
    const pageSize = params.pageSize || 10;
    const { startDate, endDate, deviceIds, regionKeys } = params;

    console.log(`[日程列表] page=${pageNumber}, size=${pageSize}, startDate=${startDate}, endDate=${endDate}, deviceIds=${deviceIds}, regionKeys=${regionKeys}`);

    // 构建日程表查询条件
    const scheduleWhere: any = { "%orderDesc%": "id" };

    // 有效期过滤：日程有效时间与查询区间有交集
    if (startDate) {
        scheduleWhere.begin_validity = { "%lte%": startDate };
    }
    if (endDate) {
        scheduleWhere.end_validity = { "%gte%": endDate };
    }

    // 如果按区域过滤，先查出该区域下的 schedule_id 集合
    let filteredScheduleIds: number[] | null = null;
    let paramAnys: any = {};
    if (deviceIds && deviceIds.length) {
        paramAnys.device_id = { "%in%": deviceIds };
    }
    // if (regionKeys && regionKeys.length) {
    //     paramAnys.region_key = { "%in%": regionKeys };
    // }
    if ((deviceIds && deviceIds.length) || (regionKeys && regionKeys.length)) {
        const sdRes = await selectDataListByParam(TABLENAME.日程设备关联表, paramAnys, ["schedule_id"]);
        filteredScheduleIds = (sdRes.data || []).map((r: any) => r.schedule_id);
        if (filteredScheduleIds.length === 0) {
            return { total: 0, list: [] };
        }
        scheduleWhere.id = { "%in%": filteredScheduleIds };
    }

    // 分页查询
    const columns = ["id", "title", "ac_control", "schedule_time", "begin_validity", "end_validity", "created_at"];
    const listRes = await selectDataListByParam(
        TABLENAME.日程表, scheduleWhere, columns
    );
    const rows: any[] = listRes.data || [];

    // 总数
    const countRes = await selectDataCountByParam(TABLENAME.日程表, scheduleWhere);
    const total = countRes.data || 0;

    // 收集所有日程 id
    const scheduleIds = rows.map(r => r.id);

    // 批量查关联的设备关联记录
    let deviceMap: { [sid: number]: any[] } = {};
    if (scheduleIds.length > 0) {
        const sdRes = await selectDataListByParam(TABLENAME.日程设备关联表, {
            schedule_id: { "%in%": scheduleIds },
        }, ["schedule_id", "device_id", "region_key"]);
        const sdRows = sdRes.data || [];
        for (const sd of sdRows) {
            if (!deviceMap[sd.schedule_id]) deviceMap[sd.schedule_id] = [];
            deviceMap[sd.schedule_id].push(sd);
        }
    }

    // 批量查区域名称（需要去重 region_key）
    const regionKeySet = new Set<number>();
    for (const sid of scheduleIds) {
        for (const sd of (deviceMap[sid] || [])) {
            regionKeySet.add(sd.region_key);
        }
    }
    let regionNameMap: { [rk: number]: string } = {};
    if (regionKeySet.size > 0) {
        const regionRes = await selectDataListByParam(TABLENAME.区域表, {
            id: { "%in%": [...regionKeySet] },
            "%orderAsc%": "sort_order",
        }, ["id", "name"]);
        for (const r of (regionRes.data || [])) {
            regionNameMap[r.id] = r.name;
        }
    }

    // 组装返回列表
    const list = rows.map(row => {
        const devices = deviceMap[row.id] || [];
        const regionNames = [...new Set(devices.map((d: any) => regionNameMap[d.region_key] || ""))].filter(Boolean);

        let validity = "";
        if (row.begin_validity || row.end_validity) {
            const from = row.begin_validity
                ? (typeof row.begin_validity === "string" ? row.begin_validity.split(" ")[0] : formatLocalTime(new Date(row.begin_validity)).split(" ")[0])
                : "";
            const to = row.end_validity
                ? (typeof row.end_validity === "string" ? row.end_validity.split(" ")[0] : formatLocalTime(new Date(row.end_validity)).split(" ")[0])
                : "";
            validity = `${from} 至 ${to}`;
        }

        return {
            id: row.id,
            title: row.title,
            acControl: row.ac_control,
            scheduleTime: row.schedule_time || "",
            validity,
            deviceCount: devices.length,
            regionNames,
            createdAt: row.created_at
                ? (typeof row.created_at === "string" ? row.created_at : formatLocalTime(new Date(row.created_at)))
                : "",
        };
    });

    console.log(`[日程列表] total=${total}, rows=${list.length}`);
    return { total, list };
}

// ======================= 新增日程 =======================

/**
 * 新增日程（含区域设备关联）
 */
export async function addSchedule(params: {
    title: string;
    schedule_time: string;
    ac_control: string;
    begin_validity?: string;
    end_validity?: string;
    deviceIds: string[];
    regionKeys: number[];
}): Promise<any> {
    const { title, schedule_time, ac_control, begin_validity, end_validity, deviceIds, regionKeys } = params;

    console.log(`[新增日程] title=${title}, time=${schedule_time}, action=${ac_control}, devices=${deviceIds}`);

    // 1. 插入 schedule 主表
    await addData(TABLENAME.日程表, {
        title,
        schedule_time,
        ac_control,
        begin_validity: begin_validity || null,
        end_validity: end_validity || null,
    });

    // 2. 通过 addData 无法直接获取自增 id，需要反向查询
    const inserted = await selectDataListByParam(TABLENAME.日程表, {
        title,
        schedule_time,
        ac_control,
        "%orderDesc%": "id",
        "%limit%": 1,
    }, ["id"]);
    const scheduleId = (inserted.data && inserted.data[0]) ? inserted.data[0].id : null;

    if (!scheduleId) {
        console.warn("[新增日程] 无法获取插入的 schedule id");
        return { isSuccess: false, msg: "日程创建失败" };
    }

    // 3. 查空调设备（优先 deviceIds，补充 regionKeys 维度）
    let devices: any[] = [];
    if (deviceIds && deviceIds.length) {
        // 有具体设备时，按 deviceIds 查，取出它们的 device_id + region_key
        const deviceRes = await selectDataListByParam(TABLENAME.设备表, {
            device_type: "空调",
            device_id: { "%in%": deviceIds },
        }, ["device_id", "region_key"]);
        devices = deviceRes.data || [];
    } else if (regionKeys && regionKeys.length) {
        // 仅传区域时，查该区域下所有空调
        const deviceRes = await selectDataListByParam(TABLENAME.设备表, {
            device_type: "空调",
            region_key: { "%in%": regionKeys },
        }, ["device_id", "region_key"]);
        devices = deviceRes.data || [];
    }

    // 4. 批量插入 schedule_device 关联记录
    if (devices.length > 0) {
        const sdRecords = devices.map((d: any) => ({
            schedule_id: scheduleId,
            device_id: d.device_id,
            region_key: d.region_key,
        }));
        await addData(TABLENAME.日程设备关联表, sdRecords);
        console.log(`[新增日程] 关联设备 ${sdRecords.length} 条`);
    } else if (regionKeys && regionKeys.length) {
        // 无设备但传了区域时，插入区域占位记录
        for (const rk of regionKeys) {
            await addData(TABLENAME.日程设备关联表, {
                schedule_id: scheduleId,
                device_id: "",
                region_key: rk,
            });
        }
        console.log(`[新增日程] 区域 ${regionKeys.length} 个，暂无设备`);
    }

    clearOffPeriodCache(); // 新增日程后清空开关机时段缓存
    return { isSuccess: true, scheduleId };
}

// ======================= 日程详情 =======================

/**
 * 获取日程详情（含关联区域/设备）
 */
export async function getScheduleDetail(scheduleId: number): Promise<any> {
    console.log(`[日程详情] scheduleId=${scheduleId}`);

    // 1. 查日程主表
    const scheduleRes = await selectDataListByParam(TABLENAME.日程表, {
        id: scheduleId,
    });

    const rows = scheduleRes.data || [];
    if (rows.length === 0) {
        return null;
    }
    const row = rows[0];

    // 2. 查关联设备
    const sdRes = await selectDataListByParam(TABLENAME.日程设备关联表, {
        schedule_id: scheduleId,
    }, ["device_id", "region_key"]);
    const sdRows = sdRes.data || [];

    const selectedRegions = [...new Set(sdRows.map((r: any) => r.region_key))];
    const selectedDevices = sdRows.filter((r: any) => r.device_id).map((r: any) => r.device_id);

    return {
        id: row.id,
        title: row.title,
        scheduleTime: row.schedule_time || "",
        acControl: row.ac_control,
        beginValidity: row.begin_validity
            ? (typeof row.begin_validity === "string" ? row.begin_validity.split(" ")[0] : formatLocalTime(new Date(row.begin_validity)).split(" ")[0])
            : "",
        endValidity: row.end_validity
            ? (typeof row.end_validity === "string" ? row.end_validity.split(" ")[0] : formatLocalTime(new Date(row.end_validity)).split(" ")[0])
            : "",
        selectedRegions,
        selectedDevices,
    };
}

// ======================= 编辑日程 =======================

/**
 * 编辑日程（更新主表 + 重建关联）
 */
export async function editSchedule(params: {
    scheduleId: number;
    title: string;
    schedule_time: string;
    ac_control: string;
    begin_validity?: string;
    end_validity?: string;
    deviceIds: string[];
    regionKeys: number[];
}): Promise<any> {
    const { scheduleId, title, schedule_time, ac_control, begin_validity, end_validity, deviceIds, regionKeys } = params;

    console.log(`[编辑日程] id=${scheduleId}, title=${title}`);

    // 1. 更新 schedule 主表
    await updateManyData(TABLENAME.日程表, { id: scheduleId }, {
        title,
        schedule_time,
        ac_control,
        begin_validity: begin_validity || null,
        end_validity: end_validity || null,
    });

    // 2. 删除旧的关联记录
    await delData(TABLENAME.日程设备关联表, { schedule_id: scheduleId });

    // 3. 查空调设备（优先 deviceIds，补充区域维度）
    let devices: any[] = [];
    if (deviceIds && deviceIds.length) {
        const deviceRes = await selectDataListByParam(TABLENAME.设备表, {
            device_type: "空调",
            device_id: { "%in%": deviceIds },
        }, ["device_id", "region_key"]);
        devices = deviceRes.data || [];
    } else if (regionKeys && regionKeys.length) {
        const deviceRes = await selectDataListByParam(TABLENAME.设备表, {
            device_type: "空调",
            region_key: { "%in%": regionKeys },
        }, ["device_id", "region_key"]);
        devices = deviceRes.data || [];
    }

    // 4. 重建关联
    if (devices.length > 0) {
        const sdRecords = devices.map((d: any) => ({
            schedule_id: scheduleId,
            device_id: d.device_id,
            region_key: d.region_key,
        }));
        await addData(TABLENAME.日程设备关联表, sdRecords);
        console.log(`[编辑日程] 重建关联设备 ${sdRecords.length} 条`);
    } else if (regionKeys && regionKeys.length) {
        for (const rk of regionKeys) {
            await addData(TABLENAME.日程设备关联表, {
                schedule_id: scheduleId,
                device_id: "",
                region_key: rk,
            });
        }
        console.log(`[编辑日程] 区域 ${regionKeys.length} 个，暂无设备`);
    }

    clearOffPeriodCache(); // 编辑日程后清空开关机时段缓存
    return { isSuccess: true };
}

// ======================= 删除日程 =======================

/**
 * 删除日程（含关联记录）
 */
export async function deleteSchedule(scheduleId: number): Promise<any> {
    console.log(`[删除日程] id=${scheduleId}`);

    // 1. 删除关联记录
    await delData(TABLENAME.日程设备关联表, { schedule_id: scheduleId });

    // 2. 删除主记录
    await delData(TABLENAME.日程表, { id: scheduleId });

    clearOffPeriodCache(); // 删除日程后清空开关机时段缓存
    return { isSuccess: true };
}
