from __future__ import annotations

import json
import os
import sys
import tempfile

from aegro.cli._paths import get_config_dir, _atomic_replace

CREDENTIALS_FILE_NAME = "credentials.json"


def _warn(msg: str) -> None:
    print(f"aegro: aviso: {msg}", file=sys.stderr)


def load_credentials() -> dict[str, str]:
    """Load farm name -> API key mapping.

    Priority:
      1. AEGRO_FARMS env var (JSON string)
      2. AEGRO_FARMS_FILE env var (path to JSON file)
      3. credentials.json in config directory (interactive setup)
    """
    env_farms = os.environ.get("AEGRO_FARMS")
    if env_farms:
        try:
            farms = json.loads(env_farms)
        except json.JSONDecodeError as exc:
            _warn(f"AEGRO_FARMS contem JSON invalido: {exc}")
            return {}
        if not isinstance(farms, dict):
            _warn(f"AEGRO_FARMS deve ser um objeto JSON, recebeu {type(farms).__name__}")
            return {}
        return farms

    env_file = os.environ.get("AEGRO_FARMS_FILE")
    if env_file:
        try:
            with open(env_file, encoding="utf-8") as f:
                farms = json.load(f)
        except json.JSONDecodeError as exc:
            _warn(f"AEGRO_FARMS_FILE ({env_file}) contem JSON invalido: {exc}")
            return {}
        except UnicodeDecodeError as exc:
            _warn(
                f"AEGRO_FARMS_FILE ({env_file}) contem encoding invalido: {exc}. "
                "Salve o arquivo como UTF-8."
            )
            return {}
        except OSError as exc:
            _warn(f"Nao foi possivel ler AEGRO_FARMS_FILE ({env_file}): {exc}")
            return {}
        if not isinstance(farms, dict):
            _warn(f"AEGRO_FARMS_FILE deve conter um objeto JSON, recebeu {type(farms).__name__}")
            return {}
        return farms

    cred_file = get_config_dir() / CREDENTIALS_FILE_NAME
    if cred_file.exists():
        try:
            try:
                raw = cred_file.read_text(encoding="utf-8")
            except UnicodeDecodeError:
                raw = cred_file.read_text(encoding="cp1252")
                _warn(
                    f"Arquivo {cred_file} lido como CP1252 (encoding legado). "
                    "Sera re-salvo como UTF-8 no proximo 'aegro auth login'."
                )
            data = json.loads(raw)
        except json.JSONDecodeError as exc:
            _warn(
                f"Arquivo de credenciais corrompido ({cred_file}): {exc}. "
                "Execute 'aegro auth login' novamente."
            )
            return {}
        except OSError as exc:
            _warn(f"Nao foi possivel ler {cred_file}: {exc}")
            return {}
        farms = data.get("farms", {})
        if not isinstance(farms, dict):
            _warn(
                f"Arquivo de credenciais corrompido ({cred_file}): 'farms' nao e um objeto. "
                "Execute 'aegro auth login' novamente."
            )
            return {}
        return farms

    return {}


def save_credentials(farms: dict[str, str]) -> None:
    """Save farm credentials atomically to the aegro config directory."""
    config_dir = get_config_dir()
    config_dir.mkdir(parents=True, exist_ok=True)
    cred_file = config_dir / CREDENTIALS_FILE_NAME
    data = {"farms": farms, "auth_method": "api-key"}
    content = json.dumps(data, indent=2, ensure_ascii=False)

    fd, tmp_path = tempfile.mkstemp(dir=str(config_dir), suffix=".tmp")
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as f:
            f.write(content)
        if sys.platform != "win32":
            os.chmod(tmp_path, 0o600)
        _atomic_replace(tmp_path, str(cred_file))
    except BaseException:
        try:
            os.unlink(tmp_path)
        except OSError:
            pass
        raise


def remove_credentials() -> bool:
    """Remove stored credentials. Returns True if file existed."""
    cred_file = get_config_dir() / CREDENTIALS_FILE_NAME
    if cred_file.exists():
        cred_file.unlink()
        return True
    return False


def validate_api_key(key: str) -> bool:
    """Basic validation that an API key is non-empty and non-whitespace."""
    return bool(key and key.strip())
