/**
 * Form 16 archive job: move records older than 5 financial years to archive (set archived_at).
 * No deletion; full data retained for audit. Scheduler runs daily at 02:00.
 */

import { sequelize } from '../config/database';
import { QueryTypes } from 'sequelize';
import logger from '../utils/logger';

const TZ = process.env.TZ || 'Asia/Kolkata';

/** Current financial year start (e.g. 2025 if we are in Apr 2025). */
function getCurrentFYStartYear(): number {
  const now = new Date();
  const year = now.getFullYear();
  const month = now.getMonth() + 1;
  if (month >= 4) return year;
  return year - 1;
}

/**
 * Archive Form 16 / 26AS records older than 5 financial years.
 * Sets archived_at = NOW() where financial_year start <= (currentFYStart - 5).
 * No rows are deleted.
 */
export async function runForm16ArchiveOldRecords(): Promise<{
  tds26as: number;
  snapshots: number;
  quarterStatus: number;
  ledger: number;
  creditNotes: number;
  debitNotes: number;
  submissions: number;
}> {
  const now = new Date();
  const currentStart = getCurrentFYStartYear();
  const cutoffStart = currentStart - 5;
  const results = {
    tds26as: 0,
    snapshots: 0,
    quarterStatus: 0,
    ledger: 0,
    creditNotes: 0,
    debitNotes: 0,
    submissions: 0,
  };

  try {
    await sequelize.transaction(async (tx) => {
      const tables: Array<{ table: string; fyColumn: string; resultKey: keyof typeof results }> = [
        { table: 'tds_26as_entries', fyColumn: 'financial_year', resultKey: 'tds26as' },
        { table: 'form_16_26as_quarter_snapshots', fyColumn: 'financial_year', resultKey: 'snapshots' },
        { table: 'form_16_quarter_status', fyColumn: 'financial_year', resultKey: 'quarterStatus' },
        { table: 'form_16_ledger_entries', fyColumn: 'financial_year', resultKey: 'ledger' },
        { table: 'form_16_credit_notes', fyColumn: 'financial_year', resultKey: 'creditNotes' },
        { table: 'form16a_submissions', fyColumn: 'financial_year', resultKey: 'submissions' },
      ];

      for (const { table, fyColumn, resultKey } of tables) {
        const [res] = await sequelize.query(
          `UPDATE ${table} SET archived_at = :now
           WHERE archived_at IS NULL
             AND TRIM(${fyColumn}) ~ '^[0-9]{4}-'
             AND (SUBSTRING(TRIM(${fyColumn}) FROM 1 FOR 4))::int <= :cutoff`,
          {
            replacements: { now, cutoff: cutoffStart },
            type: QueryTypes.UPDATE,
            transaction: tx,
          }
        );
        const count = typeof res === 'number' ? res : (res as any)?.rowCount ?? (res as any) ?? 0;
        (results as any)[resultKey] = count;
      }

      await sequelize.query(
        `UPDATE form_16_debit_notes dn
         SET archived_at = :now
         FROM form_16_credit_notes cn
         WHERE dn.credit_note_id = cn.id
           AND dn.archived_at IS NULL
           AND cn.archived_at IS NOT NULL`,
        {
          replacements: { now },
          type: QueryTypes.UPDATE,
          transaction: tx,
        }
      );
    });

    const total = Object.values(results).reduce((a, b) => a + b, 0);
    if (total > 0) {
      logger.info(`[Form16 Archive] Archived ${total} record(s) older than FY ${cutoffStart}-${String(cutoffStart + 1).slice(-2)}`, results);
    }
    return results;
  } catch (err) {
    logger.error('[Form16 Archive] Error archiving old records', err);
    throw err;
  }
}

/**
 * Start Form 16 archive scheduler: run daily at 02:00 (configurable TZ).
 */
export function startForm16ArchiveJob(): void {
  const cron = require('node-cron');
  cron.schedule('0 2 * * *', async () => {
    try {
      await runForm16ArchiveOldRecords();
    } catch (e) {
      logger.error('[Form16 Archive Job] Failed', e);
    }
  }, { timezone: TZ });

  logger.info(`[Form16 Archive Job] Daily archive job scheduled at 02:00 (TZ: ${TZ}). Keeps last 5 FY active.`);
}
