/**
 * pdfService.js — Generación de PDFs de ejercicios.
 *
 * ORIGEN v1: creatorport4x4() + creatorport4x3() en pdfcreator.js (726 + 722 líneas).
 * PROBLEMAS resueltos:
 *   - 90% de código idéntico entre las dos funciones → unificado con parámetro `rows`
 *   - totalUrl y qrCode eran globals implícitas → ahora locales a esta función
 *   - loadScriptapp duplicada → _ensureJsPDF() con carga idempotente
 *   - Las divergencias reales entre 4x4 y 4x3 (rect extra, fase labels) quedan parametrizadas
 *   - fetchImageAsBase64 y leerYAbrirURL2 importadas desde mediaService
 *   - logEventPdf importada desde logService
 */

import { SERVER_URL, PATHS, PWA, PDF_LAYOUT, PDF_TEXTS, ICONS } from '../config.js';
import { session, exerciseStore } from '../data/store.js';
import { fetchImageAsBase64, fetchExternalVideoUrl } from './mediaService.js';
import { generateQR, buildPatientURL, buildPdfFilename } from './qrService.js';
import { logPdfEvent } from './logService.js';

// ─── Carga jsPDF una sola vez ─────────────────────────────────────────────────
let _jsPdfReady = false;
async function _ensureJsPDF() {
  if (_jsPdfReady || window.jspdf) { _jsPdfReady = true; return; }
  await new Promise((resolve, reject) => {
    const s = document.createElement('script');
    s.src = `${SERVER_URL}/js/jspdf.umd.min.js`;
    s.onload  = () => { _jsPdfReady = true; resolve(); };
    s.onerror = () => reject(new Error('No se pudo cargar jspdf.umd.min.js'));
    document.head.appendChild(s);
  });
}

// ─── Helper: dibuja la cabecera de una página PDF ────────────────────────────
function _drawPageHeader(doc, { logo, qrEl, qrUrl, titulo, cellIniW, cellW, cellH,
                                 cat1, cast1, clicar, rows, faseLabels, pageIdx }) {
  const { cellMax } = PDF_LAYOUT;

  doc.addImage(logo, 'PNG', cellIniW + 2, 10, 36, 18, undefined, 'FAST');
  doc.link(cellIniW - 10, 10, 75, 18, { url: '' });

  doc.addImage(qrEl, 'PNG', cellIniW + cellW * 3.75 - 20, 10, 31, 31, undefined, 'FAST');
  doc.link(cellIniW + cellW * 3.75 - 20, 10, 31, 31, { url: qrUrl });

  doc.setFontSize(14);
  doc.text(cellIniW + cellW + 5, 21, titulo);

  doc.setFontSize(10);
  doc.text(cellIniW + 3, 33, cat1);
  doc.text(cellIniW + 3, 38, cast1);
}

// ─── Helper: dibuja la cuadrícula vacía (fondo gris + texto de fase) ─────────
function _drawGrid(doc, { rows, cellIniW, cellIniH, cellW, cellH, clicar, faseLabels }) {
  const cols = PDF_LAYOUT.cols;
  doc.setFontSize(8);
  let npc = 0, npf = 0, nplus = 0;
  const total = rows * cols;

  for (let i = 0; i < total; i++) {
    nplus = (rows === 3) ? (npf + 1) * 8 : 0;
    const ncode = npf * 8 + nplus;

    // Instrucción general en la primera celda de cada página
    if (npf === 0 && npc === 0) {
      doc.text(cellIniW + 3, cellIniH + cellH * npf + ncode + 5 - 16, clicar);
      if (rows === 3) {
        nplus = 8;
        doc.setFontSize(12);
        doc.text(cellIniW + 3, cellIniH + cellH * npf + ncode + 5 - 8, faseLabels?.[0] ?? ' ');
        doc.rect(cellIniW, cellIniH + cellH * npf + ncode - 8, cellW * cols, 8);
        doc.setFontSize(8);
      }
    }

    // Cabecera de fila en modo 3 filas (labels de fase)
    if (rows === 3 && npc === 0 && npf > 0) {
      const nc2 = npf * 8 + (npf + 1) * 8;
      nplus = (npf + 1) * 8;
      doc.setFontSize(12);
      doc.text(cellIniW + 3, cellIniH + cellH * npf + nc2 + 5 - 8, faseLabels?.[npf] ?? ' ');
      doc.rect(cellIniW, cellIniH + cellH * npf + nc2 - 8, cellW * cols, 8);
      doc.setFontSize(8);
    }

    const nc = npf * 8 + nplus;
    doc.setFillColor(235, 235, 235);
    doc.rect(cellIniW + cellW * npc, cellIniH + cellH * npf + nc, cellW, cellH, 'F');
    doc.rect(cellIniW + cellW * npc, cellIniH + cellH * npf + nc - 8, cellW, 8);
    doc.setFillColor(255, 255, 255);
    doc.setDrawColor(155);
    doc.rect(cellIniW + cellW * npc, cellIniH + cellH * npf + nc, cellW, cellH);

    npc++;
    if (npc >= cols) { npf++; npc = 0; }
    if (npf >= rows)  { npf = 0; }
  }
}

// ─── Helper: dibuja el pie de página ─────────────────────────────────────────
function _drawFooter(doc, { upload, cellIniW, cellW, cellH, year, upload_extra_rect }) {
  const { cellMax } = PDF_LAYOUT;
  const lic1 = PDF_TEXTS.llicenciaCat(year);
  const lic2 = PDF_TEXTS.llicenciaEsp(year);

  doc.setFontSize(7);
  doc.text(cellIniW + 4, 270, lic1);
  doc.text(cellIniW + 4, 275, lic2);

  doc.setDrawColor(155);
  doc.setFillColor(255, 255, 255);

  if (upload_extra_rect) {
    doc.rect(cellIniW, 263 - 8, cellIniW + cellW * 3 + 23, 8, 'FD');
  }

  doc.setFontSize(7);
  const openQr   = upload ? PDF_TEXTS.openQrPdf : PDF_TEXTS.openQrSefir;
  const iconSrc  = upload ? ICONS.iconPdf : ICONS.iconSefir;
  const pieIcon  = new Image();
  pieIcon.src    = iconSrc;
  doc.addImage(pieIcon, 'PNG', cellIniW + cellW * 4 - 9, 263 - 7.5, 7, 7, undefined, 'FAST');
  doc.text(cellIniW + 4, 260, openQr);
}

// ─── FUNCIÓN PRINCIPAL ────────────────────────────────────────────────────────
/**
 * Genera un PDF de ejercicios seleccionados.
 *
 * @param {object} opts
 * @param {number}   opts.rows        — 3 o 4 filas (4x3 o 4x4)
 * @param {boolean}  opts.upload      — true = subir al servidor + QR apunta al PDF; false = QR apunta a PWA
 * @param {boolean}  opts.useRehab    — true = modo lapp/rhb; false = modo ias
 * @param {string}   opts.codigoPdf   — prefijo del nombre del PDF
 * @param {string[]} opts.faseLabels  — solo para rows=3: array de 3 strings (etiquetas de fase)
 * @param {number[]} opts.selectedIdx — índices seleccionados del exerciseStore
 */
export async function createPdf({ rows = 4, upload = false, useRehab = false,
                                   codigoPdf = '', faseLabels = [], selectedIdx = [] }) {

  // ── 1. Leer campos del formulario ────────────────────────────────────────
  const tituloRaw   = (document.getElementById('idTitulo')?.value ?? '').slice(0, 40).toUpperCase();
  const username    = session.getUsername();

  const { qrTitulo, qrRegistro, nameSave } = buildPdfFilename(codigoPdf, tituloRaw);
  const patientURL  = buildPatientURL({ username, qrTitulo, qrRegistro,
                                         totalMp4Lite: _buildMp4Lite(selectedIdx),
                                         useRehab });
  const uploadURL   = `${PATHS.pdfs}${nameSave}`;
  const qrValue     = upload ? uploadURL : patientURL;

  // ── 2. Inicializar jsPDF ──────────────────────────────────────────────────
  await _ensureJsPDF();
  const doc = new window.jspdf.jsPDF({
    orientation: 'portrait', unit: 'mm', format: 'a4',
    putOnlyUsedFonts: true, compress: true,
  });

  const { cellMax, cellIniW, cellIniH, cols } = PDF_LAYOUT;
  const cellW = cellMax, cellH = cellMax;
  const maxPerPage = PDF_LAYOUT.pageMax[rows];
  const year = new Date().getFullYear();

  // ── 3. Generar QR ────────────────────────────────────────────────────────
  const qrEl = await generateQR(qrValue);

  // ── 4. Assets fijos ──────────────────────────────────────────────────────
  const logo = new Image(); logo.src = ICONS.logo;

  // ── 5. Acumuladores locales (antes eran globals) ─────────────────────────
  const totalUrl     = [];
  let   totalMp4     = '';
  let   totalMp4Lite = '';
  let   npk = 0, npc = 0, npf = 0;
  const arrImages    = [...selectedIdx];

  // ── 6. Construir totalMp4 / totalMp4Lite ────────────────────────────────
  for (const ipos of arrImages) {
    const ex = exerciseStore.getAt(ipos);
    if (!ex) continue;
    totalMp4     += ',' + ex.titulo;
    totalMp4Lite += ',' + ex.ordenOri;
  }

  // ── 7. Primera página ────────────────────────────────────────────────────
  doc.setLineWidth(0);
  doc.setFontSize(10);
  doc.setDrawColor(155);

  _drawPageHeader(doc, { logo, qrEl, qrUrl: qrValue, titulo: tituloRaw,
                          cellIniW, cellW, cellH,
                          cat1: PDF_TEXTS.instruccioCat, cast1: PDF_TEXTS.instruccioEsp,
                          clicar: PDF_TEXTS.clicar, rows, faseLabels });

  _drawGrid(doc, { rows, cellIniW, cellIniH, cellW, cellH,
                    clicar: PDF_TEXTS.clicar, faseLabels });

  _drawFooter(doc, { upload, cellIniW, cellW, cellH, year, upload_extra_rect: false });

  doc.setFontSize(7);
  doc.text(cellIniW + 4, 280, `${new Date()} - PEFiR. All rights reserved.`);
  doc.text('Page ' + doc.internal.getCurrentPageInfo().pageNumber,
           cellIniW + cellW * 4 - 4, 280, null, null, 'right');

  // ── 8. Insertar imágenes ──────────────────────────────────────────────────
  for (let ii = 0; ii < arrImages.length; ii++) {
    const ipos = arrImages[ii];
    const ex   = exerciseStore.getAt(ipos);
    if (!ex) continue;

    // Nueva página cuando se supera maxPerPage
    if (npk > 0 && npk % maxPerPage === 0) {
      npc = 0; npf = 0;
      doc.addPage();
      _drawPageHeader(doc, { logo, qrEl, qrUrl: qrValue, titulo: tituloRaw,
                              cellIniW, cellW, cellH,
                              cat1: PDF_TEXTS.instruccioCat, cast1: PDF_TEXTS.instruccioEsp,
                              clicar: PDF_TEXTS.clicar, rows,
                              faseLabels: rows === 3 ? faseLabels.slice(3) : faseLabels });
      _drawGrid(doc, { rows, cellIniW, cellIniH, cellW, cellH,
                        clicar: PDF_TEXTS.clicar,
                        faseLabels: rows === 3 ? faseLabels.slice(3) : faseLabels });
      _drawFooter(doc, { upload, cellIniW, cellW, cellH, year, upload_extra_rect: true });
      doc.setFontSize(7);
      doc.text(cellIniW + 4, 280, String(new Date()));
      doc.text('Page ' + doc.internal.getCurrentPageInfo().pageNumber,
               cellIniW + cellW * 4 - 4, 280, null, null, 'right');
      npc = 0; npf = 0;
    }

    const nplus = rows === 3 ? (npf + 1) * 8 : 0;
    const ncode = npf * 8 + nplus;

    const base64 = await fetchImageAsBase64(ex.titulo);
    if (!base64) { npk++; npc++; if (npc >= cols) { npf++; npc = 0; } continue; }

    const imgProps = doc.getImageProperties(base64);
    let imgW, imgH, rectXp, rectYp;

    rectXp = cellIniW + cellW * npc;
    rectYp = cellIniH + cellH * npf + ncode;

    if (imgProps.width > imgProps.height) {
      imgW = cellMax - 2; imgH = Math.floor(imgProps.height * imgW / imgProps.width);
      rectYp += Math.floor((cellMax - imgH) / 2); rectXp += 1;
    } else {
      imgH = cellMax - 2; imgW = Math.floor(imgProps.width * imgH / imgProps.height);
      rectXp += Math.floor((cellMax - imgW) / 2); rectYp += 1;
    }

    doc.addImage(base64, 'JPEG', rectXp, rectYp, imgW, imgH, ipos.toString(), undefined, 'FAST');

    // Link en la imagen
    const isExternalTxt = ex.videomp4.endsWith('.txt');
    if (isExternalTxt) {
      const extUrl = await fetchExternalVideoUrl(ex.videomp4);
      if (extUrl) {
        const numfile = ex.videomp4.slice(-11, -8);
        let finalUrl = extUrl;
        if (numfile[0] === '8' && numfile[1] === '9' && numfile[2] === '9') {
          finalUrl = extUrl + '?' + qrTitulo + '_' + qrRegistro;
        } else if (numfile[0] === '8' && numfile[1] === '8' && numfile[2] === '9') {
          finalUrl = `${SERVER_URL}/viewpdf.html#${extUrl}`;
        }
        doc.link(rectXp, rectYp, imgW, imgH, { url: finalUrl });
        totalUrl.push(finalUrl);
      }
    } else {
      doc.link(rectXp, rectYp, imgW, imgH, { url: ex.videomp4 });
      totalUrl.push(ex.videomp4);
    }

    // Marca de agua
    const agua = new Image(); agua.src = ICONS.watermark;
    doc.addImage(agua, 'PNG', rectXp + imgW - cellMax / 4 - 1, rectYp + imgH - 2,
                 cellMax / 4, 1, undefined, 'FAST');

    // Texto/enlace del título bajo la imagen
    let label = ex.titulo.toUpperCase().slice(8, -4).replace(/_+/g, ' ').slice(0, 25);
    const textY = cellIniH + cellH * npf + ncode - 3.5;

    if (!useRehab) {
      doc.textWithLink(label, cellIniW + cellW * npc + 2, textY, { url: ex.videomp4 });
    } else {
      doc.textWithLink(label, cellIniW + cellW * npc + 2, textY, { url: '' });
    }

    npk++; npc++;
    if (npc >= cols) { npf++; npc = 0; }
    if (npf >= rows)  { npf = 0; }
  }

  // ── 9. Página final (instrucciones QR) ──────────────────────────────────
  doc.addPage();
  doc.addImage(logo, 'PNG', cellIniW + 2, 10, 36, 18, undefined, 'FAST');
  doc.link(cellIniW - 10, 10, 75, 18, { url: '' });
  doc.setFontSize(13); doc.setTextColor(40, 40, 40);
  doc.text(`${qrTitulo}_${qrRegistro}`, cellIniW + 42, 18);
  doc.setFontSize(8);
  doc.text(new Date().toLocaleDateString('ca-ES'), cellIniW + 42, 24);

  // QR de la página final apunta a newpdf.html
  const newpdfBase = useRehab ? PWA.newpdfRhb : PWA.newpdfIas;
  const newpdfUrl  = `${newpdfBase}?${username}#${qrTitulo}_${qrRegistro}${totalMp4Lite}`;
  if (!upload) await generateQR(newpdfUrl);
  const newQrEl = document.getElementById('qr_code');

  const _qs = 40, _pw = 210, _qx = (_pw - _qs) / 2, _qy = 60;
  doc.addImage(newQrEl, 'PNG', _qx, _qy, _qs, _qs, undefined, 'FAST');
  doc.link(_qx, _qy, _qs, _qs, { url: newpdfUrl });

  doc.setFontSize(10); doc.setTextColor(40, 40, 40);
  const _ty = _qy + _qs + 14;
  [
    "Aquest QR s'ofereix per compatibilitat amb els diferents navegadors.",
    "Us permet recrear el pdf al vostre sistema en lloc d'obrir l'aplicació SEFiR.",
    "Escanegeu el QR superior d'aquesta pàgina i obriu el pdf.",
    "",
    "Este QR se ofrece por compatibilidad con los diferentes navegadores.",
    "Le permite recrear el pdf en su sistema en lugar de abrir la aplicación SEFiR.",
    "Escanear el QR superior de esta página y abrir el pdf.",
  ].forEach((l, i) => doc.text(l, _pw / 2, _ty + i * 7, { align: 'center' }));

  doc.setFontSize(7);
  const year4 = new Date().getFullYear();
  doc.text(cellIniW + 4, 270, PDF_TEXTS.llicenciaCat(year4));
  doc.text(cellIniW + 4, 275, PDF_TEXTS.llicenciaEsp(year4));
  doc.text(cellIniW + 4, 280, `${new Date()} - PEFiR. All rights reserved.`);
  doc.text('Page ' + doc.internal.getCurrentPageInfo().pageNumber,
           cellIniW + cellW * 4 - 4, 280, null, null, 'right');

  // ── 10. Metadatos del documento ──────────────────────────────────────────
  doc.setProperties({
    title: nameSave,
    subject: 'exercicis',
    author: `CST. Servei de fisioteràpia: ${username}`,
    keywords: totalUrl.join(','),
    creator: 'Software info. (abeciabuil@gmail.com)',
  });

  // ── 11. Guardar / subir ──────────────────────────────────────────────────
  const pdfName = `${qrTitulo}_${qrRegistro}`;

  if (!confirm('El archivo esta preparado, puede crearlo!.')) {
    alert('Operación cancelada.'); return;
  }

  if (navigator.onLine) {
    await logPdfEvent({ pdfName, qrUrl: patientURL, imageList: totalMp4 });
  }

  if (upload) {
    await doc.save(`${pdfName}.pdf`);
    const pdfBlob  = await doc.output('blob');
    const formData = new FormData();
    formData.append('file', pdfBlob, `${pdfName}.pdf`);
    try {
      const res = await fetch(`${PATHS.uploadPdf}?t=${Date.now()}`, { method: 'POST', body: formData });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const text = await res.text();
      const statusEl = document.getElementById('status');
      if (statusEl) { statusEl.innerText = text; }
      if (typeof obtenerPdfs === 'function') await obtenerPdfs();
    } catch (err) {
      console.error('[pdfService] upload error:', err);
      const statusEl = document.getElementById('status');
      if (statusEl) statusEl.innerText = err.message;
    }
  } else {
    await doc.save(`${pdfName}.pdf`);
  }
}

// ─── Helper interno ───────────────────────────────────────────────────────────
function _buildMp4Lite(selectedIdx) {
  return selectedIdx.reduce((acc, ipos) => {
    const ex = exerciseStore.getAt(ipos);
    return ex ? acc + ',' + ex.ordenOri : acc;
  }, '');
}
