"""
Turnos Monitor - At-a-glance view of the request/turno pipeline.

Request -> Vet Accept + Payment -> Turno (VetVisit)

Run standalone:
    python -m ward.tools.monitors.turnos.main

Or use uvicorn:
    uvicorn ward.tools.monitors.turnos.main:app --port 12010 --reload
"""

import os
from datetime import datetime
from pathlib import Path
from typing import Optional

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy import create_engine, text
from sqlalchemy.engine import Engine

app = FastAPI(title="Turnos Monitor", version="0.1.0")

templates = Jinja2Templates(directory=Path(__file__).parent)

# =============================================================================
# NEST CONFIG - Pluggable environment targeting
# =============================================================================
# Default nest: local development database
# Override with env vars or future nest selector UI

NEST_CONFIG = {
    "name": os.getenv("NEST_NAME", "local"),
    "db": {
        "host": os.getenv("DB_HOST", "localhost"),
        "port": os.getenv("DB_PORT", "5433"),  # local default
        "name": os.getenv("DB_NAME", "amarback"),
        "user": os.getenv("DB_USER", "mariano"),
        "password": os.getenv("DB_PASSWORD", ""),
    }
}


def get_db_url() -> str:
    """Build database URL from nest config."""
    db = NEST_CONFIG["db"]
    return f"postgresql://{db['user']}:{db['password']}@{db['host']}:{db['port']}/{db['name']}"


# =============================================================================
# STATE DEFINITIONS
# =============================================================================
# Pipeline states with labels, colors, and order

STATES = {
    "pending":          ("Sin Atender",     "#fbbf24", 1),  # amber
    "in_progress_vet":  ("Buscando Vet",    "#f97316", 2),  # orange
    "vet_asked":        ("Esperando Vet",   "#fb923c", 3),  # orange light
    "vet_accepted":     ("Vet OK",          "#4ade80", 4),  # green
    "in_progress_pay":  ("Esp. Pago",       "#60a5fa", 5),  # blue
    "payed":            ("Pagado",          "#2dd4bf", 6),  # teal
    "coordinated":      ("Coordinado",      "#22c55e", 7),  # green
    "not_coordinated":  ("Sin Coord.",      "#facc15", 8),  # yellow
    "completed":        ("Turno",           "#059669", 9),  # emerald
    "rejected":         ("Rechazado",       "#f87171", 10), # red
}

# States to show in the active pipeline (exclude end states)
ACTIVE_STATES = [
    "pending",
    "in_progress_vet",
    "vet_asked",
    "vet_accepted",
    "in_progress_pay",
    "payed",
    "not_coordinated",
    "coordinated",
]

# =============================================================================
# DATABASE
# =============================================================================

_engine: Optional[Engine] = None


def get_engine() -> Optional[Engine]:
    """Get or create database engine (lazy singleton)."""
    global _engine
    if _engine is None:
        try:
            _engine = create_engine(get_db_url(), pool_pre_ping=True)
        except Exception as e:
            print(f"[turnos] DB engine error: {e}")
    return _engine


def fetch_active_requests() -> list[dict]:
    """Fetch active service requests with vet and petowner info."""
    engine = get_engine()
    if not engine:
        return []

    query = text("""
        SELECT
            sr.id,
            sr.state,
            sr.created_at,
            sr.date_coordinated,
            sr.hour_coordinated,
            sr.pay_number,
            po.first_name || ' ' || COALESCE(po.last_name, '') as petowner_name,
            COALESCE(v.first_name || ' ' || v.last_name, '') as vet_name
        FROM solicitudes_servicerequest sr
        JOIN mascotas_petowner po ON sr.petowner_id = po.id
        LEFT JOIN mascotas_veterinarian v ON sr.veterinarian_id = v.id
        WHERE sr.state = ANY(:states)
        ORDER BY
            CASE sr.state
                WHEN 'pending' THEN 1
                WHEN 'in_progress_vet' THEN 2
                WHEN 'vet_asked' THEN 3
                WHEN 'vet_accepted' THEN 4
                WHEN 'in_progress_pay' THEN 5
                WHEN 'payed' THEN 6
                WHEN 'not_coordinated' THEN 7
                WHEN 'coordinated' THEN 8
                ELSE 9
            END,
            sr.created_at DESC
    """)

    try:
        with engine.connect() as conn:
            result = conn.execute(query, {"states": ACTIVE_STATES})
            rows = result.fetchall()

        requests = []
        for row in rows:
            state_info = STATES.get(row.state, ("?", "#888", 99))
            age_h = _hours_since(row.created_at)

            requests.append({
                "id": row.id,
                "state": row.state,
                "state_label": state_info[0],
                "state_color": state_info[1],
                "petowner": row.petowner_name.strip(),
                "vet": row.vet_name.strip() if row.vet_name else "-",
                "is_paid": bool(row.pay_number),
                "is_scheduled": bool(row.date_coordinated and row.hour_coordinated),
                "age_hours": age_h,
                "age_class": "old" if age_h > 48 else ("warn" if age_h > 24 else ""),
            })
        return requests

    except Exception as e:
        print(f"[turnos] Query error: {e}")
        return []


def fetch_counts() -> dict[str, int]:
    """Fetch count per state."""
    engine = get_engine()
    if not engine:
        return {}

    query = text("""
        SELECT state, COUNT(*) as cnt
        FROM solicitudes_servicerequest
        WHERE state = ANY(:states)
        GROUP BY state
    """)

    try:
        with engine.connect() as conn:
            result = conn.execute(query, {"states": ACTIVE_STATES})
            return {row.state: row.cnt for row in result.fetchall()}
    except Exception as e:
        print(f"[turnos] Count error: {e}")
        return {}


def _hours_since(dt: Optional[datetime]) -> int:
    """Hours since datetime."""
    if not dt:
        return 0
    try:
        now = datetime.now(dt.tzinfo) if dt.tzinfo else datetime.now()
        return int((now - dt).total_seconds() / 3600)
    except:
        return 0


# =============================================================================
# ROUTES
# =============================================================================

@app.get("/health")
def health():
    """Health check."""
    engine = get_engine()
    db_ok = False
    if engine:
        try:
            with engine.connect() as conn:
                conn.execute(text("SELECT 1"))
                db_ok = True
        except:
            pass

    return {
        "status": "ok" if db_ok else "degraded",
        "service": "turnos-monitor",
        "nest": NEST_CONFIG["name"],
        "database": "connected" if db_ok else "disconnected",
    }


@app.get("/", response_class=HTMLResponse)
def index(request: Request, view: str = "pipeline"):
    """Main monitor view. ?view=list for list view."""
    requests_data = fetch_active_requests()
    counts = fetch_counts()

    # Group by state
    by_state = {s: [] for s in ACTIVE_STATES}
    for req in requests_data:
        if req["state"] in by_state:
            by_state[req["state"]].append(req)

    template = "list.html" if view == "list" else "index.html"

    return templates.TemplateResponse(template, {
        "request": request,
        "items": requests_data,
        "by_state": by_state,
        "counts": counts,
        "states": STATES,
        "active_states": ACTIVE_STATES,
        "total": len(requests_data),
        "nest_name": NEST_CONFIG["name"],
        "view": view,
    })


@app.get("/api/data")
def api_data():
    """JSON API endpoint."""
    return {
        "nest": NEST_CONFIG["name"],
        "requests": fetch_active_requests(),
        "counts": fetch_counts(),
    }


# =============================================================================
# MAIN
# =============================================================================

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=int(os.getenv("PORT", "12010")),
        reload=True,
    )
