"""Actualiza una nota existente de Obsidian (.md) en disco.

Compone funciones puras del grupo obsidian: parse_obsidian_frontmatter para
leer el estado actual y format_obsidian_note para reescribir. Funcion impura:
lee y reescribe un archivo en disco.
"""

import os

from obsidian import format_obsidian_note, parse_obsidian_frontmatter


def update_obsidian_note(
    path: str,
    body: str = None,
    set_frontmatter: dict = None,
    append: str = None,
) -> str:
    """Actualiza una nota Markdown de Obsidian existente.

    Lee la nota actual, aplica las modificaciones pedidas y la reescribe.

    Args:
        path: ruta al archivo .md a actualizar.
        body: si se da (no None), reemplaza por completo el cuerpo de la nota.
        set_frontmatter: si se da, hace merge (update de claves) sobre el
            frontmatter actual. Las claves nuevas se anaden, las existentes se
            sobreescriben. Las no mencionadas se conservan.
        append: si se da, concatena este texto al final del cuerpo (separado
            por un salto de linea). Se aplica DESPUES de un eventual reemplazo
            de body.

    Returns:
        La ruta del archivo actualizado.

    Raises:
        FileNotFoundError: si la nota no existe.
        IsADirectoryError: si la ruta apunta a un directorio.
        OSError: si la lectura/escritura falla por otro motivo de I/O.
    """
    if not os.path.exists(path):
        raise FileNotFoundError(f"obsidian note not found: {path}")
    if os.path.isdir(path):
        raise IsADirectoryError(f"expected a file, got a directory: {path}")

    with open(path, "r", encoding="utf-8") as f:
        content = f.read()

    parsed = parse_obsidian_frontmatter(content)
    frontmatter = dict(parsed.get("frontmatter", {}) or {})
    current_body = parsed.get("body", "") or ""

    if set_frontmatter:
        frontmatter.update(set_frontmatter)

    new_body = current_body if body is None else body

    if append is not None:
        if new_body and not new_body.endswith("\n"):
            new_body = new_body + "\n" + append
        else:
            new_body = new_body + append

    new_content = format_obsidian_note(frontmatter, new_body)

    with open(path, "w", encoding="utf-8") as f:
        f.write(new_content)

    return path


if __name__ == "__main__":
    import tempfile

    fd, tmp = tempfile.mkstemp(suffix=".md")
    os.close(fd)
    with open(tmp, "w", encoding="utf-8") as f:
        f.write("---\ntitle: A\n---\n\nLinea original.")
    update_obsidian_note(tmp, set_frontmatter={"status": "wip"}, append="Linea nueva.")
    with open(tmp, "r", encoding="utf-8") as f:
        out = f.read()
    assert "status" in out, out
    assert "Linea nueva." in out, out
    assert "Linea original." in out, out
    os.remove(tmp)
    print("update_obsidian_note smoke OK")
