"""
Core Routes - Dashboard
GMAO Collège
"""
from flask import Blueprint, render_template, request, url_for, flash, redirect, jsonify
from flask_login import login_required, current_user
from datetime import datetime
from ...extensions import db
from ..models.maintenance import Intervention
from ..models.equipment import Equipment
from ..models.company import Company
from ..models.college import Building, Room
from ..models.company import Part
from app_new.constants import INTERVENTION_STATUSES, EQUIPMENT_STATUSES
from sqlalchemy import func
from ..authorization import has_permission

dashboard_bp = Blueprint('dashboard', __name__)


@dashboard_bp.route('/')
@login_required
def index():
    """Tableau de bord principal."""
    from datetime import date
    from ..services.planning_service import PlanningService
    from ..models.planning import ScheduledTask, AdminTask
    from ..models.maintenance import Lot

    dashboard_permissions = {
        'intervention': has_permission('intervention.view', current_user),
        'intervention_manage': has_permission('intervention.manage', current_user),
        'patrimoine': has_permission('patrimoine.view', current_user),
        'planning': has_permission('planning.view', current_user),
        'planning_manage': has_permission('planning.manage', current_user),
        'stock': has_permission('stock.view', current_user),
        'prevention': has_permission('prevention.view', current_user),
        'ent': has_permission('integration.ent.view', current_user),
        'outlook': has_permission('integration.outlook.view', current_user),
        'ai': has_permission('system.configure', current_user),
    }
    
    # Statistiques
    stats = {
        'interventions_total': Intervention.query.count() if dashboard_permissions['intervention'] else 0,
        'interventions_en_cours': Intervention.query.filter_by(status='en_cours').count() if dashboard_permissions['intervention'] else 0,
        'interventions_en_attente': Intervention.query.filter_by(status='en_attente').count() if dashboard_permissions['intervention'] else 0,
        'interventions_urgentes': Intervention.query.filter_by(priority='urgente', is_deleted=False).count() if dashboard_permissions['intervention'] else 0,
        'equipments_total': Equipment.query.count() if dashboard_permissions['patrimoine'] else 0,
        'equipments_actifs': Equipment.query.filter_by(status='en_service', is_deleted=False).count() if dashboard_permissions['patrimoine'] else 0,
        'equipments_panne': Equipment.query.filter(Equipment.status.in_(['en_panne', 'hors_service', 'hs']), Equipment.is_deleted.is_(False)).count() if dashboard_permissions['patrimoine'] else 0,
        'buildings_total': Building.query.count() if dashboard_permissions['patrimoine'] else 0,
        'rooms_total': Room.query.count() if dashboard_permissions['patrimoine'] else 0,
        'companies_total': Company.query.count() if dashboard_permissions['intervention'] else 0,
        'parts_low_stock': Part.query.filter(Part.quantity <= Part.min_quantity).count() if dashboard_permissions['stock'] else 0,
    }

    # Contrôle des lots : un lot présent doit être rattaché à au moins un
    # équipement, sauf s'il a été explicitement marqué « non présent ».
    equipment_counts = dict(
        db.session.query(Equipment.lot_id, func.count(Equipment.id))
        .filter(
            Equipment.lot_id.isnot(None),
            Equipment.is_deleted.is_(False),
            db.or_(Equipment.status.is_(None), Equipment.status != 'jete'),
        )
        .group_by(Equipment.lot_id)
        .all()
        if dashboard_permissions['patrimoine'] else {}
    )
    lots = Lot.query.order_by(Lot.name).all() if dashboard_permissions['patrimoine'] else []
    lots_without_equipment = [
        lot for lot in lots
        if lot.is_present and equipment_counts.get(lot.id, 0) == 0
    ]
    lots_missing_duration = []
    for lot in lots:
        if not lot.is_present or equipment_counts.get(lot.id, 0) == 0:
            continue
        active_tasks = [task for task in lot.tasks if task.is_active]
        missing_tasks = [
            task for task in lot.tasks
            if task.is_active and not task.duree_minutes
        ]
        if missing_tasks or not active_tasks:
            lots_missing_duration.append({
                'lot': lot,
                'tasks': missing_tasks,
                'no_task': not active_tasks,
            })
    stats['lots_without_equipment'] = len(lots_without_equipment)
    stats['lots_missing_duration'] = len(lots_missing_duration)
    
    # Dernières interventions
    recent_interventions = Intervention.query.order_by(Intervention.created_at.desc()).limit(10).all() if dashboard_permissions['intervention'] else []
    
    # Interventions urgentes
    urgent_interventions = Intervention.query.filter_by(priority='urgente', is_deleted=False).limit(5).all() if dashboard_permissions['intervention'] else []
    
    # Interventions du jour (planning)
    today = date.today()
    day_schedule = PlanningService.get_day_schedule(today) if dashboard_permissions['planning'] else None
    
    # Interprétations en attente (non traitées)
    from ...outlook.models import OutlookMailInterpretation
    from ...ent.interpretation_models import EntMessageInterpretation
    
    # Récupérer les interprétations Outlook
    outlook_interpretations = OutlookMailInterpretation.query.filter_by(
        status='pending',
        user_id=current_user.id
    ).order_by(OutlookMailInterpretation.created_at.desc()).limit(10).all() if dashboard_permissions['outlook'] else []
    
    # Récupérer les interprétations ENT
    ent_interpretations = EntMessageInterpretation.query.filter_by(
        status='pending'
    ).order_by(EntMessageInterpretation.created_at.desc()).limit(10).all() if dashboard_permissions['ent'] else []
    
    # Combiner les deux listes avec une source
    pending_interpretations = []
    for interp in outlook_interpretations:
        pending_interpretations.append({
            'id': interp.id,
            'source': 'Outlook',
            'date': interp.mail.received_at if interp.mail else None,
            'sender': interp.mail.from_name if interp.mail else 'Inconnu',
            'subject': interp.mail.subject if interp.mail else 'N/A',
            'type': interp.analysis_type,
            'action': interp.analysis_action,
            'description': interp.suggested_description,
            'equipment': interp.suggested_equipment,
            'confidence': getattr(interp, 'analysis_confidence', 0.5),
            'detail_url': url_for('outlook_pages.mail_view', account_id=interp.mail.account_id, mail_id=interp.mail_id) if interp.mail else url_for('outlook_dashboard.all_interpretations'),
            'create_url': url_for('outlook_dashboard.create_intervention_from_interpretation', interp_id=interp.id)
        })
    
    for interp in ent_interpretations:
        pending_interpretations.append({
            'id': interp.id,
            'source': 'ENT',
            'date': interp.message.date if interp.message else None,
            'sender': interp.message.sender_name if interp.message else 'Inconnu',
            'subject': interp.message.subject if interp.message else 'N/A',
            'type': interp.analysis_type,
            'action': interp.analysis_action,
            'description': interp.suggested_description,
            'equipment': interp.suggested_equipment,
            'confidence': getattr(interp, 'analysis_confidence', 0.5),
            'detail_url': url_for('ent.message_detail', msg_id=interp.message_id) if interp.message else url_for('ent.interpretations'),
            'create_url': url_for('interventions.create', from_interpretation=interp.id, source='ent')
        })
    
    # Trier par date décroissante
    pending_interpretations.sort(key=lambda x: x['date'] if x['date'] else datetime.min, reverse=True)
    pending_interpretations = pending_interpretations[:15]  # Limiter à 15
    
    return render_template('dashboard/index.html',
                         stats=stats,
                         recent_interventions=recent_interventions,
                         urgent_interventions=urgent_interventions,
                         pending_interpretations=pending_interpretations,
                         day_schedule=day_schedule,
                         lots_without_equipment=lots_without_equipment,
                         lots_missing_duration=lots_missing_duration,
                         today=today,
                         statuses=INTERVENTION_STATUSES,
                         dashboard_permissions=dashboard_permissions)


@dashboard_bp.route('/api/stats')
@login_required
def api_stats():
    """API JSON pour les graphiques du dashboard."""
    from datetime import date, timedelta
    from sqlalchemy import func

    can_intervention = has_permission('intervention.view', current_user)
    can_patrimoine = has_permission('patrimoine.view', current_user)

    # Interventions par mois (6 derniers mois)
    six_months_ago = date.today() - timedelta(days=180)
    monthly = db.session.query(
        func.date_format(Intervention.created_at, '%Y-%m').label('month'),
        func.count().label('count')
    ).filter(Intervention.created_at >= six_months_ago).group_by('month').order_by('month').all() if can_intervention else []

    monthly_data = [{'month': r.month, 'count': r.count} for r in monthly]

    # Interventions par statut
    status_data = {}
    if can_intervention:
        for status_val, info in INTERVENTION_STATUSES.items():
            count = Intervention.query.filter_by(status=status_val).count()
            if count > 0:
                status_data[info['label']] = count

    # Equipements par statut
    equip_status = {}
    if can_patrimoine:
        for s in EQUIPMENT_STATUSES:
            count = Equipment.query.filter_by(status=s).count()
            if count > 0:
                equip_status[s] = count

    # Top 5 equipements les plus intervenus
    top_equip = db.session.query(
        Equipment.name,
        func.count(Intervention.id).label('count')
    ).join(Intervention, Intervention.equipment_id == Equipment.id)\
     .group_by(Equipment.id)\
     .order_by(func.count(Intervention.id).desc())\
     .limit(5).all() if can_intervention and can_patrimoine else []

    top_data = [{'name': r.name, 'count': r.count} for r in top_equip]

    return jsonify({
        'monthly': monthly_data,
        'by_status': status_data,
        'equip_status': equip_status,
        'top_equipments': top_data
    })


@dashboard_bp.route('/search')
@login_required
def search():
    """Recherche globale."""
    from flask import request
    query = request.args.get('q', '')
    results = {
        'interventions': [],
        'equipments': [],
        'rooms': [],
    }
    
    if query:
        if has_permission('intervention.view', current_user):
            results['interventions'] = Intervention.query.filter(
                db.or_(
                    Intervention.title.ilike(f'%{query}%'),
                    Intervention.description.ilike(f'%{query}%')
                )
            ).limit(10).all()
        
        if has_permission('patrimoine.view', current_user):
            results['equipments'] = Equipment.query.filter(
                db.or_(
                    Equipment.name.ilike(f'%{query}%'),
                    Equipment.serial_number.ilike(f'%{query}%')
                )
            ).limit(10).all()
        
        if has_permission('patrimoine.view', current_user):
            results['rooms'] = Room.query.filter(
                Room.name.ilike(f'%{query}%')
            ).limit(10).all()
    
    return render_template('dashboard/search.html', query=query, results=results)


@dashboard_bp.route('/alerts')
@login_required
def alerts():
    """Liste des alertes."""
    from app_new.core.models.maintenance import Intervention
    from app_new.core.models.company import Alert
    alerts_list = Alert.query.filter_by(is_read=False).order_by(Alert.created_at.desc()).all()
    
    can_intervention = has_permission('intervention.view', current_user)
    can_patrimoine = has_permission('patrimoine.view', current_user)
    can_outlook = has_permission('integration.outlook.view', current_user)
    can_ent = has_permission('integration.ent.view', current_user)

    # Interventions urgentes (statut haute priorité)
    urgent_interventions = Intervention.query.filter(
        Intervention.priority == 'haute',
        Intervention.status.in_(['planifiee', 'en_cours', 'en_attente'])
    ).order_by(Intervention.scheduled_date.desc()).all() if can_intervention else []
    
    # Équipements en panne
    from app_new.core.models.equipment import Equipment
    equipments_panne = Equipment.query.filter(
        Equipment.status.in_(['en_panne', 'hors_service', 'hs']),
        Equipment.is_deleted.is_(False),
    ).all() if can_patrimoine else []
    
    # Équipements à jeter
    equipments_to_trash = Equipment.query.filter_by(status='a_jeter').all() if can_patrimoine else []
    
    # Interprétations en attente
    from ...outlook.models import OutlookMailInterpretation
    from ...ent.interpretation_models import EntMessageInterpretation
    pending_outlook = OutlookMailInterpretation.query.filter_by(
        status='pending', user_id=current_user.id
    ).order_by(OutlookMailInterpretation.created_at.desc()).all() if can_outlook else []
    pending_ent = EntMessageInterpretation.query.filter_by(
        status='pending'
    ).order_by(EntMessageInterpretation.created_at.desc()).all() if can_ent else []
    
    return render_template('dashboard/alerts.html',
                         alerts=alerts_list,
                         urgent_interventions=urgent_interventions,
                         equipments_panne=equipments_panne,
                         equipments_to_trash=equipments_to_trash,
                         pending_outlook=pending_outlook,
                         pending_ent=pending_ent)


@dashboard_bp.route('/alerts/mark-read/<int:alert_id>', methods=['POST'])
@login_required
def mark_alert_read(alert_id):
    """Marque une alerte comme lue."""
    from app_new.core.models.company import Alert
    alert = Alert.query.get(alert_id)
    if alert:
        alert.is_read = True
        db.session.commit()
        flash('Alerte marquée comme lue.', 'success')
    return redirect(url_for('dashboard.alerts'))

@dashboard_bp.route('/create-month-interventions', methods=['POST'])
@login_required
def create_month_interventions():
    """Créer les interventions pour les 30 prochains jours à partir des tâches planifiées."""
    from datetime import date, timedelta
    from ..models.planning import ScheduledTask
    from ..models.maintenance import Intervention
    from ..models.company import Company
    from flask_login import current_user

    if not (has_permission('planning.manage', current_user) or has_permission('intervention.manage', current_user)):
        from flask import abort
        abort(403)
    
    today = date.today()
    one_month_later = today + timedelta(days=30)
    
    # Récupérer les tâches planifiées dans le mois (uniquement avec équipement)
    tasks = db.session.query(ScheduledTask).filter(
        ScheduledTask.equipment_id.isnot(None),
        ScheduledTask.scheduled_date >= today,
        ScheduledTask.scheduled_date <= one_month_later,
        ScheduledTask.status.in_(['planned', 'scheduled'])
    ).all()
    
    created = 0
    for task in tasks:
        # Vérifier si l'intervention existe déjà
        existing = db.session.query(Intervention).filter(
            Intervention.equipment_id == task.equipment_id,
            Intervention.scheduled_date == task.scheduled_date,
            Intervention.scheduled_start == task.scheduled_start
        ).first()
        
        if not existing:
            intervention = Intervention(
                title=f"Intervention: {task.preventive_task.name if task.preventive_task else (task.lot_task.tache if task.lot_task else 'Tâche planifiée')}",
                description=task.notes or '',
                equipment_id=task.equipment_id,
                room_id=task.room_id,
                scheduled_date=task.scheduled_date,
                scheduled_start=task.scheduled_start,
                scheduled_end=task.scheduled_end,
                estimated_duration=task.estimated_duration or 30,
                status='en_attente',
                type='preventif',
                assigned_to_id=task.assigned_to_id,
                company_id=task.company_id,
                author_id=current_user.id,
                requester_name='Système automatique'
            )
            db.session.add(intervention)
            created += 1
    
    db.session.commit()
    flash(f'{created} interventions créées pour les 30 prochains jours', 'success')
    return redirect(url_for('dashboard.index'))
