"""Parsea el texto de un secreto de `pass` para credenciales de Metabase.

Distingue dos formatos sin tocar disco ni red (funcion pura):

- API-key: una sola linea con la clave (las API keys de Metabase empiezan por
  ``mb_``, p.ej. el secreto ``metabase/aurgi-api-key``).
- Sesion: multi-linea estilo ``captacion/metabase`` — la primera linea es la
  contrasena y una linea posterior lleva el email/usuario con un prefijo
  reconocible (``email:``, ``user:``, ``login:`` o ``username:``).

El caller decide el ``mode`` y este parser solo extrae los campos del texto.
"""

# Prefijos (case-insensitive) que identifican la linea del email/usuario en un
# secreto multi-linea de pass. Se prueban en este orden.
_EMAIL_PREFIXES = ("email:", "login:", "username:", "user:")


def parse_metabase_secret(secret_text: str, mode: str = "auto") -> dict:
    """Extrae credenciales de Metabase del texto crudo de un secreto de pass.

    No ejecuta `pass` ni hace I/O: recibe el texto ya leido y lo interpreta.
    Funcion pura y determinista, apta para tests unitarios.

    Args:
        secret_text: contenido completo del secreto (varias lineas separadas por
            ``\\n``). Por convencion de pass la primera linea es la
            contrasena/clave; las siguientes son metadata.
        mode: ``"api_key"``, ``"session"`` o ``"auto"`` (default). En ``auto`` se
            detecta el formato: si hay una linea de email/usuario reconocible se
            asume sesion; si no, se asume api_key (una sola linea de clave).

    Returns:
        Dict. Nunca lanza:

        - api_key -> ``{"status": "ok", "mode": "api_key", "api_key": str}``
        - session -> ``{"status": "ok", "mode": "session", "email": str,
          "password": str}``
        - error -> ``{"status": "error", "error": str}`` para texto vacio, modo
          invalido, o session sin email/password localizables.

    Example:
        >>> parse_metabase_secret("mb_abc123")
        {'status': 'ok', 'mode': 'api_key', 'api_key': 'mb_abc123'}
        >>> parse_metabase_secret("hunter2\\nemail: a@b.com\\nurl: http://x")
        {'status': 'ok', 'mode': 'session', 'email': 'a@b.com', 'password': 'hunter2'}
    """
    if mode not in ("api_key", "session", "auto"):
        return {"status": "error", "error": f"invalid mode {mode!r}"}

    lines = secret_text.splitlines()
    if not lines or not lines[0].strip():
        return {"status": "error", "error": "empty secret"}

    email = _find_email(lines)

    if mode == "auto":
        mode = "session" if email is not None else "api_key"

    if mode == "api_key":
        return {
            "status": "ok",
            "mode": "api_key",
            "api_key": lines[0].strip(),
        }

    # mode == "session"
    if email is None:
        return {
            "status": "error",
            "error": (
                "session secret without email/user line "
                f"(expected one of {', '.join(_EMAIL_PREFIXES)})"
            ),
        }
    password = lines[0].strip()
    if not password:
        return {"status": "error", "error": "session secret without password"}
    return {
        "status": "ok",
        "mode": "session",
        "email": email,
        "password": password,
    }


def _find_email(lines: list[str]) -> str | None:
    """Devuelve el email/usuario de la primera linea con prefijo reconocido."""
    for raw in lines[1:]:
        low = raw.strip().lower()
        for prefix in _EMAIL_PREFIXES:
            if low.startswith(prefix):
                # Conserva el valor original (no el lowercased) tras el prefijo.
                value = raw.strip()[len(prefix):].strip()
                if value:
                    return value
    return None
