import threading
import uvicorn
import os
import sys
from typing import List, Dict, Any, Literal
from datetime import datetime
from pydantic import BaseModel, Field
import abc
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles

# --- SCHEMAS ---
class HealthPulse(BaseModel):
    agent_id: str
    status: Literal["healthy", "degraded", "down"]
    latency_ms: float
    timestamp: datetime = Field(default_factory=datetime.now)
    vitality_score: int 

class Netra(abc.ABC):
    def __init__(self, agent_id: str):
        self.agent_id = agent_id

    @abc.abstractmethod
    def gaze(self) -> HealthPulse:
        pass

class Saksh:
    _instance = None 

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Saksh, cls).__new__(cls)
        return cls._instance

    def __init__(self, start_dashboard=True, port=2604):
        if hasattr(self, '_initialized'):
            return
            
        self._thousand_eyes: List[Netra] = []
        self._initialized = True
        
        if start_dashboard:
            self._start_dashboard_thread(port)

    def open_eye(self, adapter: Netra):
        self._thousand_eyes.append(adapter)

    def observe(self) -> Dict[str, Any]:
        report = {"total": len(self._thousand_eyes), "status": "stable", "eyes": []}
        for eye in self._thousand_eyes:
            pulse = eye.gaze()
            report["eyes"].append(pulse.dict())
            if pulse.status == "down":
                report["status"] = "critical"
        return report

    def _start_dashboard_thread(self, port):
        def run_server():
            app = FastAPI(title="Saksh Sidecar")
            
            app.add_middleware(
                CORSMiddleware,
                allow_origins=["*"],
                allow_methods=["*"],
                allow_headers=["*"],
            )

            @app.get("/api/status")
            def get_status():
                return self.observe()

            # --- PATH FIX FOR LIBRARY ---
            # Finds the 'dashboard/static' folder relative to THIS file (core.py)
            current_dir = os.path.dirname(os.path.abspath(__file__))
            static_dir = os.path.join(current_dir, "dashboard", "static")
            
            if os.path.exists(static_dir):
                app.mount("/", StaticFiles(directory=static_dir, html=True), name="static")
            else:
                print(f"⚠️ SAKSH WARNING: Static files not found at {static_dir}")

            print(f"\n👁️  SAKSH DASHBOARD ONLINE: http://localhost:{port}\n")
            
            config = uvicorn.Config(app, host="0.0.0.0", port=port, log_level="error", loop="asyncio")
            server = uvicorn.Server(config)
            server.install_signal_handlers = lambda: None
            server.run()

        thread = threading.Thread(target=run_server, daemon=True)
        thread.start()