from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Any

from src.config.hyperliquid_env import derive_address_from_private_key, mask_address, parse_env_file

DEFAULT_BASE_DIR = Path("/home/agent/.hermes")


def _candidate_files(base_dir: Path) -> list[Path]:
    ordered: list[Path] = []
    for name in ("Mainnet.env", "Testnet.env"):
        path = base_dir / name
        if path.exists():
            ordered.append(path)
    for path in sorted(base_dir.glob("*.env.bak")):
        if path not in ordered:
            ordered.append(path)
    dot_env = base_dir / ".env"
    if dot_env.exists() and dot_env not in ordered:
        ordered.append(dot_env)
    return ordered


def _env_guess(path: Path) -> str:
    lower = path.name.lower()
    if "mainnet" in lower:
        return "mainnet"
    if "testnet" in lower:
        return "testnet"
    return "unknown"


def _api_key(raw: dict[str, str]) -> str | None:
    value = (
        raw.get("HL_AGENT_WALLET_ADDRESS", "").strip()
        or raw.get("Mainnet_API_Key", "").strip()
        or raw.get("Testnet_API_Key", "").strip()
        or raw.get("API_Wallet_Adress", "").strip()
        or raw.get("API_Wallet_Address", "").strip()
        or raw.get("API Key", "").strip()
        or raw.get("API_KEY", "").strip()
    )
    return value or None


def _row(path: Path) -> tuple[dict[str, Any], str | None]:
    warnings: list[str] = []
    errors: list[str] = []
    try:
        raw = parse_env_file(path)
    except Exception as exc:
        return {
            "file": str(path),
            "env_guess": _env_guess(path),
            "HL_WALLET_ADDRESS": None,
            "API Key": None,
            "derived_address_from_HL_API_PRIVATE_KEY": None,
            "private_key_matches_API_Key": False,
            "private_key_matches_HL_WALLET_ADDRESS": False,
            "looks_like_api_wallet_private_key": False,
            "looks_like_main_wallet_private_key": False,
            "recommended_account_address": None,
            "recommended_signer_address": None,
            "safe_for_testnet_signed_probe": False,
            "warnings": [],
            "errors": [type(exc).__name__],
        }, None
    wallet = raw.get("HL_ACCOUNT_ADDRESS", "").strip() or raw.get("Mainnet_Account_Address", "").strip() or raw.get("Testnet_Account_Address", "").strip() or raw.get("HL_WALLET_ADDRESS", "").strip() or None
    private_key = raw.get("HL_AGENT_PRIVATE_KEY", "").strip() or raw.get("Mainnet_Private_Key", "").strip() or raw.get("Testnet_Private_Key", "").strip() or raw.get("HL_API_PRIVATE_KEY", "").strip() or None
    api_key = _api_key(raw)
    derived = derive_address_from_private_key(private_key)
    if not wallet:
        errors.append("missing_HL_WALLET_ADDRESS")
    if private_key and not derived:
        errors.append("invalid_HL_API_PRIVATE_KEY")
    if api_key and derived and api_key.lower() != derived.lower():
        warnings.append("api_key_private_key_mismatch")
    if wallet and api_key and wallet.lower() == api_key.lower():
        errors.append("account_address_equals_api_wallet_address")
    private_key_matches_api = bool(api_key and derived and api_key.lower() == derived.lower())
    private_key_matches_wallet = bool(wallet and derived and wallet.lower() == derived.lower())
    looks_like_api_wallet_private_key = bool(derived and not private_key_matches_wallet)
    looks_like_main_wallet_private_key = private_key_matches_wallet
    env_guess = _env_guess(path)
    safe_for_probe = bool(env_guess == "testnet" and wallet and private_key and derived and not private_key_matches_wallet and not errors)
    row = {
        "file": str(path),
        "env_guess": env_guess,
        "HL_WALLET_ADDRESS": mask_address(wallet),
        "API Key": mask_address(api_key),
        "derived_address_from_HL_API_PRIVATE_KEY": mask_address(derived),
        "private_key_matches_API_Key": private_key_matches_api,
        "private_key_matches_HL_WALLET_ADDRESS": private_key_matches_wallet,
        "looks_like_api_wallet_private_key": looks_like_api_wallet_private_key,
        "looks_like_main_wallet_private_key": looks_like_main_wallet_private_key,
        "recommended_account_address": mask_address(wallet),
        "recommended_signer_address": mask_address(derived),
        "safe_for_testnet_signed_probe": safe_for_probe,
        "warnings": warnings,
        "errors": errors,
    }
    return row, private_key


def build_credential_matrix(*, base_dir: str | Path = DEFAULT_BASE_DIR) -> dict[str, Any]:
    base = Path(base_dir).expanduser()
    rows: list[dict[str, Any]] = []
    private_keys_by_env: dict[str, str] = {}
    warnings: list[str] = []
    for path in _candidate_files(base):
        row, private_key = _row(path)
        rows.append(row)
        if private_key and row["env_guess"] in {"mainnet", "testnet"}:
            private_keys_by_env[row["env_guess"]] = private_key
    if private_keys_by_env.get("mainnet") and private_keys_by_env.get("testnet") and private_keys_by_env["mainnet"] == private_keys_by_env["testnet"]:
        warnings.append("same_private_key_used_in_both_envs")
    return {"base_dir": str(base), "files": rows, "warnings": warnings, "errors": []}


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description="Masked Hyperliquid credential matrix. Never prints private keys.")
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args(argv)
    payload = build_credential_matrix()
    print(json.dumps(payload, indent=2, sort_keys=True) if args.json else payload)
    return 0 if not payload.get("errors") else 2


if __name__ == "__main__":
    raise SystemExit(main())
