/**
 * 日志清理服务
 * 定时清理过期日志，防止数据库膨胀
 */

import { Injectable, OnModuleInit } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { LogLevel } from '@prisma/client';
import { winstonLogger } from '../config/winston.config';

@Injectable()
export class LogCleanupService implements OnModuleInit {
  // 日志保留天数配置
  private readonly retentionDays = {
    [LogLevel.ERROR]: 90,   // 错误日志保留 90 天
    [LogLevel.WARN]: 30,    // 警告日志保留 30 天
    [LogLevel.INFO]: 14,    // 信息日志保留 14 天
    [LogLevel.DEBUG]: 7,    // 调试日志保留 7 天
  };

  // 告警保留天数
  private readonly alertRetentionDays = 90;

  // 清理记录保留天数
  private readonly cleanupRecordRetentionDays = 30;

  constructor(private readonly prisma: PrismaService) {}

  onModuleInit() {
    winstonLogger.info('LogCleanupService initialized', {
      retentionDays: this.retentionDays,
      alertRetentionDays: this.alertRetentionDays,
    });
  }

  /**
   * 每天凌晨 3 点执行日志清理
   */
  @Cron(CronExpression.EVERY_DAY_AT_3AM)
  async cleanupLogs(): Promise<void> {
    winstonLogger.info('Starting scheduled log cleanup...');

    const startTime = Date.now();
    let totalDeleted = 0;

    try {
      // 按级别清理日志
      for (const [level, days] of Object.entries(this.retentionDays)) {
        const cutoffDate = new Date();
        cutoffDate.setDate(cutoffDate.getDate() - days);

        const result = await this.prisma.systemLog.deleteMany({
          where: {
            level: level as LogLevel,
            createdAt: { lt: cutoffDate },
          },
        });

        if (result.count > 0) {
          winstonLogger.info(`Cleaned up ${result.count} ${level} logs older than ${days} days`);
          totalDeleted += result.count;
        }
      }

      // 清理过期告警
      const alertCutoffDate = new Date();
      alertCutoffDate.setDate(alertCutoffDate.getDate() - this.alertRetentionDays);

      const alertResult = await this.prisma.logAlert.deleteMany({
        where: {
          createdAt: { lt: alertCutoffDate },
        },
      });

      if (alertResult.count > 0) {
        winstonLogger.info(`Cleaned up ${alertResult.count} alerts older than ${this.alertRetentionDays} days`);
      }

      // 清理过期清理记录
      const cleanupRecordCutoffDate = new Date();
      cleanupRecordCutoffDate.setDate(cleanupRecordCutoffDate.getDate() - this.cleanupRecordRetentionDays);

      const cleanupRecordResult = await this.prisma.logCleanupRecord.deleteMany({
        where: {
          startedAt: { lt: cleanupRecordCutoffDate },
        },
      });

      if (cleanupRecordResult.count > 0) {
        winstonLogger.info(`Cleaned up ${cleanupRecordResult.count} cleanup records older than ${this.cleanupRecordRetentionDays} days`);
      }

      // 记录本次清理
      await this.prisma.logCleanupRecord.create({
        data: {
          type: 'scheduled',
          olderThanDays: 0, // 使用配置的保留天数
          dryRun: false,
          deletedCount: totalDeleted + alertResult.count,
          status: 'COMPLETED',
          completedAt: new Date(),
        },
      });

      const duration = Date.now() - startTime;
      winstonLogger.info(`Log cleanup completed in ${duration}ms, total deleted: ${totalDeleted + alertResult.count}`);

    } catch (error) {
      winstonLogger.error('Log cleanup failed', { error: (error as Error).message });

      // 记录失败
      await this.prisma.logCleanupRecord.create({
        data: {
          type: 'scheduled',
          olderThanDays: 0,
          dryRun: false,
          deletedCount: totalDeleted,
          status: 'FAILED',
          errorMessage: (error as Error).message,
          completedAt: new Date(),
        },
      });
    }
  }

  /**
   * 每小时检查日志表大小（可选的监控功能）
   */
  @Cron(CronExpression.EVERY_HOUR)
  async checkLogTableSize(): Promise<void> {
    try {
      // 获取日志数量
      const [totalLogs, errorLogs, recentLogs] = await Promise.all([
        this.prisma.systemLog.count(),
        this.prisma.systemLog.count({ where: { level: LogLevel.ERROR } }),
        this.prisma.systemLog.count({
          where: {
            createdAt: { gte: new Date(Date.now() - 60 * 60 * 1000) }, // 最近 1 小时
          },
        }),
      ]);

      // 如果日志量过大，记录警告
      if (totalLogs > 1000000) {
        winstonLogger.warn('Log table size warning', {
          totalLogs,
          errorLogs,
          recentLogs,
          message: `Log table has ${totalLogs} records, consider cleanup`,
        });
      } else {
        winstonLogger.debug('Log table size check', {
          totalLogs,
          errorLogs,
          recentLogs,
        });
      }
    } catch (error) {
      winstonLogger.error('Failed to check log table size', { error: (error as Error).message });
    }
  }

  /**
   * 手动触发清理（供 API 调用）
   */
  async manualCleanup(options: {
    level?: LogLevel;
    olderThanDays: number;
    dryRun?: boolean;
  }): Promise<{ deletedCount: number }> {
    const { level, olderThanDays, dryRun = false } = options;

    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);

    const where: any = {
      createdAt: { lt: cutoffDate },
    };

    if (level) {
      where.level = level;
    }

    // 统计数量
    const count = await this.prisma.systemLog.count({ where });

    if (!dryRun && count > 0) {
      await this.prisma.systemLog.deleteMany({ where });
    }

    // 记录清理操作
    await this.prisma.logCleanupRecord.create({
      data: {
        type: level || 'all',
        olderThanDays,
        dryRun,
        deletedCount: dryRun ? 0 : count,
        status: 'COMPLETED',
        completedAt: new Date(),
      },
    });

    return { deletedCount: dryRun ? 0 : count };
  }
}

