/**
 * OCDS bulk export — streaming JSONL by year.
 * GET /api/ocds/bulk/year/{YYYY} → application/x-ndjson, one Release per line.
 *
 * Streamed via PostgreSQL cursor (batch=500 rows) so we never hold the
 * whole year in memory. ~30-50K rows/year → ~50-150MB plaintext.
 * Gzip is delegated to Traefik compress middleware (if enabled).
 *
 * Use case: power users + civic-tech tooling want to bulk-ingest data.
 * For incremental sync use the paginated /api/ocds/releases endpoint.
 */
import type { APIRoute } from 'astro';
import pg from 'pg';
// @ts-expect-error — pg-cursor has no .d.ts in current version
import Cursor from 'pg-cursor';
import { announcementToRelease, type AnnouncementRow } from '../../../../../lib/ocds-mapper.js';

export const prerender = false;

const SQL = `
  SELECT
    a.id, a.ref_number, a.type, a.source, a.title, a.description,
    a.publication_date, a.contract_date,
    a.estimated_value, a.awarded_value, a.currency,
    a.procedure_type, a.procedure_state,
    a.framework_agreement, a.modification_desc,
    a.cpv_code, a.cpv_name, a.cpv_division,
    a.authority_cui, a.authority_name, a.authority_address,
    a.authority_email, a.authority_phone, a.authority_url,
    acl.county AS authority_county, a.authority_siruta,
    a.supplier_cui, a.supplier_name, a.supplier_address,
    scl.county AS supplier_county, a.supplier_siruta,
    a.supplier_is_sme, a.contract_has_lots, a.lots_count,
    a.seap_url
  FROM seap.announcements a
  LEFT JOIN seap.cui_location acl ON acl.cui = a.authority_cui
  LEFT JOIN seap.cui_location scl ON scl.cui = regexp_replace(upper(a.supplier_cui), '(^RO)|\\s+', '', 'g')
  WHERE EXTRACT(YEAR FROM a.publication_date) = $1
  ORDER BY a.publication_date NULLS LAST, a.id
`;

let pool: pg.Pool | null = null;
function getPool(): pg.Pool {
  if (!pool) {
    pool = new pg.Pool({
      connectionString: process.env.DATABASE_URL || import.meta.env.DATABASE_URL,
      max: 2,
    });
  }
  return pool;
}

export const GET: APIRoute = async ({ params }) => {
  const year = parseInt(params.year as string);
  if (isNaN(year) || year < 2007 || year > 2030) {
    return new Response(JSON.stringify({ error: 'Year must be 2007-2030' }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  const stream = new ReadableStream<Uint8Array>({
    async start(controller) {
      const client = await getPool().connect();
      try {
        const cursor: any = client.query(new Cursor(SQL, [year]));
        const enc = new TextEncoder();
        let total = 0;
        // Header line — package metadata as first line (NDJSON-package convention)
        const header = {
          version: '1.1',
          publisher: { name: 'vreaudigital.ro', uri: 'https://vreaudigital.ro' },
          license: 'https://creativecommons.org/licenses/by/4.0/',
          publicationPolicy: 'https://vreaudigital.ro/api/ocds',
          publishedDate: new Date().toISOString(),
          extent: { year, source: 'SEAP / TED / datagov' },
        };
        controller.enqueue(enc.encode('# ' + JSON.stringify(header) + '\n'));

        const readBatch = (n: number): Promise<AnnouncementRow[]> =>
          new Promise((resolve, reject) => {
            cursor.read(n, (err: Error | null, rows: AnnouncementRow[]) =>
              err ? reject(err) : resolve(rows),
            );
          });

        let batch: AnnouncementRow[];
        do {
          batch = await readBatch(500);
          for (const row of batch) {
            const release = announcementToRelease(row);
            controller.enqueue(enc.encode(JSON.stringify(release) + '\n'));
            total++;
          }
        } while (batch.length > 0);

        cursor.close(() => client.release());
        controller.close();
      } catch (err) {
        try { client.release(); } catch {}
        controller.error(err);
      }
    },
  });

  return new Response(stream, {
    status: 200,
    headers: {
      'Content-Type': 'application/x-ndjson; charset=utf-8',
      'Content-Disposition': `attachment; filename="ocds-vreaudigital-${year}.jsonl"`,
      'Access-Control-Allow-Origin': '*',
      'Cache-Control': 'public, max-age=3600, s-maxage=86400',
      'X-OCDS-Version': '1.1',
    },
  });
};
