"""Convert DOCX bytes to PDF using headless LibreOffice (layout matches Word export)."""

from __future__ import annotations

import os
import shutil
import subprocess
import tempfile
from pathlib import Path

from src.be01.docx_normalize import (
    relax_justified_softbreak_paragraphs_in_docx,
    strip_table_row_height_rules_from_docx,
)


def resolve_libreoffice_soffice() -> str:
    """Return path to `soffice`/`libreoffice` binary."""
    env = (os.environ.get("LIBREOFFICE_PATH") or "").strip()
    if env:
        p = Path(env)
        if p.is_file():
            return str(p.resolve())
        w = shutil.which(env)
        if w:
            return w
    for name in ("soffice", "libreoffice"):
        found = shutil.which(name)
        if found:
            return found
    mac = Path("/Applications/LibreOffice.app/Contents/MacOS/soffice")
    if mac.is_file():
        return str(mac)
    raise FileNotFoundError(
        "Không tìm thấy LibreOffice (soffice). Cài đặt libreoffice-writer-nogui hoặc đặt LIBREOFFICE_PATH."
    )


def convert_docx_bytes_to_pdf(
    docx_bytes: bytes,
    *,
    timeout_sec: float = 120.0,
    relax_justified_softbreaks: bool = True,
    strip_table_row_heights: bool = False,
) -> bytes:
    """
    Write DOCX to a temp file, run headless LibreOffice, read resulting PDF.

    Uses the same rendering stack as manual « Save as PDF » in LibreOffice (≈ Word layout).

    ``relax_justified_softbreaks`` defaults to ``True`` to run
    :func:`~src.be01.docx_normalize.relax_justified_softbreak_paragraphs_in_docx`
    (``distribute`` → ``both`` in document/styles/headers, split soft breaks in the body,
    ``doNotExpandShiftReturn`` in settings) so LibreOffice/Word-like renderers avoid absurd
    inter-word gaps while keeping justified paragraphs.
    """
    if not docx_bytes or len(docx_bytes) < 100:
        raise ValueError("DOCX payload quá nhỏ hoặc rỗng.")

    soffice = resolve_libreoffice_soffice()
    if strip_table_row_heights:
        docx_bytes = strip_table_row_height_rules_from_docx(docx_bytes)
    if relax_justified_softbreaks:
        docx_bytes = relax_justified_softbreak_paragraphs_in_docx(docx_bytes)

    with tempfile.TemporaryDirectory(prefix="docx2pdf-") as td:
        td_path = Path(td)
        docx_path = td_path / "document.docx"
        docx_path.write_bytes(docx_bytes)
        home = td_path / ".lo_home"
        home.mkdir(parents=True, exist_ok=True)
        cmd = [
            soffice,
            "--headless",
            "--nologo",
            "--nodefault",
            "--nofirststartwizard",
            "--convert-to",
            "pdf",
            "--outdir",
            str(td_path),
            str(docx_path),
        ]
        env = {**os.environ, "HOME": str(home)}
        proc = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=timeout_sec,
            env=env,
        )
        pdf_path = td_path / "document.pdf"
        if proc.returncode != 0 or not pdf_path.is_file():
            err = (proc.stderr or proc.stdout or "").strip() or f"exit {proc.returncode}"
            raise RuntimeError(f"LibreOffice không chuyển được DOCX sang PDF: {err}")
        return pdf_path.read_bytes()
