import { Injectable } from '@nestjs/common';
import { createLogger } from '@core/observability/logging/config/winston.config';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { SkipAssertAccess } from '@common/decorators/skip-assert-access.decorator';

const logger = createLogger('TrajectoryRetentionService');

export interface RetentionPolicy {
  /** 保留天数，超过则候选 archive；0 表示永久保留 */
  retainDays: number;
  /** archive 后是否物理删除（false → soft archive 字段，目前未实现表层 flag）*/
  hardDelete: boolean;
}

/**
 * PR4c retention job 骨架。
 *
 * **当前状态**：
 *   - `previewDeletion()` 跑 SQL count + 返回候选列表，**只读**，可以现在跑
 *   - `executeDeletion()` 会真删 → 本 session 不调用；上 cron 时由 admin 显式 trigger
 *
 * Retention 跟 anchor 解耦：被删除的 event 在 anchor 周期已锚定的话，
 * 后续校验仍能用外部 anchor + 残留 chain segment 证明历史完整性。
 *
 * 真实生产：与 docs/standards/`合规保留期` 对齐（金融/HR/IT 等不同分类 retention 不同）。
 */
@Injectable()
export class TrajectoryRetentionService {
  constructor(private readonly prisma: PrismaService) {}

  async previewDeletion(policy: RetentionPolicy): Promise<{
    candidateCount: number;
    oldestCreatedAt: Date | null;
  }> {
    if (policy.retainDays <= 0) {
      return { candidateCount: 0, oldestCreatedAt: null };
    }
    const cutoff = new Date(Date.now() - policy.retainDays * 24 * 60 * 60 * 1000);
    const candidates = await this.prisma.agentTrajectoryEvent.findMany({
      where: { createdAt: { lt: cutoff } },
      select: { id: true, createdAt: true },
      orderBy: { createdAt: 'asc' },
      take: 1,
    });
    const count = await this.prisma.agentTrajectoryEvent.count({
      where: { createdAt: { lt: cutoff } },
    });
    return {
      candidateCount: count,
      oldestCreatedAt: candidates[0]?.createdAt ?? null,
    };
  }

  /**
   * 真删——管理员明示 trigger。
   * 不删 anchor 表（如已建）；不删 message 表（message 是用户数据，单独 retention 通道）。
   */
  @SkipAssertAccess('admin retention 任务，按时间窗全局删除审计事件，无 per-org IDOR；调用入口已限 admin 权限')
  async executeDeletion(policy: RetentionPolicy): Promise<{ deletedCount: number }> {
    if (policy.retainDays <= 0) {
      logger.log('Retention disabled (retainDays=0); nothing to delete');
      return { deletedCount: 0 };
    }
    if (!policy.hardDelete) {
      logger.warn('soft-archive flag not implemented yet; falling back to no-op');
      return { deletedCount: 0 };
    }
    const cutoff = new Date(Date.now() - policy.retainDays * 24 * 60 * 60 * 1000);
    const r = await this.prisma.agentTrajectoryEvent.deleteMany({
      where: { createdAt: { lt: cutoff } },
    });
    logger.log(`Retention deleted ${r.count} trajectory events older than ${cutoff.toISOString()}`);
    return { deletedCount: r.count };
  }
}
