"""Identity-Tools — Agent-Identitäten erstellen, prüfen und autorisieren."""

from datetime import datetime, timezone

from mcp.server.fastmcp import FastMCP

from src.db import (
    create_identity as db_create_identity,
    get_identity as db_get_identity,
    list_identities as db_list_identities,
    update_identity,
    create_authorization,
    get_authorization,
    approve_authorization,
    log_activity,
)


def register_identity_tools(mcp: FastMCP):
    """Identity-bezogene MCP-Tools registrieren."""

    @mcp.tool()
    async def create_agent_identity(
        name: str,
        owner: str,
        capabilities: list[str] | None = None,
    ) -> dict:
        """Neue Agent-Identität erstellen.

        Registriert einen neuen AI-Agent mit Name, Besitzer und
        optionalen Fähigkeiten. Gibt eine eindeutige Agent-ID zurück.

        Args:
            name: Name des Agents (z.B. "shopping-assistant")
            owner: Besitzer/Ersteller des Agents (z.B. "chris@example.com")
            capabilities: Liste von Fähigkeiten
                          (z.B. ["read_data", "make_purchases", "send_emails"])
        """
        result = db_create_identity(
            name=name,
            owner=owner,
            capabilities=capabilities,
        )
        return {
            "agent_id": result["agent_id"],
            "name": name,
            "owner": owner,
            "capabilities": result["capabilities"],
            "trust_score": result["trust_score"],
            "status": "active",
            "message": f"Agent-Identität '{name}' erstellt.",
        }

    @mcp.tool()
    async def get_identity(agent_id: str) -> dict:
        """Agent-Identität und Trust-Score abrufen.

        Args:
            agent_id: Eindeutige Agent-ID (z.B. "agent_abc123def456")
        """
        identity = db_get_identity(agent_id)
        if identity is None:
            return {"error": f"Agent '{agent_id}' nicht gefunden."}

        # Trust-Score interpretieren
        score = identity["trust_score"]
        if score >= 0.9:
            trust_level = "Hoch"
        elif score >= 0.7:
            trust_level = "Gut"
        elif score >= 0.5:
            trust_level = "Neutral"
        elif score >= 0.3:
            trust_level = "Niedrig"
        else:
            trust_level = "Kritisch"

        return {
            "agent_id": identity["agent_id"],
            "name": identity["name"],
            "owner": identity["owner"],
            "capabilities": identity["capabilities"],
            "trust_score": score,
            "trust_level": trust_level,
            "status": identity["status"],
            "created_at": identity["created_at"],
            "updated_at": identity["updated_at"],
        }

    @mcp.tool()
    async def authorize_action(
        agent_id: str,
        action: str,
        resource: str = "",
        scope: str = "",
        expires_hours: int = 24,
    ) -> dict:
        """Autorisierung für eine bestimmte Aktion anfordern.

        Erstellt ein Autorisierungs-Token, das geprüft werden kann.
        Token sind zeitlich begrenzt.

        Args:
            agent_id: Agent-ID des anfragenden Agents
            action: Gewünschte Aktion (z.B. "read_emails", "make_purchase")
            resource: Betroffene Ressource (z.B. "inbox", "shopify-store")
            scope: Geltungsbereich (z.B. "read-only", "full-access")
            expires_hours: Gültigkeitsdauer in Stunden (Standard: 24)
        """
        identity = db_get_identity(agent_id)
        if identity is None:
            return {"error": f"Agent '{agent_id}' nicht gefunden."}

        if identity["status"] != "active":
            return {"error": f"Agent ist nicht aktiv (Status: {identity['status']})."}

        # Prüfen ob Agent die Fähigkeit hat
        capabilities = identity.get("capabilities", [])
        has_capability = (
            not capabilities  # Keine Einschränkungen
            or action in capabilities
            or any(action.startswith(c) for c in capabilities)
        )

        # Autorisierung erstellen
        expires_hours = min(max(1, expires_hours), 720)  # 1h bis 30 Tage
        auth = create_authorization(
            agent_id=agent_id,
            action=action,
            resource=resource,
            scope=scope,
            expires_hours=expires_hours,
        )

        # Bei hohem Trust automatisch genehmigen
        if identity["trust_score"] >= 0.8 and has_capability:
            approve_authorization(auth["token"], granted_by="auto-trust")
            auth["status"] = "approved"
            log_activity(agent_id, f"auto_authorize:{action}", True)

        return {
            "token": auth["token"],
            "agent_id": agent_id,
            "action": action,
            "resource": resource,
            "scope": scope,
            "status": auth["status"],
            "has_capability": has_capability,
            "trust_score": identity["trust_score"],
            "expires_at": auth["expires_at"],
            "message": (
                "Autorisierung automatisch genehmigt (hoher Trust-Score)."
                if auth["status"] == "approved"
                else "Autorisierung erstellt. Wartet auf Genehmigung."
            ),
        }

    @mcp.tool()
    async def verify_authorization(token: str) -> dict:
        """Autorisierungs-Token prüfen.

        Prüft ob ein Token gültig, genehmigt und nicht abgelaufen ist.

        Args:
            token: Das zu prüfende Autorisierungs-Token
        """
        auth = get_authorization(token)
        if auth is None:
            return {
                "valid": False,
                "error": "Token nicht gefunden.",
            }

        # Ablaufzeit prüfen
        now = datetime.now(timezone.utc)
        expires_at = auth.get("expires_at", "")
        expired = False
        if expires_at:
            try:
                exp_dt = datetime.fromisoformat(expires_at)
                expired = now > exp_dt
            except ValueError:
                pass

        # Gültigkeit bestimmen
        is_valid = (
            auth["status"] == "approved"
            and not expired
        )

        # Aktivität loggen
        if is_valid:
            log_activity(auth["agent_id"], f"use_token:{auth['action']}", True)

        return {
            "valid": is_valid,
            "token": token,
            "agent_id": auth["agent_id"],
            "action": auth["action"],
            "resource": auth.get("resource", ""),
            "scope": auth.get("scope", ""),
            "status": auth["status"],
            "expired": expired,
            "granted_by": auth.get("granted_by", ""),
            "expires_at": expires_at,
        }

    @mcp.tool()
    async def list_identities(owner: str = "",
                              status: str = "") -> dict:
        """Alle registrierten Agent-Identitäten auflisten.

        Args:
            owner: Optional — Filter nach Besitzer
            status: Optional — Filter nach Status (active, suspended, revoked)
        """
        identities = db_list_identities(
            owner=owner if owner else None,
            status=status if status else None,
        )

        return {
            "total": len(identities),
            "filter_owner": owner if owner else "alle",
            "filter_status": status if status else "alle",
            "identities": [
                {
                    "agent_id": i["agent_id"],
                    "name": i["name"],
                    "owner": i["owner"],
                    "capabilities": i["capabilities"],
                    "trust_score": i["trust_score"],
                    "status": i["status"],
                    "created_at": i["created_at"],
                }
                for i in identities
            ],
        }

    @mcp.tool()
    async def revoke_identity(agent_id: str, reason: str = "") -> dict:
        """Agent-Identität widerrufen.

        Setzt den Status auf "revoked". Der Agent kann danach
        keine Autorisierungen mehr anfordern.

        Args:
            agent_id: Agent-ID des zu sperrenden Agents
            reason: Optional — Grund für die Sperrung
        """
        identity = db_get_identity(agent_id)
        if identity is None:
            return {"error": f"Agent '{agent_id}' nicht gefunden."}

        if identity["status"] == "revoked":
            return {
                "agent_id": agent_id,
                "already_revoked": True,
                "message": "Agent ist bereits gesperrt.",
            }

        update_identity(agent_id, status="revoked")
        log_activity(agent_id, "identity_revoked", False)

        return {
            "agent_id": agent_id,
            "name": identity["name"],
            "previous_status": identity["status"],
            "new_status": "revoked",
            "reason": reason if reason else "Kein Grund angegeben",
            "message": f"Agent-Identität '{identity['name']}' wurde widerrufen.",
        }
