"""
Activity record building and resource extraction.

Handles automatic extraction of resources from tool parameters
for policy evaluation and activity logging.
"""
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
import re


def build_activity_record(
    agent_id: str,
    action: str,
    params: Dict[str, Any],
    task: str,
    context: Optional[Dict[str, Any]] = None,
    resources: Optional[List[Dict[str, Any]]] = None,
) -> Dict[str, Any]:
    """
    Build a complete activity record for logging or evaluation.
    
    Args:
        agent_id: The agent making the action
        action: Action identifier (e.g., "tool.fetch_revenue", "http.request")
        params: Parameters for the action
        task: Task context grouping related actions
        context: Optional context (reasoning, user_prompt, step, etc.)
        resources: Optional explicit resources (auto-extracted if not provided)
    
    Returns:
        Complete activity record ready for API submission
    """
    if resources is None:
        resources = extract_resources(action, params)
    
    return {
        "agent_id": agent_id,
        "action": action,
        "params": params,
        "task": task,
        "context": context or {},
        "resources": resources,
        "timestamp": datetime.now(tz=timezone.utc).isoformat(),
    }


def extract_resources(action: str, params: Dict[str, Any]) -> List[Dict[str, Any]]:
    """
    Auto-extract resources from action parameters.
    
    Recognizes common patterns:
    - HTTP: url, method, domain
    - S3/Storage: bucket, key
    - Database: table, query_id
    - API: service, path
    
    Args:
        action: The action identifier
        params: The action parameters
    
    Returns:
        List of resource descriptors
    """
    resources = []
    
    # HTTP resources
    if action == "http.request" or "url" in params:
        url = params.get("url", "")
        resources.append({
            "type": "http",
            "url": url,
            "method": params.get("method", "GET").upper(),
            "domain": _extract_domain(url),
            "path": _extract_path(url),
        })
    
    # S3/Storage resources
    if "bucket" in params:
        resources.append({
            "type": "s3",
            "bucket": params["bucket"],
            "key": params.get("key", "*"),
            "key_prefix": _extract_key_prefix(params.get("key", "")),
        })
    
    # Database resources
    if any(k in params for k in ("query", "table", "query_id")):
        resources.append({
            "type": "database",
            "query_id": params.get("query_id"),
            "table": params.get("table"),
            "operation": _infer_db_operation(params),
        })
    
    # API/Service resources
    if "service" in params:
        resources.append({
            "type": "api",
            "service": params["service"],
            "path": params.get("path"),
            "method": params.get("method", "GET").upper(),
        })
    
    # Tool-specific resources (extract from nested params)
    if action.startswith("tool."):
        tool_resources = _extract_tool_resources(params)
        resources.extend(tool_resources)
    
    return resources


def _extract_domain(url: str) -> str:
    """Extract domain from URL."""
    if not url:
        return ""
    try:
        parsed = urlparse(url)
        return parsed.netloc
    except Exception:
        return ""


def _extract_path(url: str) -> str:
    """Extract path from URL."""
    if not url:
        return ""
    try:
        parsed = urlparse(url)
        return parsed.path
    except Exception:
        return ""


def _extract_key_prefix(key: str) -> str:
    """Extract prefix from S3 key (directory part)."""
    if not key or "/" not in key:
        return ""
    return key.rsplit("/", 1)[0] + "/"


def _infer_db_operation(params: Dict[str, Any]) -> str:
    """Infer database operation type from params or query."""
    query = str(params.get("query", "")).upper()
    
    if query.startswith("SELECT"):
        return "read"
    elif query.startswith(("INSERT", "UPDATE", "DELETE")):
        return "write"
    elif query.startswith(("CREATE", "DROP", "ALTER")):
        return "admin"
    
    # Infer from query_id naming convention
    query_id = str(params.get("query_id", "")).lower()
    if any(w in query_id for w in ("get", "fetch", "read", "list", "select")):
        return "read"
    elif any(w in query_id for w in ("insert", "update", "delete", "write", "create")):
        return "write"
    
    return "unknown"


def _extract_tool_resources(params: Dict[str, Any]) -> List[Dict[str, Any]]:
    """Extract resources from tool parameters (nested kwargs/args)."""
    resources = []
    
    # Check kwargs for common resource patterns
    kwargs = params.get("kwargs", {})
    if isinstance(kwargs, dict):
        # Amount-based resources
        if "amount" in kwargs:
            resources.append({
                "type": "payment",
                "amount": kwargs["amount"],
                "currency": kwargs.get("currency", "USD"),
            })
        
        # Account/customer resources
        if "account_id" in kwargs or "customer_id" in kwargs:
            resources.append({
                "type": "account",
                "account_id": kwargs.get("account_id") or kwargs.get("customer_id"),
            })
        
        # Email resources
        if "to" in kwargs or "email" in kwargs:
            resources.append({
                "type": "email",
                "recipient": kwargs.get("to") or kwargs.get("email"),
            })
    
    return resources


def sanitize_params_for_logging(params: Dict[str, Any]) -> Dict[str, Any]:
    """
    Sanitize parameters for safe logging (redact sensitive fields).
    
    Args:
        params: The original parameters
    
    Returns:
        Sanitized copy with sensitive values redacted
    """
    sensitive_keys = {
        "password", "secret", "token", "api_key", "apikey",
        "authorization", "auth", "credential", "private_key",
        "access_token", "refresh_token", "bearer",
    }
    
    def _sanitize(obj: Any, depth: int = 0) -> Any:
        if depth > 10:  # Prevent infinite recursion
            return obj
        
        if isinstance(obj, dict):
            result = {}
            for k, v in obj.items():
                if k.lower() in sensitive_keys:
                    result[k] = "[REDACTED]"
                else:
                    result[k] = _sanitize(v, depth + 1)
            return result
        elif isinstance(obj, list):
            return [_sanitize(item, depth + 1) for item in obj]
        else:
            return obj
    
    return _sanitize(params)


