"""Pipeline: anade UN contacto a la libreta CardDAV de Enmanuel en una llamada.

Compone funciones del registry: genera un UID determinista cuando el caller no
da uno (contact_import_key) para que re-anadir el mismo contacto sobrescriba en
vez de duplicar, serializa el dict de contacto a VCARD 3.0 (build_vcard),
resuelve la contrasena CardDAV desde `pass` (pass_get_secret) y sube el VCARD
via HTTP PUT (carddav_put_vcard). Impuro (red + lectura de `pass`). Solo stdlib.

La contrasena resuelta NUNCA se logea ni se incluye en el dict de retorno.
"""

import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from core.build_vcard import build_vcard
from core.contact_import_key import contact_import_key
from infra.carddav_put_vcard import carddav_put_vcard
from infra.pass_get_secret import pass_get_secret

# Config destino embebida (libreta CardDAV de Enmanuel en Xandikos self-hosted).
DEFAULT_BASE_URL = "https://dav-eedeb681c4ab89ab8e444ac9.organic-machine.com"
DEFAULT_USERNAME = "enmanuel"
DEFAULT_COLLECTION = "/enmanuel/contacts/addressbook/"


def _as_list(value) -> list:
    """Normaliza None / string suelto / lista a lista de strings.

    None -> []; string suelto -> [string]; lista|tupla -> lista. Cualquier otro
    valor escalar se envuelve en una lista de un elemento.
    """
    if value is None:
        return []
    if isinstance(value, str):
        return [value]
    if isinstance(value, (list, tuple)):
        return list(value)
    return [value]


def add_contact_dav(
    name: str,
    *,
    tels=None,
    emails=None,
    adrs=None,
    org: str = "",
    note: str = "",
    uid: str = "",
    base_url: str = DEFAULT_BASE_URL,
    username: str = DEFAULT_USERNAME,
    collection_path: str = DEFAULT_COLLECTION,
    secret_path: str = "dav/xandikos-enmanuel",
    timeout_s: float = 20.0,
    verify_tls: bool = True,
) -> dict:
    """Anade un contacto a la libreta CardDAV en una sola llamada (one-shot).

    Args:
        name: nombre completo del contacto (FN del vCard). Obligatorio.
        tels: telefono(s). Acepta lista, string suelto o None.
        emails: email(s). Acepta lista, string suelto o None.
        adrs: direccion(es). Acepta lista, string suelto o None.
        org: organizacion (ORG). Vacio = se omite.
        note: nota libre (NOTE). Vacio = se omite.
        uid: UID del vCard. Si se deja vacio se calcula con contact_import_key
            (telefono > email > nombre), de modo que re-anadir el mismo contacto
            sobrescribe el recurso en vez de duplicarlo (idempotencia).
        base_url: URL base del servidor DAV. Default = libreta de Enmanuel.
        username: usuario HTTP Basic. Default = enmanuel.
        collection_path: ruta de la coleccion CardDAV destino.
        secret_path: ruta del secreto en `pass` con la contrasena (primera linea).
        timeout_s: timeout del PUT en segundos. Default 20.0.
        verify_tls: si True (default) verifica el certificado TLS.

    Returns:
        dict. En exito reusa el dict de carddav_put_vcard mas el uid usado:
        {status:'ok', http_status:int, url:str, uid:str}. En error (sin lanzar):
        {status:'error', error:str, uid:str, http_status:int|None}. Si la
        contrasena no se encuentra en `pass`, devuelve {status:'error',
        error:..., uid:...} sin tocar la red.
    """
    tels_list = _as_list(tels)
    emails_list = _as_list(emails)
    adrs_list = _as_list(adrs)

    used_uid = uid.strip() if uid else ""
    if not used_uid:
        used_uid = contact_import_key(name, phones=tels_list, emails=emails_list)

    contact = {"uid": used_uid, "fn": name}
    if tels_list:
        contact["tels"] = tels_list
    if emails_list:
        contact["emails"] = emails_list
    if adrs_list:
        contact["adrs"] = adrs_list
    if org:
        contact["org"] = org
    if note:
        contact["note"] = note

    vcard_text = build_vcard(contact)

    secret = pass_get_secret(secret_path)
    if secret.get("status") != "ok":
        return {
            "status": "error",
            "error": "pass: %s" % secret.get("error", "secret not found"),
            "uid": used_uid,
            "http_status": None,
        }
    password = secret["value"]

    result = carddav_put_vcard(
        base_url,
        username,
        password,
        collection_path,
        used_uid,
        vcard_text,
        timeout_s=timeout_s,
        verify_tls=verify_tls,
    )
    # Reusar el dict de carddav_put_vcard + asegurar el uid usado.
    result["uid"] = used_uid
    return result


if __name__ == "__main__":
    import argparse
    import json

    parser = argparse.ArgumentParser(
        description="Anade UN contacto a la libreta CardDAV de Enmanuel."
    )
    parser.add_argument("--name", required=True, help="Nombre completo (FN).")
    parser.add_argument(
        "--tel", action="append", default=[], help="Telefono (repetible)."
    )
    parser.add_argument(
        "--email", action="append", default=[], help="Email (repetible)."
    )
    parser.add_argument(
        "--adr", action="append", default=[], help="Direccion (repetible)."
    )
    parser.add_argument("--org", default="", help="Organizacion (ORG).")
    parser.add_argument("--note", default="", help="Nota libre (NOTE).")
    parser.add_argument("--uid", default="", help="UID explicito (opcional).")
    parser.add_argument("--base-url", default=DEFAULT_BASE_URL)
    parser.add_argument("--username", default=DEFAULT_USERNAME)
    parser.add_argument("--collection-path", default=DEFAULT_COLLECTION)
    parser.add_argument("--secret-path", default="dav/xandikos-enmanuel")
    parser.add_argument("--timeout-s", type=float, default=20.0)
    parser.add_argument(
        "--no-verify-tls",
        action="store_true",
        help="Desactiva la verificacion TLS (solo pruebas).",
    )
    args = parser.parse_args()

    out = add_contact_dav(
        args.name,
        tels=args.tel,
        emails=args.email,
        adrs=args.adr,
        org=args.org,
        note=args.note,
        uid=args.uid,
        base_url=args.base_url,
        username=args.username,
        collection_path=args.collection_path,
        secret_path=args.secret_path,
        timeout_s=args.timeout_s,
        verify_tls=not args.no_verify_tls,
    )
    print(json.dumps(out, ensure_ascii=False))
