/**
 * Auditor T2E (2026-06-01) — partition-maintenance planner tests.
 *
 * The planner is pure (no DB) — given a list of existing partitions
 * and a "now" anchor, it returns which partitions to add and which
 * to drop. The service's tick() wraps this with the live DB calls;
 * we don't test the DDL execution here.
 */
import { planPartitionMaintenance } from '../partition-maintenance.service';

const NOW = new Date(Date.UTC(2026, 5, 15)); // 2026-06-15 (June)

describe('planPartitionMaintenance (auditor T2E)', () => {
    it('adds the next N months when only the current month exists', () => {
        const plan = planPartitionMaintenance(
            ['p202606', 'pmax'],
            { lookaheadMonths: 3, retentionMonths: 3, now: NOW }
        );
        // Current + 3 ahead → June, July, August, September
        // June already exists → only July/Aug/Sep are added.
        expect(plan.toAdd.map((p) => p.name)).toEqual([
            'p202607',
            'p202608',
            'p202609',
        ]);
    });

    it('produces correct lessThan boundary (first day of NEXT month)', () => {
        const plan = planPartitionMaintenance(
            ['pmax'],
            { lookaheadMonths: 1, retentionMonths: 3, now: NOW }
        );
        // p202606 < 2026-07-01, p202607 < 2026-08-01.
        expect(plan.toAdd).toEqual([
            { name: 'p202606', lessThan: '2026-07-01' },
            { name: 'p202607', lessThan: '2026-08-01' },
        ]);
    });

    it('handles year boundary (December → January)', () => {
        const dec = new Date(Date.UTC(2026, 11, 1)); // 2026-12-01
        const plan = planPartitionMaintenance(
            ['pmax'],
            { lookaheadMonths: 2, retentionMonths: 3, now: dec }
        );
        expect(plan.toAdd).toEqual([
            { name: 'p202612', lessThan: '2027-01-01' },
            { name: 'p202701', lessThan: '2027-02-01' },
            { name: 'p202702', lessThan: '2027-03-01' },
        ]);
    });

    it('drops partitions older than retention window', () => {
        const plan = planPartitionMaintenance(
            // April 2026 partition exists but is older than 3-month retention from June.
            ['p202601', 'p202602', 'p202603', 'p202606', 'pmax'],
            { lookaheadMonths: 0, retentionMonths: 3, now: NOW }
        );
        // Retention cutoff = June - 3mo = March 2026. Anything < March drops.
        // p202601 (Jan), p202602 (Feb) are older than cutoff → drop.
        // p202603 (March) is exactly on cutoff → keep (boundary not strict-less).
        expect(plan.toDrop).toEqual(['p202601', 'p202602']);
    });

    it('never drops pmax', () => {
        const plan = planPartitionMaintenance(
            ['p202501', 'pmax'],
            { lookaheadMonths: 0, retentionMonths: 1, now: NOW }
        );
        expect(plan.toDrop).not.toContain('pmax');
    });

    it('never drops partitions in the wanted-keep set', () => {
        // Edge case: if retention is shorter than 1 month and current
        // month is in both sets, must NOT drop it.
        const plan = planPartitionMaintenance(
            ['p202606', 'pmax'],
            { lookaheadMonths: 0, retentionMonths: 0, now: NOW }
        );
        expect(plan.toDrop).not.toContain('p202606');
    });

    it('is idempotent: re-running after the prior toAdd ran returns empty toAdd', () => {
        const first = planPartitionMaintenance(
            ['p202606', 'pmax'],
            { lookaheadMonths: 2, retentionMonths: 3, now: NOW }
        );
        const afterFirstRun = ['p202606', ...first.toAdd.map((p) => p.name), 'pmax'];

        const second = planPartitionMaintenance(afterFirstRun, {
            lookaheadMonths: 2,
            retentionMonths: 3,
            now: NOW,
        });
        expect(second.toAdd).toEqual([]);
    });

    it('ignores partitions with non-conforming names (e.g. pmax)', () => {
        const plan = planPartitionMaintenance(
            ['pmax', 'p_oldname', 'p202606'],
            { lookaheadMonths: 0, retentionMonths: 3, now: NOW }
        );
        // Doesn't choke on pmax/p_oldname. Only p202606 is parsed.
        expect(plan.toDrop).toEqual([]);
    });
});
