// oms/services/cron-jobs/done-rate.ts

import dayjs from "dayjs";
import doneRateService from "../../src/services/doneRateService"; // 导入 DoneRateService
import { clickhouseService } from "../../src/services/clients";
import mongoose, { Connection } from "mongoose"; // 导入 mongoose 和 Connection 用于处理远程连接
import TotalDoneRate from "../../src/models/totalDoneRateModel"; // 导入新的 TotalDoneRate 模型

// ClickHouse 表名
const CLICKHOUSE_EVENTS_TABLE = "events"; // 确保与 ClickHouseService 中的表名一致

/**
 * ClickHouse 查询结果接口：每日每个作品的独立开始用户数
 */
interface ClickHouseStartCountResult {
  res: string; // 作品 ID
  unique_starts: number; // 独立开始用户数
}

/**
 * ClickHouse 查询结果接口：每日每个作品的独立完成用户数
 */
interface ClickHouseDoneCountResult {
  res: string; // 作品 ID
  unique_dones: number; // 独立完成用户数
}

/**
 * 每日统计昨天的作品完成率。
 * 统计逻辑从 ClickHouse 中提取数据，得到每个作品的完成情况，并更新到 doneRateModel。
 * 随后，根据这些日统计数据，累加更新本地的 totalDoneRate 表。
 * @returns Promise<string> - 返回统计结果的摘要信息。
 */
async function run(): Promise<string> {
  console.log("[DoneRate Cron] Starting daily done-rate calculation for yesterday..."); // 获取昨天和今天的日期

  // 获取昨天和今天的日期
  const yesterday = dayjs().subtract(1, "day");
  const yesterdayYYYYMMDD = yesterday.format("YYYYMMDD");
  const yesterdayStart = yesterday.startOf("day").toDate();
  const yesterdayEnd = yesterday.endOf("day").toDate();

  // 格式化日期字符串，使其符合 ClickHouse 的 toDateTime() 函数要求
  const yesterdayStartString = dayjs(yesterdayStart).format("YYYY-MM-DD HH:mm:ss");
  const yesterdayEndString = dayjs(yesterdayEnd).format("YYYY-MM-DD HH:mm:ss");

  console.log(`[DoneRate Cron] Processing data for date: ${yesterdayYYYYMMDD}`);

  try {
    // --- 1. 从 ClickHouse 中提取数据 ---

    // 查询昨天每个作品的独立开始用户数
    const startCountsQuery = `
      SELECT
          res,
          count(DISTINCT uid) AS unique_starts
      FROM ${CLICKHOUSE_EVENTS_TABLE}
      WHERE event = 'color_start'
        AND time >= toDateTime('${yesterdayStartString}')
        AND time < toDateTime('${yesterdayEndString}')
      GROUP BY res
      HAVING res IS NOT NULL
    `;
    const startResults = await clickhouseService.queryEvents<ClickHouseStartCountResult>(startCountsQuery);
    const artworkStartCounts = new Map<string, number>();
    startResults.forEach((row) => {
      if (row.res && mongoose.Types.ObjectId.isValid(row.res)) {
        artworkStartCounts.set(row.res, row.unique_starts);
      } else {
        console.warn(`[DoneRate Cron] Invalid artwork ID found in start_counts result: ${row.res}`);
      }
    });
    console.log(`[DoneRate Cron] Retrieved ${startResults.length} unique start counts from ClickHouse.`); // 查询昨天每个作品的独立完成用户数

    // 查询昨天每个作品的独立完成用户数
    const doneCountsQuery = `
      SELECT
          res,
          count(DISTINCT uid) AS unique_dones
      FROM ${CLICKHOUSE_EVENTS_TABLE}
      WHERE event = 'color_done'
        AND time >= toDateTime('${yesterdayStartString}')
        AND time < toDateTime('${yesterdayEndString}')
      GROUP BY res
      HAVING res IS NOT NULL
    `;
    const doneResults = await clickhouseService.queryEvents<ClickHouseDoneCountResult>(doneCountsQuery);
    const artworkDoneCounts = new Map<string, number>();
    doneResults.forEach((row) => {
      if (row.res && mongoose.Types.ObjectId.isValid(row.res)) {
        artworkDoneCounts.set(row.res, row.unique_dones);
      } else {
        console.warn(`[DoneRate Cron] Invalid artwork ID found in done_counts result: ${row.res}`);
      }
    });
    console.log(`[DoneRate Cron] Retrieved ${doneResults.length} unique done counts from ClickHouse.`);

    // --- 2. 合并数据并更新 DoneRate 模型 ---
    let updatedRecordsCount = 0; // for DoneRate
    let createdRecordsCount = 0; // for DoneRate

    // 遍历所有有开始事件的作品ID
    for (const [resIdStr, startCount] of artworkStartCounts.entries()) {
      const doneCount = artworkDoneCounts.get(resIdStr) || 0;
      const resObjectId = new mongoose.Types.ObjectId(resIdStr);

      // 使用 DoneRateService 来创建或更新记录
      const doneRateDoc = await doneRateService.createOrUpdateDoneRate(yesterdayYYYYMMDD, resObjectId, startCount, doneCount);
      if (doneRateDoc.createdAt.getTime() === doneRateDoc.updatedAt.getTime()) {
        createdRecordsCount++;
      } else {
        updatedRecordsCount++;
      }
      artworkDoneCounts.delete(resIdStr); // 已经处理过的作品ID从 doneCounts 中移除
    }

    // 处理只有完成事件但没有开始事件的作品 (通常不应发生，但以防万一)
    for (const [resIdStr, doneCount] of artworkDoneCounts.entries()) {
      const startCount = 0; // 没有开始事件，所以开始次数为0
      const resObjectId = new mongoose.Types.ObjectId(resIdStr);

      const doneRateDoc = await doneRateService.createOrUpdateDoneRate(yesterdayYYYYMMDD, resObjectId, startCount, doneCount);
      if (doneRateDoc.createdAt.getTime() === doneRateDoc.updatedAt.getTime()) {
        createdRecordsCount++;
      } else {
        updatedRecordsCount++;
      }
    }

    const totalProcessedArtworks = createdRecordsCount + updatedRecordsCount;

    console.log(`[DoneRate Cron] DoneRate model update completed. Total artworks processed: ${totalProcessedArtworks}. Created: ${createdRecordsCount}, Updated: ${updatedRecordsCount}.`); // --- 3. 获取昨天的所有 DoneRate 记录，并更新本地的 totalDoneRate 表 ---

    let updatedTotalDoneRateCount = 0;
    const yesterdayDoneRates = await doneRateService.getDoneRatesByDate(yesterdayYYYYMMDD);

    const totalDoneRatesToUpdate = yesterdayDoneRates.length;
    let updateStartTime = new Date().getTime();
    console.log(`[DoneRate Cron] 开始更新本地 TotalDoneRate 表。总计 ${totalDoneRatesToUpdate} 条记录。`);

    for (let i = 0; i < totalDoneRatesToUpdate; i++) {
      const doneRateDoc = yesterdayDoneRates[i];
      try {
        const artworkId = doneRateDoc.res; // 获取作品 ObjectId

        // 查找现有的 TotalDoneRate 文档
        const existingTotal = await TotalDoneRate.findById(artworkId);

        let newTotalStartCount = doneRateDoc.startCount;
        let newTotalDoneCount = doneRateDoc.doneCount;

        if (existingTotal) {
          // 如果已存在，则累加
          newTotalStartCount += existingTotal.totalStartCount || 0;
          newTotalDoneCount += existingTotal.totalDoneCount || 0;
        }

        const newCompletionRate = newTotalStartCount > 0 ? (newTotalDoneCount / newTotalStartCount) * 100 : 0;

        // 使用 findByIdAndUpdate 进行原子操作，确保数据一致性
        // 这里的 _id 是根据 artworkId 来查找或创建的
        const updatedDoc = await TotalDoneRate.findByIdAndUpdate(
          artworkId,
          {
            $set: {
              totalStartCount: newTotalStartCount,
              totalDoneCount: newTotalDoneCount,
              completionRate: newCompletionRate,
            },
          },
          { new: true, upsert: true } // upsert: true 表示如果文档不存在则创建
        );

        if (updatedDoc) {
          updatedTotalDoneRateCount++;
        }

        // 进度日志
        if ((i + 1) % 50 === 0 || i === totalDoneRatesToUpdate - 1) {
          const elapsed = new Date().getTime() - updateStartTime;
          console.log(`[DoneRate Cron] 进度: 已更新 ${i + 1}/${totalDoneRatesToUpdate} 条本地 TotalDoneRate 记录, 当前耗时: ${elapsed}ms`);
        }
      } catch (totalUpdateError) {
        console.error(`[DoneRate Cron] Error updating TotalDoneRate document for artwork ID ${doneRateDoc.res}:`, totalUpdateError);
      }
    }

    const updateTimeTaken = new Date().getTime() - updateStartTime;
    console.log(`[DoneRate Cron] 本地 TotalDoneRate 表更新完成。总计更新 ${updatedTotalDoneRateCount} 条记录，总耗时 ${updateTimeTaken}ms。`);

    const summary = `[DoneRate Cron] Daily done-rate calculation for ${yesterdayYYYYMMDD} completed. Total DoneRate processed: ${totalProcessedArtworks}. Created DoneRate: ${createdRecordsCount}, Updated DoneRate: ${updatedRecordsCount}. Updated TotalDoneRate records: ${updatedTotalDoneRateCount}.`;
    console.log(summary);
    return summary;
  } catch (error) {
    console.error(`[DoneRate Cron] Error during done-rate calculation for ${yesterdayYYYYMMDD}:`, error);
    throw new Error("Failed to calculate daily done-rates."); // 抛出错误以通知 cron 调度器
  } finally {
  }
}

export = { run }; // 导出 run 函数以供 cron-jobs/index.ts 使用
