"""Tests para vault_pdf_extract."""

from __future__ import annotations

import os
import sqlite3
import sys
from pathlib import Path

import pytest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from vault_pdf_extract import vault_pdf_extract


def _make_vault(tmp: Path) -> tuple[Path, Path]:
    """Crea un vault mínimo con vault_index.db."""
    db = tmp / "vault_index.db"
    conn = sqlite3.connect(str(db))
    conn.executescript(
        """
        CREATE TABLE IF NOT EXISTS files (
            rowid INTEGER PRIMARY KEY AUTOINCREMENT,
            rel_path TEXT UNIQUE NOT NULL,
            size_bytes INTEGER,
            ext TEXT
        );
        CREATE VIRTUAL TABLE IF NOT EXISTS files_fts
            USING fts5(rel_path, content_text, content='', contentless_delete=1);
        CREATE TABLE IF NOT EXISTS pdf_extracts (
            rel_path TEXT PRIMARY KEY,
            page_count INTEGER,
            text_len INTEGER,
            extracted_to TEXT,
            extracted_at INTEGER
        );
        """
    )
    conn.commit()
    conn.close()
    return tmp, db


def _insert_file_entry(db: Path, rel_path: str):
    conn = sqlite3.connect(str(db))
    conn.execute(
        "INSERT OR IGNORE INTO files(rel_path, size_bytes, ext) VALUES (?, 0, '.pdf')",
        (rel_path,),
    )
    conn.commit()
    conn.close()


def _make_pdf(path: Path, text: str = "Hello vault PDF.\nPage two content."):
    """Crea un PDF mínimo con fitz para tests."""
    import fitz

    doc = fitz.open()
    page = doc.new_page()
    page.insert_text((72, 72), text)
    doc.save(str(path))
    doc.close()


def test_pdf_extract_basic(tmp_path):
    vault, db = _make_vault(tmp_path)
    rel = "docs/test.pdf"
    pdf = vault / rel
    pdf.parent.mkdir(parents=True, exist_ok=True)
    _make_pdf(pdf)
    _insert_file_entry(db, rel)

    result = vault_pdf_extract(str(vault), rel, db_path=str(db))

    assert result["rel_path"] == rel
    assert result["page_count"] >= 1
    assert result["text_len"] > 0
    assert result["persisted"] is True

    conn = sqlite3.connect(str(db))
    row = conn.execute("SELECT page_count, text_len FROM pdf_extracts WHERE rel_path=?", (rel,)).fetchone()
    conn.close()
    assert row is not None
    assert row[0] >= 1
    assert row[1] > 0


def test_pdf_dump_text_creates_file(tmp_path):
    vault, db = _make_vault(tmp_path)
    rel = "docs/dump.pdf"
    pdf = vault / rel
    pdf.parent.mkdir(parents=True, exist_ok=True)
    _make_pdf(pdf, "Contenido para dump a disco.")
    _insert_file_entry(db, rel)
    # Crear data/processed/ para que se use ese directorio
    (vault / "data" / "processed").mkdir(parents=True, exist_ok=True)

    result = vault_pdf_extract(str(vault), rel, db_path=str(db), dump_text=True)

    assert result["extracted_to"] is not None
    txt_path = vault / result["extracted_to"]
    assert txt_path.exists()
    assert txt_path.stat().st_size > 0


def test_pdf_no_dump(tmp_path):
    vault, db = _make_vault(tmp_path)
    rel = "docs/nodump.pdf"
    pdf = vault / rel
    pdf.parent.mkdir(parents=True, exist_ok=True)
    _make_pdf(pdf, "No se debe volcar a disco.")
    _insert_file_entry(db, rel)

    result = vault_pdf_extract(str(vault), rel, db_path=str(db), dump_text=False)

    assert result["extracted_to"] is None


def test_pdf_persists_to_fts(tmp_path):
    vault, db = _make_vault(tmp_path)
    rel = "docs/fts.pdf"
    pdf = vault / rel
    pdf.parent.mkdir(parents=True, exist_ok=True)
    _make_pdf(pdf, "Texto especial para FTS xyzpdftest.")
    _insert_file_entry(db, rel)

    vault_pdf_extract(str(vault), rel, db_path=str(db), dump_text=False)

    conn = sqlite3.connect(str(db))
    # FTS5 contentless: no permite SELECT directo, usar MATCH
    row = conn.execute(
        "SELECT rowid FROM files_fts WHERE files_fts MATCH 'xyzpdftest'",
    ).fetchone()
    conn.close()
    assert row is not None, "FTS no encontró el texto del PDF"


def test_pdf_corrupt_errors(tmp_path):
    vault, db = _make_vault(tmp_path)
    rel = "docs/corrupt.pdf"
    pdf = vault / rel
    pdf.parent.mkdir(parents=True, exist_ok=True)
    pdf.write_bytes(b"%PDF-1.4 garbage bytes \x00\x01\x02 not a real pdf")
    _insert_file_entry(db, rel)

    with pytest.raises(RuntimeError, match="corrupto|inválido|PDF"):
        vault_pdf_extract(str(vault), rel, db_path=str(db))
