"""
Centralized Prometheus metric definitions for TASC-Stack.

All custom application-level metrics should be defined here for consistency
and reuse across services. HTTP-level metrics are handled separately by
the instrumentator module.
"""

from prometheus_client import Counter, Histogram, Gauge, REGISTRY, PROCESS_COLLECTOR


def enable_process_metrics():
    """Enable Python process metrics (memory, CPU, file descriptors).

    This is safe to call multiple times - it will only register once.
    Process metrics include:
    - process_virtual_memory_bytes
    - process_resident_memory_bytes
    - process_start_time_seconds
    - process_cpu_seconds_total
    - process_open_fds
    - process_max_fds
    """
    # Process collector is registered by default, but this function
    # serves as documentation and explicit enablement point
    pass


# ========================================
# LLM Performance & Cost Metrics
# ========================================

LLM_TOKENS_INPUT = Counter(
    "llm_tokens_input_total",
    "Total input (prompt) tokens sent to LLM",
    labelnames=["model", "caller"],
)

LLM_TOKENS_OUTPUT = Counter(
    "llm_tokens_output_total",
    "Total output (completion) tokens received from LLM",
    labelnames=["model", "caller"],
)

LLM_REQUEST_DURATION = Histogram(
    "llm_request_duration_seconds",
    "Total duration of LLM completion request",
    labelnames=["model", "caller"],
    buckets=(0.1, 0.25, 0.5, 1, 2.5, 5, 10, 25, 50, 100),
)

LLM_ERRORS = Counter(
    "llm_errors_total",
    "Total LLM errors by error type",
    labelnames=["model", "error_type", "caller"],
)

# ========================================
# Embedding Metrics
# ========================================

EMBEDDING_REQUEST_DURATION = Histogram(
    "embedding_request_duration_seconds",
    "Duration of embedding API calls",
    labelnames=["model"],
    buckets=(0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 15),
)

EMBEDDING_ERRORS = Counter(
    "embedding_errors_total",
    "Total embedding errors by model and error type",
    labelnames=["model", "error_type"],
)

# ========================================
# Task Execution Metrics
# ========================================

TASK_COMPLETIONS = Counter(
    "task_completions_total",
    "Total task completions by status",
    labelnames=["task_type", "status"],
)

TASK_DURATION = Histogram(
    "task_duration_seconds",
    "Task execution duration from creation to completion",
    labelnames=["task_type", "status"],
    buckets=(1, 5, 10, 30, 60, 300, 600, 1800, 3600),
)

# ========================================
# Queue Metrics
# ========================================

QUEUE_DEPTH = Gauge(
    "job_queue_depth",
    "Current depth of job queue",
    labelnames=["queue_name"],
)

JOBS_PROCESSED = Counter(
    "jobs_processed_total",
    "Total jobs processed by queue",
    labelnames=["queue_name", "status"],
)

JOB_PROCESSING_DURATION = Histogram(
    "job_processing_duration_seconds",
    "Time to process a job from dequeue to completion",
    labelnames=["queue_name", "status"],
    buckets=(0.01, 0.05, 0.1, 0.5, 1, 5, 10, 30, 60, 300, 600, 1800),
)

JOB_RETRIES = Counter(
    "job_retries_total",
    "Total job retry attempts",
    labelnames=["queue_name", "job_type"],
)

# ========================================
# Code Assistant Metrics
# ========================================

CODE_ASSISTANT_INVOCATIONS = Counter(
    "code_assistant_invocations_total",
    "Total code assistant invocations",
    labelnames=["action", "status"],
)

CODE_ASSISTANT_DURATION = Histogram(
    "code_assistant_duration_seconds",
    "Code assistant execution duration",
    labelnames=["action"],
    buckets=(1, 5, 10, 30, 60, 120, 300, 600, 1800, 3600),
)

CODE_ASSISTANT_OUTPUT_FILES = Counter(
    "code_assistant_output_files_total",
    "Total files generated by code assistant",
)

# ========================================
# Trigger Metrics
# ========================================

TRIGGER_PULLS = Counter(
    "trigger_pulls_total",
    "Total trigger pull executions",
    labelnames=["status"],
)

# ========================================
# Email Metrics
# ========================================

EMAILS_SENT = Counter(
    "emails_sent_total",
    "Total emails sent by the agent",
)

EMAIL_REPLIES = Counter(
    "email_replies_total",
    "Total email replies received from users",
)

EMAIL_UNSUBSCRIBES = Counter(
    "email_unsubscribes_total",
    "Total email unsubscribe actions",
    labelnames=["scope"],
)

# ========================================
# Message Metrics
# ========================================

USER_MESSAGES = Counter(
    "user_messages_total",
    "Total messages sent by users",
)

AGENT_MESSAGES = Counter(
    "agent_messages_total",
    "Total messages sent by agents",
    labelnames=["agent_type"],
)

# ========================================
# Wake Cycle Metrics
# ========================================

WAKE_CYCLE_DURATION = Histogram(
    "wake_cycle_duration_seconds",
    "Total duration of agent wake cycle",
    labelnames=["agent_type"],
    buckets=(0.5, 1, 2, 5, 10, 30, 60, 120, 300, 600),
)

WAKE_CYCLE_STEPS = Histogram(
    "wake_cycle_steps",
    "Number of steps executed per wake cycle",
    labelnames=["agent_type"],
    buckets=(1, 2, 3, 5, 7, 10, 15, 20, 30, 50),
)

WAKE_TO_FIRST_LLM = Histogram(
    "wake_to_first_llm_seconds",
    "Time from wake start to first LLM call",
    labelnames=["agent_type"],
    buckets=(0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10),
)

STATE_BUILD_DURATION = Histogram(
    "state_build_duration_seconds",
    "Time to load agent state (kv store, history, plugins, inbox)",
    labelnames=["agent_type"],
    buckets=(0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 5),
)

STATE_COMMIT_DURATION = Histogram(
    "state_commit_duration_seconds",
    "Time to persist agent state",
    labelnames=["agent_type"],
    buckets=(0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 5),
)

TOOL_CALL_DURATION = Histogram(
    "tool_call_duration_seconds",
    "Time for tool execution per step",
    labelnames=["agent_type"],
    buckets=(0.01, 0.1, 0.5, 1, 5, 10, 30, 60, 300, 600, 1800),
)

# ========================================
# Database Metrics
# ========================================

DB_QUERY_DURATION = Histogram(
    "db_query_duration_seconds",
    "Database query execution time",
    labelnames=["operation", "table"],
    buckets=(0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5),
)

DB_QUERY_ERRORS = Counter(
    "db_query_errors_total",
    "Database query errors",
    labelnames=["operation", "table", "error_type"],
)

DB_POOL_SIZE = Gauge(
    "db_connection_pool_size",
    "Database connection pool size by state",
    labelnames=["state", "engine"],  # state: checkedin, checkedout, overflow, total; engine: sync, async
)

DB_POOL_CHECKOUT_TIME = Histogram(
    "db_connection_checkout_seconds",
    "Time spent waiting to acquire a database connection from the pool",
    labelnames=["engine"],  # sync or async
    buckets=(0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1),
)

# ========================================
# Redis Metrics
# ========================================

REDIS_COMMAND_DURATION = Histogram(
    "redis_command_duration_seconds",
    "Redis command execution time",
    labelnames=["command"],
    buckets=(0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5),
)

REDIS_ERRORS = Counter(
    "redis_errors_total",
    "Redis operation errors",
    labelnames=["command", "error_type"],
)

# ========================================
# Authentication & Authorization Metrics
# ========================================

AUTH_ATTEMPTS = Counter(
    "auth_attempts_total",
    "Authentication attempts",
    labelnames=["method", "status"],
)

PERMISSION_CHECKS = Counter(
    "permission_checks_total",
    "Permission check outcomes",
    labelnames=["resource_type", "action", "result"],
)

AUTH_ERRORS = Counter(
    "auth_errors_total",
    "Authentication and authorization errors",
    labelnames=["operation", "error_type"],
)

# ========================================
# Service-to-Service Call Metrics
# ========================================

SERVICE_CALL_DURATION = Histogram(
    "service_call_duration_seconds",
    "Inter-service call latency",
    labelnames=["source_service", "target_service", "method"],
    buckets=(0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10),
)

SERVICE_CALL_ERRORS = Counter(
    "service_call_errors_total",
    "Inter-service call failures",
    labelnames=["source_service", "target_service", "method", "error_type"],
)

# ========================================
# Agent Session Concurrency Metrics
# ========================================

ACTIVE_AGENT_SESSIONS = Gauge(
    "active_agent_sessions",
    "Currently active agent sessions",
    labelnames=["agent_type"],
)

# ========================================
# Session Creation Metrics
# ========================================

SESSIONS_CREATED = Counter(
    "sessions_created_total",
    "Total agent sessions created",
    labelnames=["channel", "initiated_by"],
)

# ========================================
# Plugin Hook Metrics
# ========================================

PLUGIN_HOOK_DURATION = Histogram(
    "plugin_hook_duration_seconds",
    "Duration of individual plugin hook execution",
    labelnames=["hook_type", "plugin"],
    buckets=(0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10, 30, 60),
)

# ========================================
# Bot Tool Call Metrics
# ========================================

BOT_TOOL_INVOCATIONS = Counter(
    "bot_tool_invocations_total",
    "Total bot tool invocations by tool name and status",
    labelnames=["tool_name", "status"],
)

BOT_TOOL_DURATION = Histogram(
    "bot_tool_duration_seconds",
    "Duration of individual bot tool call execution",
    labelnames=["tool_name"],
    buckets=(0.01, 0.1, 0.5, 1, 5, 10, 30, 60, 300, 600, 1800),
)
