"""Resuelve el path absoluto real de un attachment embebido en un vault Obsidian.

Funcion impura: recorre el filesystem del vault. Obsidian resuelve los embeds
![[...]] por nombre de archivo unico (no por path), asi que esta funcion busca
recursivamente un archivo cuyo basename coincida con el nombre del embed.
"""

import os

# Directorios de maquinaria de Obsidian que nunca contienen attachments de usuario.
_EXCLUDED_DIRS = {".obsidian", ".trash"}


def resolve_obsidian_embed(vault_dir: str, embed_name: str) -> str:
    """Resuelve el path absoluto de un attachment embebido buscandolo por nombre.

    Obsidian resuelve los embeds `![[archivo.jpg]]` por nombre de archivo unico
    dentro del vault, no por ruta. Esta funcion replica ese comportamiento:
    recorre ``vault_dir`` recursivamente (una sola pasada con ``os.walk``) y
    devuelve el primer archivo cuyo basename coincida, de forma
    case-insensitive, con ``embed_name``.

    Si ``embed_name`` no trae extension (p.ej. ``"foto"``), se acepta cualquier
    archivo cuyo basename sin extension coincida (p.ej. ``foto.jpg``).

    Los directorios ``.obsidian/`` y ``.trash/`` se excluyen del recorrido.

    Impura: lee el filesystem. NO lanza si el embed no se encuentra (devuelve
    cadena vacia). SI lanza si ``vault_dir`` no existe.

    Args:
        vault_dir: Ruta a la raiz del vault Obsidian.
        embed_name: Nombre del attachment embebido (lo que devuelve
            ``extract_obsidian_embeds``), con o sin extension.

    Returns:
        El path absoluto del primer archivo que coincide, o cadena vacia ``""``
        si ningun archivo del vault coincide.

    Raises:
        FileNotFoundError: si ``vault_dir`` no existe.
        NotADirectoryError: si ``vault_dir`` no es un directorio.
    """
    if not os.path.exists(vault_dir):
        raise FileNotFoundError(f"vault path does not exist: {vault_dir}")
    if not os.path.isdir(vault_dir):
        raise NotADirectoryError(f"vault path is not a directory: {vault_dir}")

    target = embed_name.strip()
    if not target:
        return ""

    target_lower = target.lower()
    has_extension = os.path.splitext(target)[1] != ""
    target_stem_lower = os.path.splitext(target_lower)[0]

    for dirpath, dirnames, filenames in os.walk(vault_dir):
        # Podar maquinaria de Obsidian in-place para no descender en ella.
        dirnames[:] = [d for d in dirnames if d not in _EXCLUDED_DIRS]
        for filename in filenames:
            filename_lower = filename.lower()
            if has_extension:
                # Comparar basename completo, case-insensitive.
                if filename_lower == target_lower:
                    return os.path.abspath(os.path.join(dirpath, filename))
            else:
                # Sin extension en el embed: comparar solo el stem del archivo.
                stem_lower = os.path.splitext(filename_lower)[0]
                if stem_lower == target_stem_lower:
                    return os.path.abspath(os.path.join(dirpath, filename))

    return ""


if __name__ == "__main__":
    import tempfile

    with tempfile.TemporaryDirectory() as tmp:
        os.makedirs(os.path.join(tmp, "attachments"))
        os.makedirs(os.path.join(tmp, ".obsidian"))
        with open(os.path.join(tmp, "attachments", "Foto.JPG"), "w") as f:
            f.write("x")
        with open(os.path.join(tmp, "doc.pdf"), "w") as f:
            f.write("y")

        # Match case-insensitive con extension.
        hit = resolve_obsidian_embed(tmp, "foto.jpg")
        assert hit.endswith(os.path.join("attachments", "Foto.JPG")), hit

        # Match sin extension en el embed.
        hit2 = resolve_obsidian_embed(tmp, "doc")
        assert hit2.endswith("doc.pdf"), hit2

        # No existe -> "".
        assert resolve_obsidian_embed(tmp, "no_existe.png") == ""

    print("resolve_obsidian_embed smoke OK")
