import { NextResponse } from 'next/server';
import { spawn } from 'node:child_process';
import path from 'node:path';
import { checkSystemBin } from '@/lib/system-bins';

export const dynamic = 'force-dynamic';
export const maxDuration = 600;

const DATA_DIR = path.join(process.cwd(), 'data');

function timestamp(): string {
  const d = new Date();
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
}

export async function GET() {
  if (!(await checkSystemBin('zip', '-v'))) {
    return NextResponse.json({ error: "Binario 'zip' non disponibile sul server." }, { status: 503 });
  }

  // -r ricorsivo, - stdout, -x esclude pattern relativi al cwd.
  // Stato runtime escluso: .tmp/, transcode-jobs.json.
  const child = spawn(
    'zip',
    [
      '-r', '-',
      'cards.txt', 'portals.txt', 'uploads', 'fonts',
      '-x', 'uploads/.tmp/*',
    ],
    { cwd: DATA_DIR },
  );

  // Adatta stdout di Node a Web ReadableStream per la Response di Next.
  const stream = new ReadableStream<Uint8Array>({
    start(controller) {
      child.stdout.on('data', (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)));
      child.stdout.on('end', () => controller.close());
      child.on('error', (err) => controller.error(err));
      child.on('exit', code => {
        if (code !== 0 && code !== null) {
          // 12 = "nothing to do" (cartella vuota). Tutto il resto è errore vero.
          if (code !== 12) controller.error(new Error(`zip exited with code ${code}`));
        }
      });
    },
    cancel() {
      try { child.kill('SIGTERM'); } catch { /* ignore */ }
    },
  });

  return new Response(stream, {
    headers: {
      'Content-Type': 'application/zip',
      'Content-Disposition': `attachment; filename="interceptop-backup-${timestamp()}.zip"`,
      'Cache-Control': 'no-store',
    },
  });
}
