"""Datenbank-Modul — SQLite-Verwaltung für Agent-Identitäten und Autorisierungen."""

import sqlite3
import uuid
import hashlib
import secrets
from pathlib import Path
from datetime import datetime, timezone, timedelta

# Datenbankpfad im Home-Verzeichnis
DB_DIR = Path.home() / ".agent-identity"
DB_PATH = DB_DIR / "identities.db"


def _get_connection() -> sqlite3.Connection:
    """Datenbankverbindung herstellen und Tabellen erstellen falls nötig."""
    DB_DIR.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row

    # Agent-Identitäten
    conn.execute("""
        CREATE TABLE IF NOT EXISTS identities (
            agent_id TEXT PRIMARY KEY,
            name TEXT NOT NULL,
            owner TEXT NOT NULL,
            capabilities TEXT DEFAULT '[]',
            trust_score REAL DEFAULT 0.5,
            status TEXT DEFAULT 'active',
            created_at TEXT NOT NULL,
            updated_at TEXT NOT NULL
        )
    """)

    # Autorisierungs-Token
    conn.execute("""
        CREATE TABLE IF NOT EXISTS authorizations (
            token TEXT PRIMARY KEY,
            agent_id TEXT NOT NULL,
            action TEXT NOT NULL,
            resource TEXT DEFAULT '',
            scope TEXT DEFAULT '',
            status TEXT DEFAULT 'pending',
            granted_by TEXT,
            expires_at TEXT,
            created_at TEXT NOT NULL,
            FOREIGN KEY (agent_id) REFERENCES identities(agent_id)
        )
    """)

    # Aktivitätslog für Trust-Score-Berechnung
    conn.execute("""
        CREATE TABLE IF NOT EXISTS activity_log (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            agent_id TEXT NOT NULL,
            action TEXT NOT NULL,
            success INTEGER NOT NULL,
            timestamp TEXT NOT NULL,
            FOREIGN KEY (agent_id) REFERENCES identities(agent_id)
        )
    """)

    conn.commit()
    return conn


def generate_agent_id() -> str:
    """Eindeutige Agent-ID generieren."""
    return f"agent_{uuid.uuid4().hex[:16]}"


def generate_token() -> str:
    """Sicheres Autorisierungs-Token generieren."""
    raw = secrets.token_hex(24)
    return f"auth_{raw}"


def now_iso() -> str:
    """Aktuelle Zeit als ISO-String."""
    return datetime.now(timezone.utc).isoformat()


def future_iso(hours: int) -> str:
    """Zeitpunkt in der Zukunft als ISO-String."""
    return (datetime.now(timezone.utc) + timedelta(hours=hours)).isoformat()


# --- Identitäten ---

def create_identity(name: str, owner: str,
                    capabilities: list[str] | None = None) -> dict:
    """Neue Agent-Identität erstellen."""
    conn = _get_connection()
    agent_id = generate_agent_id()
    now = now_iso()
    import json
    caps_json = json.dumps(capabilities or [])

    conn.execute("""
        INSERT INTO identities (agent_id, name, owner, capabilities,
                                trust_score, status, created_at, updated_at)
        VALUES (?, ?, ?, ?, 0.5, 'active', ?, ?)
    """, (agent_id, name, owner, caps_json, now, now))
    conn.commit()
    conn.close()
    return {
        "agent_id": agent_id, "name": name, "owner": owner,
        "capabilities": capabilities or [], "trust_score": 0.5,
        "status": "active", "created_at": now,
    }


def get_identity(agent_id: str) -> dict | None:
    """Agent-Identität laden."""
    conn = _get_connection()
    row = conn.execute(
        "SELECT * FROM identities WHERE agent_id = ?", (agent_id,)
    ).fetchone()
    conn.close()
    if row is None:
        return None
    import json
    result = dict(row)
    result["capabilities"] = json.loads(result["capabilities"])
    return result


def list_identities(owner: str | None = None,
                    status: str | None = None) -> list[dict]:
    """Alle Agent-Identitäten auflisten."""
    conn = _get_connection()
    query = "SELECT * FROM identities WHERE 1=1"
    params = []
    if owner:
        query += " AND owner = ?"
        params.append(owner)
    if status:
        query += " AND status = ?"
        params.append(status)
    query += " ORDER BY created_at DESC"

    rows = conn.execute(query, params).fetchall()
    conn.close()
    import json
    results = []
    for row in rows:
        r = dict(row)
        r["capabilities"] = json.loads(r["capabilities"])
        results.append(r)
    return results


def update_identity(agent_id: str, **kwargs) -> bool:
    """Agent-Identität aktualisieren."""
    conn = _get_connection()
    import json
    if "capabilities" in kwargs:
        kwargs["capabilities"] = json.dumps(kwargs["capabilities"])
    kwargs["updated_at"] = now_iso()
    sets = ", ".join(f"{k} = ?" for k in kwargs)
    values = list(kwargs.values()) + [agent_id]
    cursor = conn.execute(
        f"UPDATE identities SET {sets} WHERE agent_id = ?", values
    )
    conn.commit()
    conn.close()
    return cursor.rowcount > 0


# --- Autorisierungen ---

def create_authorization(agent_id: str, action: str,
                         resource: str = "", scope: str = "",
                         expires_hours: int = 24) -> dict:
    """Autorisierungs-Anfrage erstellen."""
    conn = _get_connection()
    token = generate_token()
    now = now_iso()
    expires = future_iso(expires_hours)

    conn.execute("""
        INSERT INTO authorizations (token, agent_id, action, resource,
                                    scope, status, expires_at, created_at)
        VALUES (?, ?, ?, ?, ?, 'pending', ?, ?)
    """, (token, agent_id, action, resource, scope, expires, now))
    conn.commit()
    conn.close()
    return {
        "token": token, "agent_id": agent_id, "action": action,
        "status": "pending", "expires_at": expires,
    }


def get_authorization(token: str) -> dict | None:
    """Autorisierung laden."""
    conn = _get_connection()
    row = conn.execute(
        "SELECT * FROM authorizations WHERE token = ?", (token,)
    ).fetchone()
    conn.close()
    if row is None:
        return None
    return dict(row)


def approve_authorization(token: str, granted_by: str) -> bool:
    """Autorisierung genehmigen."""
    conn = _get_connection()
    cursor = conn.execute("""
        UPDATE authorizations SET status = 'approved', granted_by = ?
        WHERE token = ? AND status = 'pending'
    """, (granted_by, token))
    conn.commit()
    conn.close()
    return cursor.rowcount > 0


# --- Trust Score ---

def log_activity(agent_id: str, action: str, success: bool):
    """Aktivität loggen und Trust-Score aktualisieren."""
    conn = _get_connection()
    conn.execute("""
        INSERT INTO activity_log (agent_id, action, success, timestamp)
        VALUES (?, ?, ?, ?)
    """, (agent_id, action, 1 if success else 0, now_iso()))

    # Trust-Score neu berechnen (gewichteter Durchschnitt der letzten 50 Aktionen)
    rows = conn.execute("""
        SELECT success FROM activity_log
        WHERE agent_id = ?
        ORDER BY timestamp DESC LIMIT 50
    """, (agent_id,)).fetchall()

    if rows:
        total = len(rows)
        successful = sum(r["success"] for r in rows)
        score = round(successful / total, 3)
        conn.execute("""
            UPDATE identities SET trust_score = ?, updated_at = ?
            WHERE agent_id = ?
        """, (score, now_iso(), agent_id))

    conn.commit()
    conn.close()
