import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';

const OUT_DIR = process.cwd();

const packageDocs = [
  {
    outPath: path.resolve(OUT_DIR, 'SOLICITUD_Y_DIBUJOS_OEPM_FARMAFINDER.pdf'),
    pages: [
      { kind: 'cover', title: 'ANEXO DE DIBUJOS E INSTANCIA', subtitle: 'Expediente de Patente para FarmaFinder' },
      { kind: 'instance' },
      { kind: 'diagram1' },
      { kind: 'diagram2' },
      { kind: 'diagram3' },
      { kind: 'diagram4' }
    ]
  }
];

function esc(s) {
  return String(s).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
}

function makePdf({ outPath, pages }) {
  const PAGE_W = 595.28;
  const PAGE_H = 841.89;
  const MARGIN_L = 48;
  const MARGIN_R = 48;
  const CONTENT_W = PAGE_W - MARGIN_L - MARGIN_R;

  const objects = [''];
  const contentNums = [];
  const pageNums = [];
  const add = (x) => (objects.push(x), objects.length - 1);
  const f1 = add('<< /Type /Font /Subtype /Type1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >>');
  const f2 = add('<< /Type /Font /Subtype /Type1 /BaseFont /Times-Bold /Encoding /WinAnsiEncoding >>');
  const f3 = add('<< /Type /Font /Subtype /Type1 /BaseFont /Times-Italic /Encoding /WinAnsiEncoding >>');

  const wrap = (text, max) => {
    const words = String(text).split(/\s+/);
    const lines = [];
    let line = '';
    for (const word of words) {
      const cand = line ? `${line} ${word}` : word;
      if (cand.length > max && line) {
        lines.push(line);
        line = word;
      } else {
        line = cand;
      }
    }
    if (line) lines.push(line);
    return lines;
  };

  function pageOps(page) {
    const ops = [];
    const drawText = (txt, x, y, size = 11, font = 'F1') => {
      ops.push(`BT /${font} ${size} Tf ${x} ${y} Td (${esc(txt)}) Tj ET`);
    };
    const line = (x1, y1, x2, y2, w = 1) => {
      ops.push(`${w} w ${x1} ${y1} m ${x2} ${y2} l S`);
    };
    const rect = (x, y, w, h, lw = 1) => {
      ops.push(`${lw} w ${x} ${y} ${w} ${h} re S`);
    };
    const arrow = (x1, y1, x2, y2) => {
      line(x1, y1, x2, y2, 1);
      const dx = x2 - x1;
      const dy = y2 - y1;
      const len = Math.sqrt(dx * dx + dy * dy) || 1;
      const ux = dx / len;
      const uy = dy / len;
      const ax = x2 - ux * 10;
      const ay = y2 - uy * 10;
      const px = -uy;
      const py = ux;
      line(x2, y2, ax + px * 4, ay + py * 4, 1);
      line(x2, y2, ax - px * 4, ay - py * 4, 1);
    };
    const box = (x, y, w, h, title, body) => {
      rect(x, y, w, h, 1);
      drawText(title, x + 8, y + h - 18, 11, 'F2');
      const lines = wrap(body, Math.max(18, Math.floor(w / 5.5)));
      let ty = y + h - 34;
      for (const l of lines) {
        drawText(l, x + 8, ty, 9.5, 'F1');
        ty -= 12;
      }
    };

    if (page.kind === 'cover') {
      drawText(page.title, 160, 770, 18, 'F2');
      drawText(page.subtitle, 170, 748, 12, 'F3');
      rect(70, 560, 455, 120, 1);
      drawText('Solicitante: Antoni Nuñez Romeu', 90, 640, 11, 'F1');
      drawText('DNI/NIF: 45858029P', 90, 622, 11, 'F1');
      drawText('Domicilio: C/ Font Vella 12, 1, Terrassa, Barcelona, 08221', 90, 604, 11, 'F1');
      drawText('Documentos incluidos: instancia, memoria, reivindicaciones, resumen, dibujos, tasa reducida', 90, 586, 10, 'F1');
      drawText('Expediente preparado para presentacion ante OEPM', 145, 500, 10, 'F3');
      drawText('Pagina 1', 470, 24, 9, 'F1');
      return ops.join('\n');
    }

    if (page.kind === 'instance') {
      drawText('INSTANCIA DE SOLICITUD', 175, 780, 16, 'F2');
      drawText('Oficina Espanola de Patentes y Marcas (OEPM)', 140, 760, 11, 'F1');
      line(48, 748, 547, 748, 0.8);
      drawText('Datos del solicitante', 48, 725, 12, 'F2');
      drawText('Nombre: Antoni Nuñez Romeu', 56, 705, 11, 'F1');
      drawText('DNI/NIF: 45858029P', 56, 688, 11, 'F1');
      drawText('Domicilio: C/ Font Vella 12, 1, Terrassa, Barcelona, 08221', 56, 671, 11, 'F1');
      drawText('Tipo de presentacion: Patente nacional', 56, 654, 11, 'F1');
      drawText('Titulo: Sistema y procedimiento implementados por ordenador para la identificacion de necesidades terapeuticas mediante escaneo de tarjeta sanitaria individual, contraste con stock farmacutico geolocalizado y generacion de acciones de suministro.', 56, 628, 10.3, 'F1');
      drawText('Documentacion anexa', 48, 590, 12, 'F2');
      drawText('1. Memoria descriptiva', 60, 570, 10.8, 'F1');
      drawText('2. Reivindicaciones', 60, 554, 10.8, 'F1');
      drawText('3. Resumen', 60, 538, 10.8, 'F1');
      drawText('4. Dibujos / laminas tecnicas', 60, 522, 10.8, 'F1');
      drawText('5. Solicitud de reduccion de tasas (persona fisica)', 60, 506, 10.8, 'F1');
      drawText('Declaracion: el solicitante afirma ser el inventor y unico titular de la solicitud presentada.', 48, 470, 10.5, 'F1');
      drawText('Firma: Antoni Nuñez Romeu', 48, 442, 11, 'F1');
      drawText('Fecha: 22 de junio de 2026', 48, 424, 11, 'F1');
      drawText('Pagina 2', 470, 24, 9, 'F1');
      return ops.join('\n');
    }

    if (page.kind === 'diagram1') {
      drawText('Figura 1. Arquitectura general del sistema', 160, 790, 14, 'F2');
      box(50, 620, 120, 70, '1 Usuario', 'Inicia busqueda y notificaciones');
      box(220, 620, 120, 70, '2 Escaneo TSI', 'Captura de tarjeta y validacion');
      box(390, 620, 120, 70, '3 Perfil', 'Autenticacion y ubicacion');
      box(105, 470, 120, 70, '4 Stock', 'Farmacias y medicamentos');
      box(275, 470, 120, 70, '5 Motor', 'Contraste, ordenacion y reglas');
      box(445, 470, 90, 70, '6 Accion', 'Reserva / aviso / pedido');
      arrow(170, 655, 220, 655);
      arrow(340, 655, 390, 655);
      arrow(280, 620, 165, 540);
      arrow(340, 620, 335, 540);
      arrow(445, 655, 490, 540);
      arrow(225, 470, 275, 505);
      arrow(395, 470, 445, 505);
      drawText('Flujo: usuario -> captura -> verificacion -> consulta de stock -> accion', 110, 350, 10.5, 'F1');
      drawText('Pagina 1 de dibujos', 450, 24, 9, 'F1');
      return ops.join('\n');
    }

    if (page.kind === 'diagram2') {
      drawText('Figura 2. Captura y validacion de la TSI', 175, 790, 14, 'F2');
      box(70, 600, 140, 70, '1 Camara / lector', 'Entrada de imagen o codigo');
      box(250, 600, 140, 70, '2 Extraccion', 'OCR / parseo / identificacion');
      box(430, 600, 100, 70, '3 Validacion', 'Usuario autenticado');
      box(160, 430, 160, 70, '4 Vinculo seguro', 'Asociacion a perfil y consentimiento');
      box(360, 430, 160, 70, '5 Resultado', 'Necesidad terapeutica o referencia');
      arrow(210, 635, 250, 635);
      arrow(390, 635, 430, 635);
      arrow(480, 600, 240, 500);
      arrow(320, 600, 440, 500);
      drawText('Pagina 2 de dibujos', 450, 24, 9, 'F1');
      return ops.join('\n');
    }

    if (page.kind === 'diagram3') {
      drawText('Figura 3. Contraste con stock farmaceutico', 160, 790, 14, 'F2');
      box(50, 620, 130, 70, '1 Medicamento', 'Referencia obtenida del sistema');
      box(220, 620, 130, 70, '2 Geolocalizacion', 'Distancia y prioridad');
      box(390, 620, 130, 70, '3 Inventario', 'Stock, horario y precio');
      box(135, 460, 140, 70, '4 Motor de ranking', 'Ordena por stock y proximidad');
      box(330, 460, 140, 70, '5 Resultado', 'Lista de farmacias priorizada');
      arrow(180, 655, 220, 655);
      arrow(350, 655, 390, 655);
      arrow(285, 620, 205, 530);
      arrow(455, 620, 400, 530);
      drawText('Pagina 3 de dibujos', 450, 24, 9, 'F1');
      return ops.join('\n');
    }

    if (page.kind === 'diagram4') {
      drawText('Figura 4. Flujo cuando no hay stock', 185, 790, 14, 'F2');
      box(60, 620, 120, 70, '1 Sin stock', 'No existe disponibilidad inmediata');
      box(230, 620, 120, 70, '2 Alerta', 'Aviso a farmacia o usuario');
      box(400, 620, 120, 70, '3 Reserva', 'Lista de espera o reserva');
      box(145, 450, 120, 70, '4 Pedido', 'Solicitud a proveedor o distribucion');
      box(325, 450, 120, 70, '5 Alternativa', 'Otra farmacia con stock');
      arrow(180, 655, 230, 655);
      arrow(350, 655, 400, 655);
      arrow(290, 620, 205, 520);
      arrow(460, 620, 385, 520);
      drawText('Pagina 4 de dibujos', 450, 24, 9, 'F1');
      return ops.join('\n');
    }

    return ops.join('\n');
  }

  const pageContents = pages.map((p) => pageOps(p));
  for (const content of pageContents) {
    contentNums.push(add(`<< /Length ${Buffer.byteLength(content, 'latin1')} >>\nstream\n${content}\nendstream`));
  }
  const pagesTree = add('');
  for (let i = 0; i < contentNums.length; i++) {
    pageNums.push(add(`<< /Type /Page /Parent ${pagesTree} 0 R /MediaBox [0 0 ${PAGE_W} ${PAGE_H}] /Resources << /Font << /F1 ${f1} 0 R /F2 ${f2} 0 R /F3 ${f3} 0 R >> >> /Contents ${contentNums[i]} 0 R >>`));
  }
  objects[pagesTree] = `<< /Type /Pages /Kids [${pageNums.map(n => `${n} 0 R`).join(' ')}] /Count ${pageNums.length} >>`;
  const catalog = add(`<< /Type /Catalog /Pages ${pagesTree} 0 R >>`);

  let pdf = '%PDF-1.4\n';
  const offsets = [0];
  for (let i = 1; i < objects.length; i++) {
    offsets[i] = Buffer.byteLength(pdf, 'latin1');
    pdf += `${i} 0 obj\n${objects[i]}\nendobj\n`;
  }
  const xref = Buffer.byteLength(pdf, 'latin1');
  pdf += `xref\n0 ${objects.length}\n`;
  pdf += '0000000000 65535 f \n';
  for (let i = 1; i < objects.length; i++) pdf += `${String(offsets[i]).padStart(10, '0')} 00000 n \n`;
  pdf += `trailer << /Size ${objects.length} /Root ${catalog} 0 R >>\nstartxref\n${xref}\n%%EOF\n`;
  fs.writeFileSync(outPath, Buffer.from(pdf, 'latin1'));
}

// Generate Drawings and Instance PDF
for (const doc of packageDocs) {
  makePdf(doc);
  console.log(`Wrote ${doc.outPath}`);
}

// Zip final package and source archive
try {
  console.log('Packaging all generated PDFs into a ZIP archive...');
  // Force removal of existing zip first if any to avoid duplication issues
  if (fs.existsSync('oepm_patent_package_pdf.zip')) fs.unlinkSync('oepm_patent_package_pdf.zip');
  execSync('zip -j oepm_patent_package_pdf.zip SOLICITUD_PATENTE_OEPM_FARMAFINDER.pdf PRECONVERSION_OEPM_FARMAFINDER.pdf REDUCCION_TASAS_OEPM_PERSONA_FISICA.pdf SOLICITUD_Y_DIBUJOS_OEPM_FARMAFINDER.pdf', { stdio: 'inherit' });
  console.log('Created oepm_patent_package_pdf.zip successfully.');

  console.log('Packaging pre-conversion source files into a ZIP archive...');
  if (fs.existsSync('oepm_preconversion_archive.zip')) fs.unlinkSync('oepm_preconversion_archive.zip');
  execSync('zip -r oepm_preconversion_archive.zip SOLICITUD_PATENTE_OEPM_FARMAFINDER.html SOLICITUD_PATENTE_OEPM_FARMAFINDER.md MEMORIA_TECNICA.md PLAN.md dibujos/', { stdio: 'inherit' });
  console.log('Created oepm_preconversion_archive.zip successfully.');
} catch (err) {
  console.error('Error creating zip archives:', err.message);
}
