import { Injectable } from "@nestjs/common";
import { Cron } from "@nestjs/schedule";
import { startOfYear } from "src/time-and-attendance/attachments/cas.util";
import { PrismaPostgresService } from "prisma/postgres/prisma-postgres.service";

@Injectable()
export class AttachmentArchivalService {
    private readonly batch_size = Number(process.env.ARCHIVE_BATCH_SIZE || 1000);
    private readonly cron_expression = process.env.ARCHIVE_CRON || '0 3 * * 1';

    constructor(private readonly prisma: PrismaPostgresService) { }


    @Cron(function (this: AttachmentArchivalService) { return this.cron_expression; } as any)
    async runScheduled() {
        await this.archiveCutoffToStartOfYear();
    }

    //archive everything before current year
    async archiveCutoffToStartOfYear() {
        const cutoff = startOfYear();
        console.log(`Archival: cutoff=${cutoff.toISOString()} batch=${this.batch_size}`);

        let moved = 0, total = 0, i = 0;
        do {
            moved = await this.archiveBatch(cutoff, this.batch_size);
            total += moved;
            i++;
            if (moved > 0) console.log(`Batch #${i}: moved ${moved}`);
        } while (moved === this.batch_size);

        console.log(`Archival done: total moved : ${total}`);
        return { moved: total };
    }

    //only moves table content to archive and not blobs.
    private async archiveBatch(cutoff: Date, batch_size: number): Promise<number> {
        const moved = await this.prisma.client.$executeRaw `
        WITH moved AS (
            DELETE FROM "attachments"
            WHERE id IN (
                SELECT id FROM "attachments"
                WHERE created_at < ${cutoff}
                ORDER BY id
                LIMIT ${batch_size}
            )
            RETURNING id, sha256, owner_type, owner_id, original_name, status, retention_policy, created_by, created_at
        )
        INSERT INTO archive.attachments_archive
            (id, sha256, owner_type, owner_id, original_name, status, retention_policy, created_by, created_at)
            SELECT * FROM moved;`;
        return Number(moved) || 0;
    }

}