from datetime import datetime
from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.dependencies import GESTIONNAIRE_PLUS, get_current_user, require_role
from app.core.responses import api_response
from app.db.database import get_async_session
from app.schemas.extensions import ExportSignalementsRequest
from app.schemas.common import ApiResponse
from app.schemas.stats import (
    DashboardStatsResponse,
    SignalementStatsResponse,
    TeamStatsResponse,
    AlertsResponse,
    RecentCasesResponse,
    CategoryDistributionResponse,
    CasesTrendsResponse,
    ResolutionTrendsResponse,
    QuickActionsResponse,
    InvitationPendingStatsResponse,
)
from app.schemas.rapport import RapportResponse, RapportCreateRequest, RapportsPageResponse, ScheduleConfigSchema
from app.realtime import events
from app.services.stats_service import StatsService
from app.services.export_service import ExportService

router = APIRouter(prefix="/stats", tags=["Statistiques"])


@router.get("/dashboard", response_model=ApiResponse[DashboardStatsResponse])
async def dashboard_stats(
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(get_current_user),
):
    service = StatsService(db)
    if current_user.type_utilisateur in GESTIONNAIRE_PLUS:
        data = await service.get_dashboard(current_user=current_user)
    else:
        data = await service.get_dashboard_for_user(current_user.id)
    return api_response(data, message="Statistiques récupérées")


@router.get("/signalements", response_model=ApiResponse[SignalementStatsResponse])
async def signalement_stats(
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(get_current_user),
):
    service = StatsService(db)
    if current_user.type_utilisateur in GESTIONNAIRE_PLUS:
        data = await service.get_signalements_report()
    else:
        data = await service.get_signalements_report_for_user(current_user.id)
    return api_response(data, message="Rapport récupéré")


@router.post("/signalements/export", status_code=201)
async def export_signalements(
    body: ExportSignalementsRequest,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    service = ExportService(db)
    data = await service.create_signalements_export(
        format=body.format,
        date_debut=body.dateDebut,
        date_fin=body.dateFin,
        statuts=body.statuts,
        current_user=current_user,
    )
    return api_response(data, message="Export créé", status_code=201)


# Dashboard sub-endpoints (compatibility layer)

@router.get("/dashboard/team", response_model=ApiResponse[TeamStatsResponse])
async def dashboard_team(
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Get team/staff statistics."""
    service = StatsService(db)
    data = await service.get_team_stats()
    return api_response(data, message="Statistiques de l'équipe récupérées")


@router.get("/dashboard/alerts", response_model=ApiResponse[AlertsResponse])
async def dashboard_alerts(
    limit: int = Query(10, ge=1, le=100),
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(get_current_user),
):
    """Get critical/alert cases."""
    service = StatsService(db)
    if current_user.type_utilisateur in GESTIONNAIRE_PLUS:
        data = await service.get_alerts(limit=limit)
    else:
        data = await service.get_alerts_for_user(current_user.id, limit=limit)
    return api_response(data, message="Alertes récupérées")


@router.get("/dashboard/cases/recent", response_model=ApiResponse[RecentCasesResponse])
async def dashboard_recent_cases(
    limit: int = Query(5, ge=1, le=100),
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(get_current_user),
):
    """Get recent cases."""
    service = StatsService(db)
    if current_user.type_utilisateur in GESTIONNAIRE_PLUS:
        data = await service.get_recent_cases(limit=limit)
    else:
        data = await service.get_recent_cases_for_user(current_user.id, limit=limit)
    return api_response(data, message="Dossiers récents récupérés")


@router.get("/dashboard/distribution/categories", response_model=ApiResponse[CategoryDistributionResponse])
async def dashboard_category_distribution(
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Get distribution by category."""
    service = StatsService(db)
    data = await service.get_category_distribution()
    return api_response(data, message="Distribution par catégorie récupérée")


@router.get("/dashboard/trends/cases", response_model=ApiResponse[CasesTrendsResponse])
async def dashboard_cases_trends(
    start_date: datetime | None = Query(None, alias="startDate"),
    end_date: datetime | None = Query(None, alias="endDate"),
    start_date_snake: datetime | None = Query(None, alias="start_date"),
    end_date_snake: datetime | None = Query(None, alias="end_date"),
    gestionnaire_id: str | None = Query(None, alias="gestionnaireId"),
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Get case creation trends."""
    resolved_start = start_date or start_date_snake
    resolved_end = end_date or end_date_snake
    if resolved_start is None or resolved_end is None:
        return api_response({"tendances": []}, message="Paramètres startDate/endDate requis", status_code=400)
    service = StatsService(db)
    data = await service.get_cases_trends(start_date=resolved_start, end_date=resolved_end, gestionnaire_id=gestionnaire_id)
    return api_response(data, message="Tendances des cas récupérées")


@router.get("/dashboard/trends/resolution", response_model=ApiResponse[ResolutionTrendsResponse])
async def dashboard_resolution_trends(
    start_date: datetime | None = Query(None, alias="startDate"),
    end_date: datetime | None = Query(None, alias="endDate"),
    start_date_snake: datetime | None = Query(None, alias="start_date"),
    end_date_snake: datetime | None = Query(None, alias="end_date"),
    gestionnaire_id: str | None = Query(None, alias="gestionnaireId"),
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Get resolution trends."""
    resolved_start = start_date or start_date_snake
    resolved_end = end_date or end_date_snake
    if resolved_start is None or resolved_end is None:
        return api_response({"tendances": []}, message="Paramètres startDate/endDate requis", status_code=400)
    service = StatsService(db)
    data = await service.get_resolution_trends(start_date=resolved_start, end_date=resolved_end, gestionnaire_id=gestionnaire_id)
    return api_response(data, message="Tendances de résolution récupérées")


@router.get("/dashboard/quick-actions", response_model=ApiResponse[QuickActionsResponse])
async def dashboard_quick_actions(
    role: str = Query(None),
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(get_current_user),
):
    """Get quick action items."""
    service = StatsService(db)
    effective_role = role or current_user.type_utilisateur
    data = await service.get_quick_actions(role=effective_role)
    return api_response(data, message="Actions rapides récupérées")


@router.put("/dashboard/alerts/{alert_id}/dismiss")
async def dismiss_dashboard_alert(
    alert_id: str,
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    service = StatsService(db)
    data = await service.dismiss_alert(alert_id)
    dashboard = await service.get_dashboard()
    await events.broadcast_stats_updated(
        {
            "signalementsEnAttente": dashboard.get("signalementsEnAttente", 0),
            "evenementsAVenir": dashboard.get("evenementsAVenir", 0),
            "equipeAlertes": dashboard.get("equipeAlertes", 0),
            "moderationEnAttente": dashboard.get("moderationEnAttente", 0),
        }
    )
    return api_response(data, message="Alerte ignoree")


@router.get("/dashboard/invitations/pending", response_model=ApiResponse[InvitationPendingStatsResponse])
async def dashboard_pending_invitations(
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role("ADMIN_SYSTEME")),
):
    service = StatsService(db)
    data = await service.get_pending_invitations_stats()
    return api_response(data, message="Invitations en attente récupérées")


# ── Rapport CRUD & Generation Endpoints ─────────────────────────────────────

def _map_db_to_response(r) -> RapportResponse:
    status_map = {
        "EN_ATTENTE": "draft",
        "EN_COURS": "generating",
        "TERMINE": "ready",
        "ERREUR": "failed",
        "ARCHIVE": "archived"
    }
    ui_status = status_map.get(r.statut, "draft")
    
    type_map = {
        "ACTIVITY": "activity",
        "INCIDENTS": "incidents",
        "STATISTICS": "statistics",
        "PERFORMANCE": "performance",
        "COMPLIANCE": "compliance",
        "CUSTOM": "custom"
    }
    ui_type = type_map.get(r.type, "custom")
    
    fmt = (r.parametres or {}).get("format", "pdf")
    file_size = (r.resultats or {}).get("taille", 0)
    
    schedule_data = (r.parametres or {}).get("scheduleConfig")
    schedule_config = None
    if schedule_data:
        schedule_config = ScheduleConfigSchema(
            frequency=schedule_data.get("frequency", "monthly"),
            dayOfWeek=schedule_data.get("dayOfWeek"),
            dayOfMonth=schedule_data.get("dayOfMonth"),
            hour=schedule_data.get("hour", 8),
            recipients=schedule_data.get("recipients", []),
            isActive=schedule_data.get("isActive", True),
            nextRunAt=schedule_data.get("nextRunAt"),
            lastRunAt=schedule_data.get("lastRunAt"),
        )
        
    return RapportResponse(
        id=str(r.id),
        title=r.titre,
        description=r.description,
        type=ui_type,
        status=ui_status,
        createdAt=r.date_creation,
        createdById=str(r.genere_par_id) if r.genere_par_id else None,
        createdByName=f"{r.genere_par.prenom} {r.genere_par.nom}" if r.genere_par else None,
        updatedAt=r.date_generation,
        format=fmt,
        fileUrl=r.url_fichier,
        fileSize=file_size,
        isScheduled=schedule_config is not None,
        scheduleConfig=schedule_config
    )


@router.get("/rapports", response_model=ApiResponse[RapportsPageResponse])
async def list_rapports(
    page: int = Query(1, ge=1),
    size: int = Query(20, ge=1, le=100),
    type: str | None = Query(None),
    statut: str | None = Query(None),
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """List generated or scheduled reports."""
    service = ExportService(db)
    items, total = await service.list_reports(
        page=page,
        size=size,
        type_filter=type,
        status_filter=statut,
    )
    mapped_items = [_map_db_to_response(item) for item in items]
    pages = (total + size - 1) // size
    data = RapportsPageResponse(
        items=mapped_items,
        total=total,
        page=page,
        pageSize=size,
        pages=max(pages, 1)
    )
    return api_response(data, message="Rapports récupérés")


@router.get("/rapports/templates", response_model=ApiResponse[list[dict]])
async def list_report_templates(
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """List available report templates."""
    templates = [
        {
            "id": "tpl_activity",
            "name": "Rapport d'activité",
            "description": "Synthèse globale des signalements et actions d'accompagnement.",
            "type": "activity",
        },
        {
            "id": "tpl_incidents",
            "name": "Rapport des incidents",
            "description": "Statistiques détaillées sur la typologie des incidents signalés.",
            "type": "incidents",
        },
        {
            "id": "tpl_performance",
            "name": "Performance de l'équipe",
            "description": "Taux de traitement et temps moyen de réponse des gestionnaires.",
            "type": "performance",
        }
    ]
    return api_response(templates, message="Modèles récupérés")


@router.get("/rapports/{report_id}", response_model=ApiResponse[RapportResponse])
async def get_rapport(
    report_id: str,
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Get report detail by ID."""
    service = ExportService(db)
    rapport = await service.get_report_by_id(report_id)
    if not rapport:
        return api_response(None, message="Rapport introuvable", status_code=404)
    return api_response(_map_db_to_response(rapport), message="Rapport récupéré")


@router.post("/rapports", response_model=ApiResponse[RapportResponse], status_code=201)
async def create_rapport(
    body: RapportCreateRequest,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Create and trigger a report generation job."""
    service = ExportService(db)
    rapport = await service.create_report(
        title=body.title,
        report_type=body.type,
        export_format=body.format,
        description=body.description,
        period_start=body.periodStart,
        period_end=body.periodEnd,
        user_id=str(current_user.id),
        is_scheduled=body.isScheduled,
        schedule_config=body.scheduleConfig.model_dump() if body.scheduleConfig else None,
    )
    return api_response(_map_db_to_response(rapport), message="Rapport créé et génération lancée", status_code=201)


@router.post("/rapports/{report_id}/generer", response_model=ApiResponse[RapportResponse])
async def regenerate_rapport(
    report_id: str,
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Manually regenerate an existing report file."""
    service = ExportService(db)
    rapport = await service.generate_report_file(report_id)
    if not rapport:
        return api_response(None, message="Rapport introuvable", status_code=404)
    return api_response(_map_db_to_response(rapport), message="Génération du rapport déclenchée")


@router.delete("/rapports/{report_id}")
async def delete_rapport(
    report_id: str,
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Delete a report and its associated physical file."""
    service = ExportService(db)
    success = await service.delete_report(report_id)
    if not success:
        return api_response(None, message="Rapport introuvable", status_code=404)
    return api_response(None, message="Rapport supprimé")


@router.put("/rapports/{report_id}/archiver", response_model=ApiResponse[RapportResponse])
async def archive_rapport(
    report_id: str,
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Archive a generated report."""
    service = ExportService(db)
    rapport = await service.archive_report(report_id)
    if not rapport:
        return api_response(None, message="Rapport introuvable", status_code=404)
    return api_response(_map_db_to_response(rapport), message="Rapport archivé")


@router.post("/rapports/schedule", response_model=ApiResponse[RapportResponse], status_code=201)
async def schedule_rapport(
    body: RapportCreateRequest,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Schedule a new periodic report."""
    service = ExportService(db)
    rapport = await service.create_report(
        title=body.title,
        report_type=body.type,
        export_format=body.format,
        description=body.description,
        period_start=body.periodStart,
        period_end=body.periodEnd,
        user_id=str(current_user.id),
        is_scheduled=True,
        schedule_config=body.scheduleConfig.model_dump() if body.scheduleConfig else None,
    )
    return api_response(_map_db_to_response(rapport), message="Planification enregistrée", status_code=201)


@router.delete("/rapports/{report_id}/schedule")
async def cancel_scheduled_rapport(
    report_id: str,
    db: AsyncSession = Depends(get_async_session),
    _user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    """Cancel a scheduled report configuration."""
    service = ExportService(db)
    rapport = await service.get_report_by_id(report_id)
    if not rapport:
        return api_response(None, message="Rapport introuvable", status_code=404)
    
    if rapport.parametres and "scheduleConfig" in rapport.parametres:
        del rapport.parametres["scheduleConfig"]
    rapport.statut = "EN_ATTENTE"
    await db.commit()
    
    return api_response(None, message="Planification annulée")
