"""Lee una nota de Obsidian (.md) desde disco y la descompone en sus partes.

Compone funciones puras del grupo obsidian: parse_obsidian_frontmatter y
extract_obsidian_wikilinks. Funcion impura: hace I/O de lectura de archivo.
"""

import os

from obsidian import extract_obsidian_wikilinks, parse_obsidian_frontmatter


def _normalize_tags(raw) -> list:
    """Normaliza el campo tags del frontmatter a una lista de strings.

    Acepta None, un string CSV ("a, b, c") o una lista. Devuelve siempre
    una lista de strings sin espacios sobrantes y sin entradas vacias.
    """
    if raw is None:
        return []
    if isinstance(raw, str):
        return [t.strip() for t in raw.split(",") if t.strip()]
    if isinstance(raw, (list, tuple)):
        return [str(t).strip() for t in raw if str(t).strip()]
    # Cualquier otro tipo (int, etc.) -> representacion como unico tag.
    return [str(raw).strip()] if str(raw).strip() else []


def read_obsidian_note(path: str) -> dict:
    """Lee una nota Markdown de Obsidian y devuelve sus partes estructuradas.

    Args:
        path: ruta al archivo .md a leer.

    Returns:
        dict con las claves:
            - path: la ruta leida (tal cual fue pasada).
            - frontmatter: dict con el frontmatter YAML parseado.
            - body: str con el cuerpo Markdown sin el frontmatter.
            - wikilinks: list con los destinos de los wikilinks [[...]] del body.
            - tags: list normalizada a partir de frontmatter["tags"].

    Raises:
        FileNotFoundError: si el archivo no existe.
        IsADirectoryError: si la ruta apunta a un directorio.
        OSError: si la lectura 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 = parsed.get("frontmatter", {}) or {}
    body = parsed.get("body", "") or ""

    wikilinks = extract_obsidian_wikilinks(body)
    tags = _normalize_tags(frontmatter.get("tags"))

    return {
        "path": path,
        "frontmatter": frontmatter,
        "body": body,
        "wikilinks": wikilinks,
        "tags": tags,
    }


if __name__ == "__main__":
    import tempfile

    sample = "---\ntitle: Demo\ntags: [a, b]\n---\n\nHola [[Otra Nota]] y [[Tercera]].\n"
    fd, tmp = tempfile.mkstemp(suffix=".md")
    os.close(fd)
    with open(tmp, "w", encoding="utf-8") as f:
        f.write(sample)
    note = read_obsidian_note(tmp)
    assert note["frontmatter"].get("title") == "Demo", note["frontmatter"]
    assert note["tags"] == ["a", "b"], note["tags"]
    assert "Otra Nota" in note["wikilinks"], note["wikilinks"]
    os.remove(tmp)
    print("read_obsidian_note smoke OK")
