from flask import current_app, session
from app_new.extensions import db
from app_new.core.models import Alert, Company, Equipment, Part, Intervention, INTERVENTION_STATUSES, User
import json
from datetime import datetime, timezone, timedelta


def format_datetime(value):
    """Formate une date/heure pour l'affichage"""
    if not value:
        return ""
    try:
        return value.strftime('%d/%m/%Y %H:%M')
    except:
        return str(value)


def format_date(value):
    """Formate une date pour l'affichage"""
    if not value:
        return ""
    try:
        return value.strftime('%d/%m/%Y')
    except:
        return str(value)


def get_user_session():
    """Récupérer l'utilisateur de la session"""
    if 'user_id' in session:
        return User.query.get(session['user_id'])
    return None


def requires_permission(user, permission):
    """Vérifier si l'utilisateur a une permission"""
    if not user:
        return False
    
    # Compatibilité pour les anciens appelants : la décision est déléguée au
    # RBAC SQL centralisé et ne lit plus User.role.
    from app_new.core.authorization import has_permission
    normalized = permission.replace(':', '.').replace('_', '.')
    return has_permission(normalized, user)


def log_action(user, action, data=None):
    """Loguer une action utilisateur"""
    try:
        # Log simple pour l'instant
        current_app.logger.info(f"User action: {user.username if user else 'anonymous'} - {action} - {data}")
    except Exception as e:
        current_app.logger.error(f"Error logging action: {str(e)}")


def log_user_action(user, action, data=None):
    """Loguer une action utilisateur avec plus de détails"""
    try:
        log_data = {
            'user_id': user.id if user else None,
            'username': user.username if user else 'anonymous',
            'action': action,
            'data': data,
            'timestamp': datetime.now(timezone.utc).isoformat()
        }
        current_app.logger.info(f"User action: {json.dumps(log_data)}")
    except Exception as e:
        current_app.logger.error(f"Error logging user action: {str(e)}")


def generate_alerts():
    """Génère les alertes automatiques : récurrence, stock bas, échéances préventif, workflow."""
    new_alerts = []

    # 1) Alertes récurrence : 3+ interventions curatives sur un même équipement
    equipments = Equipment.query.all()
    for eq in equipments:
        curative_count = eq.interventions.filter_by(type="curatif").count()
        existing = Alert.query.filter_by(
            equipment_id=eq.id, type="recurrence_equipement"
        ).first()

        if curative_count >= 3:
            msg = (f"⚠️ {eq.name} : {curative_count} interventions curatives. "
                   f"Travaux profonds recommandés.")
            if existing:
                existing.message = msg
                existing.severity = "critical"
            else:
                alert = Alert(type="recurrence_equipement", severity="critical",
                              message=msg, equipment_id=eq.id)
                new_alerts.append(alert)
        elif existing:
            db.session.delete(existing)

    # 2) Alertes stock bas
    parts = Part.query.all()
    for part in parts:
        if part.is_low_stock:
            existing = Alert.query.filter_by(
                part_id=part.id, type="stock_bas"
            ).first()
            msg = f"📦 Stock bas : {part.name} — {part.quantity}/{part.min_quantity} {part.unit}"
            if existing:
                existing.message = msg
                existing.severity = "warning"
            else:
                alert = Alert(type="stock_bas", severity="warning",
                               message=msg, part_id=part.id)
                new_alerts.append(alert)

    # 3) Alertes échéances préventif (uniquement si échéance dans les 7 prochains jours)
    now = datetime.now(timezone.utc)
    week_later = now + timedelta(days=7)
    upcoming = Intervention.query.filter(
        Intervention.type == "preventif",
        Intervention.is_recurring == True,
        Intervention.next_due_date != None,
        Intervention.next_due_date <= week_later,
        Intervention.status.in_(["brouillon", "en_cours", "attente_chef"]),
    ).all()
    for interv in upcoming:
        existing = Alert.query.filter_by(
            intervention_id=interv.id, type="preventive_echeance"
        ).first()
        if not existing:
            msg = (f"📅 Maintenance préventive à échéance : {interv.title} "
                   f"(équipement : {interv.equipment.name})")
            alert = Alert(type="preventive_echeance", severity="info",
                          message=msg, intervention_id=interv.id,
                          equipment_id=interv.equipment_id)
            new_alerts.append(alert)

    # 4) Alertes interventions en attente chef depuis +3 jours
    three_days_ago = datetime.now(timezone.utc) - timedelta(days=3)
    pending_chef = Intervention.query.filter(
        Intervention.status == "attente_chef",
        Intervention.requested_at <= three_days_ago
    ).all()
    for interv in pending_chef:
        existing = Alert.query.filter_by(
            intervention_id=interv.id, type="attente_chef"
        ).first()
        if not existing:
            msg = (f"⏳ Intervention #{interv.id} en attente du chef depuis +3 jours : {interv.title}")
            alert = Alert(type="attente_chef", severity="warning",
                          message=msg, intervention_id=interv.id)
            new_alerts.append(alert)

    # 5) Alertes interventions en demande GIMA depuis +7 jours
    seven_days_ago = datetime.now(timezone.utc) - timedelta(days=7)
    pending_gima = Intervention.query.filter(
        Intervention.status == "demande_gima",
        Intervention.updated_at <= seven_days_ago
    ).all()
    for interv in pending_gima:
        existing = Alert.query.filter_by(
            intervention_id=interv.id, type="gima_relance"
        ).first()
        if not existing:
            msg = (f"🏛️ Relance GIMA : Intervention #{interv.id} en demande GIMA depuis +7 jours : {interv.title}")
            alert = Alert(type="gima_relance", severity="info",
                          message=msg, intervention_id=interv.id)
            new_alerts.append(alert)

    db.session.add_all(new_alerts)
    db.session.commit()
    return new_alerts


def get_dashboard_stats():
    """Statistiques pour le tableau de bord."""
    stats = {}
    stats["interventions_total"] = Intervention.query.count()

    # Compter par statut du nouveau workflow
    for status_key in INTERVENTION_STATUSES:
        stats[f"interventions_{status_key}"] = Intervention.query.filter_by(status=status_key).count()

    # Stats rapides pour les cartes
    stats["interventions_en_attente_chef"] = Intervention.query.filter_by(status="attente_chef").count()
    stats["interventions_en_cours"] = Intervention.query.filter_by(status="en_cours").count()
    stats["interventions_demande_gima"] = Intervention.query.filter_by(status="demande_gima").count()
    stats["interventions_curatif"] = Intervention.query.filter_by(type="curatif").count()
    stats["interventions_preventif"] = Intervention.query.filter_by(type="preventif").count()
    stats["interventions_recurrentes"] = Intervention.query.filter_by(is_recurring=True).count()

    # Échéances préventif
    now = datetime.now(timezone.utc)
    week_later = now + timedelta(days=7)
    month_later = now + timedelta(days=30)
    stats["preventif_overdue"] = Intervention.query.filter(
        Intervention.is_recurring == True,
        Intervention.next_due_date < now
    ).count()
    stats["preventif_this_week"] = Intervention.query.filter(
        Intervention.is_recurring == True,
        Intervention.next_due_date >= now,
        Intervention.next_due_date <= week_later
    ).count()
    stats["preventif_this_month"] = Intervention.query.filter(
        Intervention.is_recurring == True,
        Intervention.next_due_date > week_later,
        Intervention.next_due_date <= month_later
    ).count()

    stats["equipments_total"] = Equipment.query.count()
    stats["equipments_hors_service"] = Equipment.query.filter(
        Equipment.status.in_(["hors_service", "out_of_service"])
    ).count()
    stats["parts_low_stock"] = Part.query.filter(Part.quantity <= Part.min_quantity).count()
    stats["alerts_unread"] = Alert.query.filter_by(is_read=False).count()
    stats["alerts_total"] = Alert.query.count()
    stats["entreprises_actives"] = Company.query.filter_by(is_active=True).count()
    return stats


def format_status(status):
    """Convertit le statut technique en label lisible."""
    from app_new.core.models import INTERVENTION_STATUSES, EQUIPMENT_STATUSES
    if status in INTERVENTION_STATUSES:
        return INTERVENTION_STATUSES[status]["label"]
    if status in EQUIPMENT_STATUSES:
        return EQUIPMENT_STATUSES[status]["label"]
    # Fallback pour statuts inconnus
    mapping = {
        "en_service": "En service",
        "hors_service": "Hors service",
        "en_reparation": "En réparation",
        "remplace": "Remplacé",
    }
    return mapping.get(status, status)


def status_badge_class(status):
    """Retourne la classe CSS Bootstrap pour un statut."""
    from app_new.core.models import INTERVENTION_STATUSES, EQUIPMENT_STATUSES
    if status in INTERVENTION_STATUSES:
        color = INTERVENTION_STATUSES[status].get("color", "secondary")
        if color == "purple":
            return "bg-purple"
        return f"bg-{color}"
    if status in EQUIPMENT_STATUSES:
        color = EQUIPMENT_STATUSES[status].get("color", "secondary")
        return f"bg-{color}"
    mapping = {
        "en_service": "bg-success",
        "hors_service": "bg-danger",
        "en_reparation": "bg-warning text-dark",
        "remplace": "bg-secondary",
    }
    return mapping.get(status, "bg-secondary")


def priority_badge_class(priority):
    """Retourne la classe CSS Bootstrap pour une priorité."""
    from app_new.core.models import PRIORITIES
    if priority in PRIORITIES:
        return f"bg-{PRIORITIES[priority]['color']}"
    mapping = {
        "basse": "bg-light text-dark",
        "normale": "bg-info",
        "haute": "bg-warning text-dark",
        "urgente": "bg-danger",
    }
    return mapping.get(priority, "bg-secondary")
