"""Agent identity management — auto-generate and persist Ed25519 keypair.

On first MCP initialization, generates an Ed25519 keypair and saves it to
~/.sentinel-agent/identity.json. The agent_id is populated after registration
with the Sentinel backend.

Identity file format:
{
    "agent_id": "<uuid or null>",
    "public_key": "<64-char hex>",
    "private_key": "<128-char hex>",
    "created_at": "<ISO-8601>"
}
"""

import json
import logging
import os
import sys
from pathlib import Path

from sentinel_mcp.crypto import generate_keypair

logger = logging.getLogger(__name__)

IDENTITY_DIR = Path.home() / ".sentinel-agent"
IDENTITY_FILE = IDENTITY_DIR / "identity.json"


def _secure_identity_file() -> None:
    """Restrict identity file permissions to owner-only access.

    On Unix/macOS: sets chmod 600 (owner read/write only).
    On Windows: uses icacls to restrict access to the current user.
    Logs a warning if permissions cannot be restricted.
    """
    if sys.platform == "win32":
        try:
            import subprocess
            # Remove inherited permissions, grant full control to current user only
            username = os.environ.get("USERNAME", os.environ.get("USER", ""))
            if username:
                subprocess.run(
                    ["icacls", str(IDENTITY_FILE), "/inheritance:r",
                     "/grant:r", f"{username}:(R,W)"],
                    capture_output=True, check=True,
                )
                logger.debug("Restricted identity file permissions via icacls.")
            else:
                logger.warning(
                    "SECURITY: Could not determine username to restrict identity file permissions. "
                    "Private key at %s may be readable by other users. "
                    "Manually restrict access: icacls \"%s\" /inheritance:r /grant:r YOUR_USER:(R,W)",
                    IDENTITY_FILE, IDENTITY_FILE,
                )
        except Exception as e:
            logger.warning(
                "SECURITY: Failed to restrict identity file permissions on Windows (%s). "
                "Private key at %s may be readable by other users.",
                e, IDENTITY_FILE,
            )
    else:
        try:
            os.chmod(IDENTITY_FILE, 0o600)
        except OSError as e:
            logger.warning(
                "SECURITY: Failed to chmod 600 identity file (%s). "
                "Private key at %s may be readable by other users.",
                e, IDENTITY_FILE,
            )


def load_or_create_identity() -> dict:
    """Load existing identity or generate a new keypair.

    Returns:
        Dict with keys: agent_id (str|None), public_key (str), private_key (str).
    """
    if IDENTITY_FILE.exists():
        identity = json.loads(IDENTITY_FILE.read_text())
        logger.info(
            "Loaded agent identity (agent_id=%s, public_key=%s...)",
            identity.get("agent_id", "unregistered"),
            identity["public_key"][:16],
        )
        return identity

    logger.info("No identity found — generating new Ed25519 keypair...")
    keypair = generate_keypair()

    identity = {
        "agent_id": None,
        "public_key": keypair["public_key"],
        "private_key": keypair["private_key"],
        "created_at": keypair["created_at"],
    }

    IDENTITY_DIR.mkdir(parents=True, exist_ok=True)
    IDENTITY_FILE.write_text(json.dumps(identity, indent=2))

    # Restrict file permissions to owner-only read/write.
    # On Unix: chmod 600 (owner rw only).
    # On Windows: os.chmod has limited effect — warn the user.
    _secure_identity_file()

    logger.info(
        "Generated new keypair (public_key=%s...). Agent is unregistered.",
        identity["public_key"][:16],
    )
    return identity


def save_agent_id(agent_id: str) -> dict:
    """Save the backend-assigned agent_id to the identity file.

    Args:
        agent_id: UUID string returned by the Sentinel backend after registration.

    Returns:
        Updated identity dict.
    """
    if not IDENTITY_FILE.exists():
        raise FileNotFoundError("Identity file not found — keypair not generated yet.")

    identity = json.loads(IDENTITY_FILE.read_text())
    identity["agent_id"] = agent_id
    IDENTITY_FILE.write_text(json.dumps(identity, indent=2))
    logger.info("Saved agent_id=%s to identity file.", agent_id)
    return identity


def is_registered() -> bool:
    """Check if the agent has a backend-assigned agent_id."""
    if not IDENTITY_FILE.exists():
        return False
    identity = json.loads(IDENTITY_FILE.read_text())
    return identity.get("agent_id") is not None
