"""Endpoints de sesiones y reportes."""
import json
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session as DBSession
from sqlalchemy import func
from datetime import date, datetime, timedelta
from database import get_db
from models import Session, Package, TerminalPackage, AuditLog
from schemas import (
    SessionOut, DailyReport, PackageReport,
    AnulacionReport, AutorizacionReport,
)

router = APIRouter(prefix="/api", tags=["Sessions"])


def _enrich_session(session: Session, db: DBSession) -> dict:
    """Agrega package_name y expires_at a una sesion."""
    data = {
        "id": session.id,
        "package_id": session.package_id,
        "status": session.status,
        "red_minutes": session.red_minutes,
        "green_minutes": session.green_minutes,
        "blue_minutes": session.blue_minutes,
        "payment_method": session.payment_method,
        "amount": session.amount,
        "cashier": session.cashier,
        "folio_number": session.folio_number,
        "programmed_at": session.programmed_at,
        "created_at": session.created_at,
    }
    # package_name: resolver desde TerminalPackage para combos custom, Package para globales
    if session.package_id.startswith("C-"):
        tp = db.query(TerminalPackage).filter(
            TerminalPackage.combo_id == session.package_id,
            TerminalPackage.agent_id == session.agent_id,
        ).first()
        data["package_name"] = tp.name if tp else session.package_id
    else:
        pkg = db.query(Package).filter(Package.id == session.package_id).first()
        data["package_name"] = pkg.name if pkg else session.package_id

    # expires_at: usar el valor de la DB si existe, sino calcular
    if session.expires_at:
        data["expires_at"] = session.expires_at
    elif session.programmed_at:
        total = session.green_minutes + session.blue_minutes + session.red_minutes
        data["expires_at"] = session.programmed_at + timedelta(minutes=total)

    return data


@router.get("/sessions", response_model=list[SessionOut])
def list_sessions(
    status: str = Query(None),
    db: DBSession = Depends(get_db)
):
    """Lista sesiones de hoy, opcionalmente filtradas por status."""
    today = date.today().isoformat()
    q = db.query(Session).filter(
        func.date(Session.created_at, 'localtime') == today
    )
    if status:
        q = q.filter(Session.status == status)
    sessions = q.order_by(Session.created_at.desc()).all()
    return [SessionOut(**_enrich_session(s, db)) for s in sessions]


@router.get("/sessions/{session_id}", response_model=SessionOut)
def get_session(session_id: str, db: DBSession = Depends(get_db)):
    """Detalle de una sesion."""
    session = db.query(Session).filter(Session.id == session_id).first()
    if not session:
        return None
    return SessionOut(**_enrich_session(session, db))


@router.get("/reports/daily", response_model=DailyReport)
def daily_report(db: DBSession = Depends(get_db)):
    """Resumen de ventas del dia."""
    today = date.today().isoformat()
    sessions = db.query(Session).filter(
        func.date(Session.created_at, 'localtime') == today,
        Session.status.in_(['active', 'completed'])
    ).all()

    # Agrupar por package_id y resolver nombre
    pkg_data = {}
    for s in sessions:
        if s.package_id not in pkg_data:
            if s.package_id.startswith("C-"):
                tp = db.query(TerminalPackage).filter(
                    TerminalPackage.combo_id == s.package_id,
                    TerminalPackage.agent_id == s.agent_id,
                ).first()
                pkg_name = tp.name if tp else s.package_id
            else:
                pkg = db.query(Package).filter(Package.id == s.package_id).first()
                pkg_name = pkg.name if pkg else s.package_id
            pkg_data[s.package_id] = {
                'package_name': pkg_name,
                'count': 0,
                'revenue': 0.0,
            }
        pkg_data[s.package_id]['count'] += 1
        pkg_data[s.package_id]['revenue'] += s.amount

    by_package = [PackageReport(**v) for v in pkg_data.values()]

    # --- Anulaciones del dia ---
    anulacion_logs = db.query(AuditLog).filter(
        func.date(AuditLog.timestamp, 'localtime') == today,
        AuditLog.action == 'anulacion',
    ).all()
    anulaciones = []
    for log in anulacion_logs:
        try:
            d = json.loads(log.details) if log.details else {}
        except Exception:
            d = {}
        anulaciones.append(AnulacionReport(
            folio=d.get('folio', ''),
            package=d.get('package', ''),
            amount=d.get('amount', 0.0),
            supervisor=d.get('supervisor', ''),
            motivo=d.get('motivo', ''),
            cashier=log.cashier or '',
        ))

    # --- Autorizaciones del dia (cortesias y reprogramaciones) ---
    auth_logs = db.query(AuditLog).filter(
        func.date(AuditLog.timestamp, 'localtime') == today,
        AuditLog.action.in_(['cortesia', 'reprogram']),
    ).all()
    autorizaciones = []
    for log in auth_logs:
        try:
            d = json.loads(log.details) if log.details else {}
        except Exception:
            d = {}
        if log.action == 'cortesia':
            label = 'Cortesia'
            detail = d.get('package', '')
        else:
            label = 'Reprogramacion'
            old_p = d.get('old_package', '')
            new_p = d.get('new_package', '')
            detail = f"{old_p} -> {new_p}" if old_p and new_p else ''
        autorizaciones.append(AutorizacionReport(
            action_label=label,
            folio=d.get('folio', ''),
            supervisor=d.get('supervisor', ''),
            motivo=d.get('motivo', ''),
            cashier=log.cashier or '',
            detail=detail,
        ))

    return DailyReport(
        date=today,
        total_sales=len(sessions),
        total_revenue=sum(s.amount for s in sessions),
        by_package=by_package,
        anulaciones=anulaciones,
        autorizaciones=autorizaciones,
    )
