"""Schemas for model gateway usage summaries."""

from __future__ import annotations

from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, Field


class GatewayTokenUsage(BaseModel):
    """Token usage totals."""

    prompt_tokens: int = 0
    completion_tokens: int = 0
    total_tokens: int = 0


class GatewayBudgetSummary(BaseModel):
    """Budget snapshot for gateway usage."""

    monthly_limit_usd: Optional[float] = None
    soft_limit_usd: Optional[float] = None
    current_spend_usd: float = 0.0
    soft_limit_exceeded: bool = False
    hard_limit_exceeded: bool = False


class GatewayUsageByDay(BaseModel):
    """Daily usage aggregate."""

    date: str
    request_count: int = 0
    estimated_cost: float = 0.0
    total_tokens: int = 0


class GatewayUsageByModel(BaseModel):
    """Usage aggregate grouped by model."""

    ai_model_id: Optional[str] = None
    model_alias: Optional[str] = None
    provider_name: Optional[str] = None
    request_count: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    last_request_at: Optional[datetime] = None


class ManagedAgentModelBindingSummary(BaseModel):
    """One configured AI model binding for a managed agent."""

    id: str
    ai_model_id: Optional[str] = None
    binding_type: str
    config_key: str
    gateway_alias: str
    is_primary: bool = False
    status: str
    provider_name: Optional[str] = None
    model_identifier: Optional[str] = None
    ai_model_name: Optional[str] = None
    first_seen_at: Optional[datetime] = None
    last_seen_at: Optional[datetime] = None


class ManagedAgentModelBindingSyncItem(BaseModel):
    """Upsert payload for one managed-agent model binding."""

    ai_model_id: str
    binding_type: str = "configured"
    config_key: str
    gateway_alias: str
    is_primary: bool = False
    status: str = "gateway_ready"


class ManagedAgentModelBindingSyncRequest(BaseModel):
    """Replace request for one managed agent's configured model bindings."""

    bindings: List[ManagedAgentModelBindingSyncItem] = Field(default_factory=list)


class GatewayUsageByFlow(BaseModel):
    """Usage aggregate grouped by flow."""

    flow_id: Optional[str] = None
    flow_name: Optional[str] = None
    request_count: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0


class GatewayUsageByExecution(BaseModel):
    """Usage aggregate grouped by flow execution."""

    flow_execution_id: Optional[str] = None
    request_count: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    last_request_at: Optional[datetime] = None


class GatewayUsageBySession(BaseModel):
    """Recent usage aggregate grouped by execution-backed session slices."""

    ai_model_id: Optional[str] = None
    runtime_session_id: Optional[str] = None
    session_source_type: Optional[str] = None
    session_source_id: Optional[str] = None
    flow_execution_id: Optional[str] = None
    flow_id: Optional[str] = None
    flow_name: Optional[str] = None
    session_reference: Optional[str] = None
    model_alias: Optional[str] = None
    provider_name: Optional[str] = None
    request_count: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    last_request_at: Optional[datetime] = None


class GatewayUsageSearchResultItem(BaseModel):
    """One account-scoped gateway interaction search hit."""

    api_usage_id: str
    ai_model_id: Optional[str] = None
    timestamp: datetime
    status_code: int
    outcome: str
    endpoint: str
    method: str
    provider_name: Optional[str] = None
    model_alias: Optional[str] = None
    flow_id: Optional[str] = None
    flow_name: Optional[str] = None
    flow_execution_id: Optional[str] = None
    runtime_session_id: Optional[str] = None
    session_source_type: Optional[str] = None
    session_source_id: Optional[str] = None
    session_reference: Optional[str] = None
    runtime_principal_type: Optional[str] = None
    runtime_principal_id: Optional[str] = None
    runtime_principal_name: Optional[str] = None
    auth_subject_type: Optional[str] = None
    api_key_id: Optional[str] = None
    api_key_name: Optional[str] = None
    estimated_cost: float = 0.0
    token_usage: GatewayTokenUsage
    excerpt: str
    meta_data: dict = Field(default_factory=dict)


class AccountGatewayUsageSearchResponse(BaseModel):
    """Account-scoped gateway interaction search results."""

    period_start: Optional[datetime] = None
    period_end: Optional[datetime] = None
    query: Optional[str] = None
    total: int = 0
    limit: int = 20
    offset: int = 0
    items: List[GatewayUsageSearchResultItem] = Field(default_factory=list)


class RuntimeSessionSummary(BaseModel):
    """Aggregated runtime session summary for explorer views."""

    id: str
    session_source_type: str
    session_source_id: str
    session_reference: Optional[str] = None
    runtime_principal_type: Optional[str] = None
    runtime_principal_id: Optional[str] = None
    runtime_principal_name: Optional[str] = None
    started_at: datetime
    last_activity_at: Optional[datetime] = None
    ended_at: Optional[datetime] = None
    flow_id: Optional[str] = None
    flow_name: Optional[str] = None
    flow_execution_id: Optional[str] = None
    latest_model_alias: Optional[str] = None
    latest_provider_name: Optional[str] = None
    is_active_now: bool = False
    activity_status: str = "idle"
    total_requests: int = 0
    successful_requests: int = 0
    failed_requests: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    last_request_at: Optional[datetime] = None


class AccountRuntimeSessionListResponse(BaseModel):
    """Account-scoped runtime session explorer list response."""

    period_start: datetime
    period_end: datetime
    query: Optional[str] = None
    session_source_type: Optional[str] = None
    status: str = "all"
    total: int = 0
    limit: int = 20
    offset: int = 0
    items: List[RuntimeSessionSummary] = Field(default_factory=list)


class ManagedAgentSummary(BaseModel):
    """Read-only summary for one enrolled external agent."""

    id: str
    runtime_session_id: Optional[str] = None
    owner_user_id: Optional[str] = None
    owner_username: Optional[str] = None
    owner_email: Optional[str] = None
    agent_kind: Optional[str] = None
    display_name: str
    session_source_type: str
    session_source_id: str
    session_reference: Optional[str] = None
    enrolled_via: str
    managed_mcp_servers: List[str] = Field(default_factory=list)
    lifecycle_state: str = "active"
    lifecycle_reason: Optional[str] = None
    lifecycle_updated_at: Optional[datetime] = None
    is_active_now: bool = False
    activity_status: str = "idle"
    last_seen_at: datetime
    started_at: Optional[datetime] = None
    last_activity_at: Optional[datetime] = None
    ended_at: Optional[datetime] = None
    total_requests: int = 0
    estimated_cost: float = 0.0
    configured_model_alias: Optional[str] = None
    configured_model_id: Optional[str] = None
    configured_models: List[ManagedAgentModelBindingSummary] = Field(
        default_factory=list
    )
    latest_model_alias: Optional[str] = None
    latest_provider_name: Optional[str] = None
    last_request_at: Optional[datetime] = None
    mcp_proxy_configured: bool = False
    model_gateway_configured: bool = False
    onboarding_state: str = "incomplete"
    live_validation_supported: bool = False
    live_validation_passed: Optional[bool] = None
    live_validation_status: str = "unsupported"
    last_validated_at: Optional[datetime] = None
    tags: dict[str, str] = Field(default_factory=dict)


class ManagedAgentUsageAggregate(BaseModel):
    """Historical usage aggregate across all sessions for one managed agent."""

    session_count: int = 0
    total_requests: int = 0
    successful_requests: int = 0
    failed_requests: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    latest_model_alias: Optional[str] = None
    latest_provider_name: Optional[str] = None
    last_request_at: Optional[datetime] = None


class ManagedAgentServerActivitySummary(BaseModel):
    """Historical tool activity grouped by MCP server for one managed agent."""

    server_name: Optional[str] = None
    call_count: int = 0
    successful_calls: int = 0
    failed_calls: int = 0
    last_activity_at: Optional[datetime] = None


class ManagedAgentToolActivitySummary(BaseModel):
    """Historical tool activity grouped by MCP server and tool name."""

    server_name: Optional[str] = None
    tool_name: Optional[str] = None
    call_count: int = 0
    successful_calls: int = 0
    failed_calls: int = 0
    last_activity_at: Optional[datetime] = None


class ManagedAgentCredentialSummary(BaseModel):
    """Durable credential metadata for one managed agent."""

    id: str
    api_key_id: str
    created_by_user_id: Optional[str] = None
    name: str
    description: Optional[str] = None
    credential_type: str
    status: str
    scopes: List[str] = Field(default_factory=list)
    key_prefix: Optional[str] = None
    created_at: datetime
    updated_at: datetime
    last_issued_at: datetime
    last_used_at: Optional[datetime] = None
    expires_at: Optional[datetime] = None
    revoked_at: Optional[datetime] = None
    revoked_reason: Optional[str] = None


class ManagedAgentCredentialCreateRequest(BaseModel):
    """Request to create a durable credential for one managed agent."""

    name: str = Field(..., min_length=1, max_length=100)
    description: Optional[str] = None
    expires_in_days: Optional[int] = Field(default=365, ge=1, le=3650)
    scopes: List[str] = Field(default_factory=lambda: ["mcp:read", "mcp:write"])


class ManagedAgentCredentialCreateResponse(BaseModel):
    """One-time response payload for a newly created agent credential."""

    credential: ManagedAgentCredentialSummary
    token: str


class ManagedAgentEnrollmentSummary(BaseModel):
    """Durable enrollment state for one managed agent."""

    id: str
    created_by_user_id: Optional[str] = None
    enrollment_type: str
    adapter_key: Optional[str] = None
    status: str
    target_config_path: Optional[str] = None
    discovered_config: dict = Field(default_factory=dict)
    managed_config: dict = Field(default_factory=dict)
    backup_metadata: dict = Field(default_factory=dict)
    validation_result: dict = Field(default_factory=dict)
    restore_available: bool = False
    last_applied_at: Optional[datetime] = None
    last_validated_at: Optional[datetime] = None
    last_restored_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime


class ManagedAgentEnrollmentCreateRequest(BaseModel):
    """Request to persist an enrollment record for one managed agent."""

    enrollment_type: str = Field(..., min_length=1, max_length=64)
    adapter_key: Optional[str] = Field(default=None, max_length=64)
    status: str = Field(default="pending", min_length=1, max_length=32)
    target_config_path: Optional[str] = Field(default=None, max_length=512)
    discovered_config: dict = Field(default_factory=dict)
    managed_config: dict = Field(default_factory=dict)
    backup_metadata: dict = Field(default_factory=dict)
    validation_result: dict = Field(default_factory=dict)
    restore_available: bool = False
    last_applied_at: Optional[datetime] = None
    last_validated_at: Optional[datetime] = None
    last_restored_at: Optional[datetime] = None


class ManagedAgentEnrollmentValidateRequest(BaseModel):
    """Request to update validation state for one enrollment."""

    status: str = Field(default="validated", min_length=1, max_length=32)
    validation_result: dict = Field(default_factory=dict)


class ManagedAgentEnrollmentRestoreRequest(BaseModel):
    """Request to mark one enrollment as restored."""

    status: str = Field(default="restored", min_length=1, max_length=32)
    backup_metadata: dict = Field(default_factory=dict)
    validation_result: dict = Field(default_factory=dict)


class AccountManagedAgentListResponse(BaseModel):
    """Account-scoped managed-agent registry response."""

    query: Optional[str] = None
    agent_kind: Optional[str] = None
    last_seen_after: Optional[datetime] = None
    status: str = "all"
    total: int = 0
    limit: int = 20
    offset: int = 0
    items: List[ManagedAgentSummary] = Field(default_factory=list)


class ManagedAgentDetailResponse(BaseModel):
    """One managed agent plus its recent runtime session history."""

    agent: ManagedAgentSummary
    aggregate: ManagedAgentUsageAggregate
    usage_by_model: List[GatewayUsageByModel] = Field(default_factory=list)
    activity_by_server: List[ManagedAgentServerActivitySummary] = Field(
        default_factory=list
    )
    activity_by_tool: List[ManagedAgentToolActivitySummary] = Field(
        default_factory=list
    )
    sessions: List[RuntimeSessionSummary] = Field(default_factory=list)
    credentials: List[ManagedAgentCredentialSummary] = Field(default_factory=list)
    enrollments: List[ManagedAgentEnrollmentSummary] = Field(default_factory=list)


class ManagedAgentUpdateRequest(BaseModel):
    """Operator-driven updates for one managed agent."""

    owner_user_id: Optional[str] = None
    display_name: Optional[str] = Field(default=None, min_length=1, max_length=255)
    lifecycle_action: Optional[str] = Field(
        default=None, pattern="^(suspend|resume|decommission|reenroll)$"
    )
    reason: Optional[str] = None
    tags: Optional[dict[str, str]] = None


class RuntimeSessionUpdateRequest(BaseModel):
    """Operator-driven updates for one runtime session."""

    action: str = Field(pattern="^(end)$")
    reason: Optional[str] = None


class RuntimeSessionActivityItem(BaseModel):
    """One activity item in a runtime session timeline."""

    activity_type: str
    timestamp: datetime
    title: str
    summary: Optional[str] = None
    status: Optional[str] = None
    api_usage_id: Optional[str] = None
    tool_name: Optional[str] = None
    server_name: Optional[str] = None
    auth_subject_type: Optional[str] = None
    api_key_id: Optional[str] = None
    api_key_name: Optional[str] = None
    estimated_cost: Optional[float] = None
    total_tokens: Optional[int] = None


class RuntimeSessionActivityListResponse(BaseModel):
    """List of activity items for a runtime session."""

    items: List[RuntimeSessionActivityItem] = Field(default_factory=list)


class AccountRuntimeSessionDetailResponse(BaseModel):
    """One runtime session detail summary. (Interactions and activity moved to sub-endpoints)."""

    period_start: Optional[datetime] = None
    period_end: Optional[datetime] = None
    session: RuntimeSessionSummary
    usage_by_model: List[GatewayUsageByModel] = Field(default_factory=list)


class AccountGatewayUsageSummaryResponse(BaseModel):
    """Account-scoped gateway usage summary."""

    period_start: datetime
    period_end: datetime
    total_requests: int = 0
    successful_requests: int = 0
    failed_requests: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    budget: GatewayBudgetSummary
    requests_by_day: List[GatewayUsageByDay] = Field(default_factory=list)
    usage_by_model: List[GatewayUsageByModel] = Field(default_factory=list)
    usage_by_flow: List[GatewayUsageByFlow] = Field(default_factory=list)
    usage_by_session: List[GatewayUsageBySession] = Field(default_factory=list)


class ApiKeyGatewayUsageSummaryResponse(BaseModel):
    """API Key-scoped gateway usage summary."""

    api_key_id: str
    period_start: datetime
    period_end: datetime
    total_requests: int = 0
    successful_requests: int = 0
    failed_requests: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    requests_by_day: List[GatewayUsageByDay] = Field(default_factory=list)
    usage_by_model: List[GatewayUsageByModel] = Field(default_factory=list)
    usage_by_session: List[GatewayUsageBySession] = Field(default_factory=list)


class FlowGatewayUsageSummaryResponse(BaseModel):
    """Flow-scoped gateway usage summary."""

    flow_id: str
    flow_name: Optional[str] = None
    period_start: datetime
    period_end: datetime
    total_requests: int = 0
    successful_requests: int = 0
    failed_requests: int = 0
    token_usage: GatewayTokenUsage
    estimated_cost: float = 0.0
    budget: GatewayBudgetSummary
    usage_by_model: List[GatewayUsageByModel] = Field(default_factory=list)
    usage_by_execution: List[GatewayUsageByExecution] = Field(default_factory=list)


class DashboardTelemetryResponse(BaseModel):
    """Aggregate high-level metrics for the global dashboard control plane."""

    active_agents: int = 0
    total_tool_calls: int = 0
    daily_cost: float = 0.0
    success_rate: float = 0.0
