"""
Dashboard API - REST API for the orchestrator dashboard.

Provides:
- Agent status endpoints
- Rate limit monitoring
- Subscription management
- Usage statistics
- Interaction history
"""

import asyncio
import logging
from datetime import datetime
from typing import Any, Optional

from fastapi import FastAPI, HTTPException, Query, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field

from ..tracking import (
    RateLimitState,
    CLIStateSnapshot,
    AgentHealthStatus,
    get_all_readers,
    get_rate_limit_monitor,
)
from ..subscriptions import (
    SubscriptionTier,
    Provider,
    get_subscription_manager,
    get_tier_detector,
)
from ..interaction import (
    InteractionType,
    RiskLevel,
    ResponseAction,
    get_interaction_detector,
    get_auto_handler,
)

logger = logging.getLogger(__name__)


# Pydantic models for API
class AgentStatusResponse(BaseModel):
    """Agent status response."""

    agent_id: str
    agent_type: str
    is_running: bool
    health: str
    rate_limit: Optional[dict[str, Any]] = None
    session: Optional[dict[str, Any]] = None
    subscription: Optional[dict[str, Any]] = None
    last_updated: str


class RateLimitResponse(BaseModel):
    """Rate limit response."""

    agent_id: str
    current_usage: int
    limit: int
    remaining: int
    percentage_used: float
    reset_at: Optional[str] = None
    window_type: str


class SubscriptionResponse(BaseModel):
    """Subscription response."""

    agent_id: str
    tier: str
    provider: str
    limits: dict[str, Any]
    is_verified: bool
    auto_response_enabled: bool


class InteractionResponse(BaseModel):
    """Interaction response."""

    agent_id: str
    interaction_type: str
    prompt_text: str
    risk_level: str
    suggested_response: Optional[str]
    detected_at: str


class ResponseDecisionResponse(BaseModel):
    """Response decision response."""

    agent_id: str
    action: str
    response_text: Optional[str]
    escalation_level: str
    reason: str
    decided_at: str


class StatsResponse(BaseModel):
    """Statistics response."""

    total_agents: int
    active_agents: int
    healthy_agents: int
    agents_at_limit: int
    pending_interactions: int
    auto_responses_today: int
    by_provider: dict[str, int]
    by_tier: dict[str, int]


class RegisterAgentRequest(BaseModel):
    """Request to register an agent."""

    agent_id: str
    tier: str
    account_email: str = ""
    autonomy_level: str = "assisted"
    auto_response_enabled: bool = False


class UpdateTierRequest(BaseModel):
    """Request to update agent tier."""

    tier: str


def create_dashboard_api() -> FastAPI:
    """
    Create the dashboard FastAPI application.

    Returns:
        Configured FastAPI application
    """
    app = FastAPI(
        title="Agent Orchestrator Dashboard API",
        description="REST API for monitoring and managing AI agents",
        version="1.0.0",
    )

    # Add CORS middleware
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    # Include routers
    _setup_routes(app)

    return app


def _setup_routes(app: FastAPI) -> None:
    """Set up API routes."""

    # ==========================================================================
    # Agent Status Routes
    # ==========================================================================

    @app.get("/api/agents", response_model=list[AgentStatusResponse])
    async def list_agents() -> list[dict[str, Any]]:
        """List all registered agents with status."""
        readers = get_all_readers()
        subscription_mgr = get_subscription_manager()
        results = []

        for agent_id, reader in readers.items():
            try:
                snapshot = reader.get_snapshot(agent_id)
                subscription = subscription_mgr.get_subscription(agent_id)

                results.append({
                    "agent_id": agent_id,
                    "agent_type": snapshot.agent_type,
                    "is_running": snapshot.is_running,
                    "health": snapshot.health.value,
                    "rate_limit": snapshot.rate_limit.to_dict() if snapshot.rate_limit else None,
                    "session": snapshot.session.to_dict() if snapshot.session else None,
                    "subscription": subscription.to_dict() if subscription else None,
                    "last_updated": snapshot.timestamp.isoformat(),
                })
            except Exception as e:
                logger.warning(f"Error getting status for {agent_id}: {e}")

        return results

    @app.get("/api/agents/{agent_id}", response_model=AgentStatusResponse)
    async def get_agent(agent_id: str) -> dict[str, Any]:
        """Get status for a specific agent."""
        readers = get_all_readers()
        reader = readers.get(agent_id)

        if not reader:
            raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")

        try:
            snapshot = reader.get_snapshot(agent_id)
            subscription = get_subscription_manager().get_subscription(agent_id)

            return {
                "agent_id": agent_id,
                "agent_type": snapshot.agent_type,
                "is_running": snapshot.is_running,
                "health": snapshot.health.value,
                "rate_limit": snapshot.rate_limit.to_dict() if snapshot.rate_limit else None,
                "session": snapshot.session.to_dict() if snapshot.session else None,
                "subscription": subscription.to_dict() if subscription else None,
                "last_updated": snapshot.timestamp.isoformat(),
            }
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    # ==========================================================================
    # Rate Limit Routes
    # ==========================================================================

    @app.get("/api/rate-limits", response_model=list[RateLimitResponse])
    async def list_rate_limits() -> list[dict[str, Any]]:
        """List rate limits for all agents."""
        readers = get_all_readers()
        results = []

        for agent_id, reader in readers.items():
            try:
                snapshot = reader.get_snapshot(agent_id)
                if snapshot.rate_limit:
                    rl = snapshot.rate_limit
                    results.append({
                        "agent_id": agent_id,
                        "current_usage": rl.requests_used,
                        "limit": rl.requests_limit,
                        "remaining": rl.remaining,
                        "percentage_used": rl.percentage_used,
                        "reset_at": rl.reset_at.isoformat() if rl.reset_at else None,
                        "window_type": rl.window_type.value,
                    })
            except Exception as e:
                logger.warning(f"Error getting rate limit for {agent_id}: {e}")

        return results

    @app.get("/api/rate-limits/alerts")
    async def get_rate_limit_alerts() -> list[dict[str, Any]]:
        """Get recent rate limit alerts."""
        monitor = get_rate_limit_monitor()
        alerts = monitor.get_recent_alerts(limit=50)
        return [alert.to_dict() for alert in alerts]

    @app.get("/api/rate-limits/{agent_id}", response_model=RateLimitResponse)
    async def get_rate_limit(agent_id: str) -> dict[str, Any]:
        """Get rate limit for a specific agent."""
        readers = get_all_readers()
        reader = readers.get(agent_id)

        if not reader:
            raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")

        snapshot = reader.get_snapshot(agent_id)
        if not snapshot.rate_limit:
            raise HTTPException(status_code=404, detail="No rate limit data available")

        rl = snapshot.rate_limit
        return {
            "agent_id": agent_id,
            "current_usage": rl.requests_used,
            "limit": rl.requests_limit,
            "remaining": rl.remaining,
            "percentage_used": rl.percentage_used,
            "reset_at": rl.reset_at.isoformat() if rl.reset_at else None,
            "window_type": rl.window_type.value,
        }

    # ==========================================================================
    # Subscription Routes
    # ==========================================================================

    @app.get("/api/subscriptions", response_model=list[SubscriptionResponse])
    async def list_subscriptions() -> list[dict[str, Any]]:
        """List all agent subscriptions."""
        mgr = get_subscription_manager()
        results = []

        for agent_id in mgr.list_agents():
            sub = mgr.get_subscription(agent_id)
            if sub:
                results.append({
                    "agent_id": agent_id,
                    "tier": sub.config.tier.value,
                    "provider": sub.config.provider.value,
                    "limits": sub.config.limits.to_dict(),
                    "is_verified": sub.is_verified,
                    "auto_response_enabled": sub.config.auto_response_enabled,
                })

        return results

    @app.get("/api/subscriptions/{agent_id}", response_model=SubscriptionResponse)
    async def get_subscription(agent_id: str) -> dict[str, Any]:
        """Get subscription for a specific agent."""
        mgr = get_subscription_manager()
        sub = mgr.get_subscription(agent_id)

        if not sub:
            raise HTTPException(status_code=404, detail=f"No subscription for {agent_id}")

        return {
            "agent_id": agent_id,
            "tier": sub.config.tier.value,
            "provider": sub.config.provider.value,
            "limits": sub.config.limits.to_dict(),
            "is_verified": sub.is_verified,
            "auto_response_enabled": sub.config.auto_response_enabled,
        }

    @app.post("/api/subscriptions", response_model=SubscriptionResponse)
    async def register_subscription(request: RegisterAgentRequest) -> dict[str, Any]:
        """Register a new agent subscription."""
        mgr = get_subscription_manager()

        try:
            tier = SubscriptionTier(request.tier)
        except ValueError:
            raise HTTPException(status_code=400, detail=f"Invalid tier: {request.tier}")

        sub = mgr.register(
            agent_id=request.agent_id,
            tier=tier,
            account_email=request.account_email,
            autonomy_level=request.autonomy_level,
            auto_response_enabled=request.auto_response_enabled,
        )

        return {
            "agent_id": request.agent_id,
            "tier": sub.config.tier.value,
            "provider": sub.config.provider.value,
            "limits": sub.config.limits.to_dict(),
            "is_verified": sub.is_verified,
            "auto_response_enabled": sub.config.auto_response_enabled,
        }

    @app.put("/api/subscriptions/{agent_id}/tier")
    async def update_subscription_tier(
        agent_id: str,
        request: UpdateTierRequest,
    ) -> dict[str, Any]:
        """Update an agent's subscription tier."""
        mgr = get_subscription_manager()

        try:
            tier = SubscriptionTier(request.tier)
        except ValueError:
            raise HTTPException(status_code=400, detail=f"Invalid tier: {request.tier}")

        sub = mgr.update_tier(agent_id, tier)
        if not sub:
            raise HTTPException(status_code=404, detail=f"No subscription for {agent_id}")

        return {
            "agent_id": agent_id,
            "tier": sub.config.tier.value,
            "message": "Tier updated successfully",
        }

    @app.delete("/api/subscriptions/{agent_id}")
    async def delete_subscription(agent_id: str) -> dict[str, str]:
        """Delete an agent's subscription."""
        mgr = get_subscription_manager()

        if mgr.unregister(agent_id):
            return {"message": f"Subscription for {agent_id} deleted"}
        else:
            raise HTTPException(status_code=404, detail=f"No subscription for {agent_id}")

    @app.post("/api/subscriptions/{agent_id}/detect-tier")
    async def detect_subscription_tier(agent_id: str) -> dict[str, Any]:
        """Auto-detect subscription tier for an agent."""
        detector = get_tier_detector()
        tier, confidence = detector.detect_from_cli_state(agent_id)

        return {
            "agent_id": agent_id,
            "detected_tier": tier.value,
            "confidence": confidence,
        }

    # ==========================================================================
    # Interaction Routes
    # ==========================================================================

    @app.get("/api/interactions", response_model=list[InteractionResponse])
    async def list_pending_interactions() -> list[dict[str, Any]]:
        """List all pending interactions awaiting response."""
        detector = get_interaction_detector()
        interactions = detector.check_all_agents()

        return [
            {
                "agent_id": i.agent_id,
                "interaction_type": i.interaction_type.value,
                "prompt_text": i.prompt_text,
                "risk_level": i.risk_level.value,
                "suggested_response": i.suggested_response,
                "detected_at": i.detected_at.isoformat(),
            }
            for i in interactions
        ]

    @app.get("/api/interactions/history")
    async def get_interaction_history(
        agent_id: Optional[str] = Query(None),
        action: Optional[str] = Query(None),
        limit: int = Query(100, le=1000),
    ) -> list[dict[str, Any]]:
        """Get interaction response history."""
        handler = get_auto_handler()

        action_filter = None
        if action:
            try:
                action_filter = ResponseAction(action)
            except ValueError:
                raise HTTPException(status_code=400, detail=f"Invalid action: {action}")

        history = handler.get_history(
            agent_id=agent_id,
            action=action_filter,
            limit=limit,
        )

        return [decision.to_dict() for decision in history]

    @app.get("/api/interactions/{agent_id}", response_model=InteractionResponse)
    async def get_interaction(agent_id: str) -> dict[str, Any]:
        """Get pending interaction for a specific agent."""
        detector = get_interaction_detector()
        interaction = detector.check_agent(agent_id)

        if not interaction:
            raise HTTPException(
                status_code=404,
                detail=f"No pending interaction for {agent_id}",
            )

        return {
            "agent_id": interaction.agent_id,
            "interaction_type": interaction.interaction_type.value,
            "prompt_text": interaction.prompt_text,
            "risk_level": interaction.risk_level.value,
            "suggested_response": interaction.suggested_response,
            "detected_at": interaction.detected_at.isoformat(),
        }

    # ==========================================================================
    # Statistics Routes
    # ==========================================================================

    @app.get("/api/stats", response_model=StatsResponse)
    async def get_stats() -> dict[str, Any]:
        """Get overall orchestrator statistics."""
        readers = get_all_readers()
        subscription_mgr = get_subscription_manager()
        detector = get_interaction_detector()
        handler = get_auto_handler()

        total = len(readers)
        active = 0
        healthy = 0
        at_limit = 0

        for agent_id, reader in readers.items():
            try:
                snapshot = reader.get_snapshot(agent_id)
                if snapshot.is_running:
                    active += 1
                if snapshot.health == AgentHealthStatus.HEALTHY:
                    healthy += 1
                if snapshot.rate_limit and snapshot.rate_limit.usage_percentage >= 100:
                    at_limit += 1
            except Exception:
                pass

        pending = len(detector.check_all_agents())
        handler_stats = handler.get_stats()
        subscription_summary = subscription_mgr.get_summary()

        return {
            "total_agents": total,
            "active_agents": active,
            "healthy_agents": healthy,
            "agents_at_limit": at_limit,
            "pending_interactions": pending,
            "auto_responses_today": handler_stats.get("auto_responses_this_hour", 0),
            "by_provider": subscription_summary.get("by_provider", {}),
            "by_tier": subscription_summary.get("by_tier", {}),
        }

    @app.get("/api/stats/rate-limits")
    async def get_rate_limit_stats() -> dict[str, Any]:
        """Get rate limit statistics."""
        monitor = get_rate_limit_monitor()
        return monitor.get_health_summary()

    @app.get("/api/stats/interactions")
    async def get_interaction_stats() -> dict[str, Any]:
        """Get interaction handling statistics."""
        handler = get_auto_handler()
        return handler.get_stats()

    @app.get("/api/stats/subscriptions")
    async def get_subscription_stats() -> dict[str, Any]:
        """Get subscription statistics."""
        mgr = get_subscription_manager()
        return mgr.get_summary()

    # ==========================================================================
    # Health Check
    # ==========================================================================

    @app.get("/api/health")
    async def health_check() -> dict[str, str]:
        """API health check endpoint."""
        return {
            "status": "healthy",
            "timestamp": datetime.now().isoformat(),
        }

    @app.get("/api/tiers")
    async def list_available_tiers() -> dict[str, list[str]]:
        """List available subscription tiers by provider."""
        return {
            "anthropic": [
                SubscriptionTier.CLAUDE_FREE.value,
                SubscriptionTier.CLAUDE_PRO.value,
                SubscriptionTier.CLAUDE_MAX.value,
            ],
            "openai": [
                SubscriptionTier.CHATGPT_FREE.value,
                SubscriptionTier.CHATGPT_PLUS.value,
                SubscriptionTier.CHATGPT_PRO.value,
            ],
            "google": [
                SubscriptionTier.GEMINI_FREE.value,
                SubscriptionTier.GEMINI_PRO.value,
                SubscriptionTier.GEMINI_ULTRA.value,
            ],
        }


# Module-level app instance
_app: Optional[FastAPI] = None


def get_dashboard_app() -> FastAPI:
    """Get or create the dashboard API application."""
    global _app
    if _app is None:
        _app = create_dashboard_api()
    return _app


def set_dashboard_app(app: Optional[FastAPI]) -> None:
    """Set the dashboard API application."""
    global _app
    _app = app
