"""pdf_add_text — escribe un bloque de texto en el documento PDF."""

import sys
import os

_types_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "python", "types", "infra")
sys.path.insert(0, _types_dir)
from pdf_doc import PDFDoc
from pdf_style import PDFStyle


def _parse_hex_color(hex_color: str) -> tuple[int, int, int]:
    """Convierte color hex (#RRGGBB) a tupla (r, g, b)."""
    h = hex_color.lstrip("#")
    if len(h) == 3:
        h = "".join(c * 2 for c in h)
    r = int(h[0:2], 16)
    g = int(h[2:4], 16)
    b = int(h[4:6], 16)
    return r, g, b


def _align_char(alignment: str) -> str:
    """Convierte nombre de alineacion al caracter fpdf2."""
    mapping = {
        "left": "L",
        "center": "C",
        "right": "R",
        "justify": "J",
    }
    return mapping.get(alignment, "L")


def pdf_add_text(
    doc: PDFDoc,
    text: str,
    style: PDFStyle | None = None,
    x: float | None = None,
    y: float | None = None,
    width: float | None = None,
) -> PDFDoc:
    """Escribe un bloque de texto en el documento PDF con el estilo dado.

    Posiciona el cursor en (x, y) si se especifican, o continua desde
    la posicion actual. Aplica fuente, tamaño, color y alineacion del estilo.
    Respeta saltos de linea en el texto.

    Args:
        doc: PDFDoc con una pagina activa.
        text: texto a escribir. Soporta saltos de linea con '\\n'.
        style: PDFStyle con fuente, tamaño, color, alineacion. None usa defaults.
        x: posicion X en mm. None mantiene la posicion actual (margen izquierdo).
        y: posicion Y en mm. None mantiene la posicion actual (posicion del cursor).
        width: ancho del bloque de texto en mm. None usa el ancho disponible.

    Returns:
        PDFDoc con el texto añadido (mismo objeto modificado).
    """
    if style is None:
        style = PDFStyle()

    fpdf = doc.fpdf

    # Aplicar margen superior
    if style.margin_top > 0:
        fpdf.ln(style.margin_top)

    # Posicion
    if x is not None or y is not None:
        cur_x = x if x is not None else fpdf.get_x()
        cur_y = y if y is not None else fpdf.get_y()
        fpdf.set_xy(cur_x, cur_y)

    # Fuente
    family = style.font_family
    # Detectar bold/italic del nombre
    bold = "-Bold" in family or "-BoldOblique" in family
    italic = "-Oblique" in family or "-BoldOblique" in family
    base_family = family.split("-")[0]
    style_str = ""
    if bold:
        style_str += "B"
    if italic:
        style_str += "I"
    fpdf.set_font(base_family, style=style_str, size=style.font_size)

    # Color
    r, g, b = _parse_hex_color(style.color)
    fpdf.set_text_color(r, g, b)

    # Alineacion
    align = _align_char(style.alignment)

    # Ancho disponible
    cell_width = width if width is not None else (fpdf.epw)

    # Altura de linea
    line_h = style.font_size * style.line_height * 0.352778  # pt a mm aprox

    # Escribir texto con multi_cell para soportar saltos de linea y wrap
    fpdf.multi_cell(w=cell_width, h=line_h, text=text, align=align)

    # Margen inferior
    if style.margin_bottom > 0:
        fpdf.ln(style.margin_bottom)

    return doc
