"""
Wizard de création d'équipements par lot - GMAO Collège
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_login import login_required
from app_new.extensions import db
from app_new.core.models.equipment import Equipment, EquipmentCategory
from app_new.core.models.maintenance import Lot
from app_new.core.models.college import Room, Building, Zone, RoomType
from app_new.core.services.equipment_creation import create_equipment

wizard_bp = Blueprint('wizard', __name__, url_prefix='/wizard', template_folder='templates')


@wizard_bp.route('/api/lots', methods=['POST'])
@login_required
def quick_create_lot():
    """Crée un lot depuis un formulaire d'équipement et le lie à sa catégorie."""
    data = request.get_json(silent=True) or {}
    name = (data.get('name') or '').strip()
    category_id = data.get('category_id')
    try:
        category_id = int(category_id)
    except (TypeError, ValueError):
        category_id = 0
    category = db.session.get(EquipmentCategory, category_id)
    if not name or len(name) > 500 or not category:
        return jsonify({'error': 'Sélectionnez une catégorie et saisissez le nom du lot.'}), 400
    existing = Lot.query.filter(
        Lot.category_id == category.id,
        db.func.lower(Lot.name) == name.lower(),
    ).first()
    if existing:
        return jsonify({
            'error': 'Ce lot existe déjà dans cette catégorie.',
            'lot': {'id': existing.id, 'name': existing.name, 'category_id': category.id},
        }), 409
    lot = Lot(name=name, category_id=category.id, is_present=True)
    db.session.add(lot)
    db.session.commit()
    return jsonify({
        'success': True,
        'lot': {'id': lot.id, 'name': lot.name, 'category_id': category.id},
    }), 201


@wizard_bp.route('/equipments')
@login_required
def equipment_wizard():
    """Page principale du wizard de création d'équipements."""
    categories = EquipmentCategory.query.order_by(EquipmentCategory.name).all()
    buildings = Building.query.order_by(Building.name).all()
    room_types = RoomType.query.order_by(RoomType.name).all()
    
    # Récupérer les lots groupés par catégorie (relation directe)
    lots_by_category = {}
    for cat in categories:
        lots_by_category[cat.id] = [{'id': lot.id, 'name': lot.name} for lot in cat.lots]
    
    # Tous les lots pour fallback
    lots = Lot.query.order_by(Lot.name).all()
    
    housing_id = request.args.get('housing_id', type=int)
    selected_room_ids = []
    if housing_id:
        from app_new.core.models.college import HousingUnit
        housing = HousingUnit.query.get_or_404(housing_id)
        selected_room_ids = [room.id for room in housing.rooms]
    return render_template('wizard/equipment_wizard.html',
                          lots=lots,
                          categories=categories,
                          buildings=buildings,
                          room_types=room_types,
                          lots_by_category=lots_by_category,
                          selected_room_ids=selected_room_ids)


@wizard_bp.route('/equipments/bulk-create', methods=['POST'])
@login_required
def bulk_create_equipments():
    """Crée plusieurs familles d'équipements en une transaction."""
    data = request.get_json(silent=True) or {}
    room_ids = list(dict.fromkeys(data.get('room_ids') or []))
    items = data.get('items') or []
    rooms = Room.query.filter(Room.id.in_(room_ids)).all() if room_ids else []
    if len(rooms) != len(room_ids):
        return jsonify({'error': 'Une ou plusieurs pièces sont invalides.'}), 400
    if not rooms or not items:
        return jsonify({'error': 'Sélectionnez au moins une pièce et un équipement.'}), 400

    created = []
    try:
        for raw in items:
            name = (raw.get('name') or '').strip()
            category_raw = raw.get('category_id')
            lot_raw = raw.get('lot_id')
            category = db.session.get(EquipmentCategory, int(category_raw)) if category_raw not in (None, '') else None
            lot = db.session.get(Lot, int(lot_raw)) if lot_raw not in (None, '') else None
            quantity = int(raw.get('quantity') or 1)
            mode = raw.get('mode', 'quantitatif')
            mobility = raw.get('mobility', 'non_precise')
            if not name or quantity < 1 or quantity > 1000 or (category_raw not in (None, '') and not category) or (lot_raw not in (None, '') and not lot):
                raise ValueError('Une ligne contient des données invalides.')
            if lot and category and lot.category_id != category.id:
                raise ValueError(f'Le lot « {lot.name} » ne correspond pas à la catégorie « {category.name} ».')

            root = create_equipment(
                name=name, category_id=category.id if category else None,
                lot_id=lot.id if lot else None, is_group=True,
                quantity=quantity * len(rooms), mobility=mobility,
                tracked_individually=(mode == 'individuel'), status='en_service',
                create_schedule=False,
            )
            created.append(root)
            for room in rooms:
                group = create_equipment(
                    name=name, parent_id=root.id, room_id=room.id, is_group=True,
                    quantity=quantity, mobility=mobility, status='en_service',
                    tracked_individually=(mode == 'individuel'),
                    create_schedule=False,
                )
                created.append(group)
                if mode == 'individuel':
                    for number in range(1, quantity + 1):
                        unit = create_equipment(
                            name=f'{name} #{number}', parent_id=group.id, room_id=room.id,
                            is_group=False, quantity=1, mobility=mobility,
                            tracked_individually=True, individual_number=number,
                            status='en_service', position=f'{name} n°{number}',
                            create_schedule=False,
                        )
                        created.append(unit)
        # Valider d'abord le patrimoine. La génération des échéances est
        # volontairement découplée : une anomalie dans un lot ne doit jamais
        # annuler les équipements déjà créés.
        db.session.commit()
        task_targets = [eq for eq in created if (not eq.is_group or (eq.parent_id and not eq.tracked_individually))]
        task_errors = []
        for equipment in task_targets:
            try:
                equipment.create_scheduled_tasks_from_lot(commit=True)
            except Exception as exc:
                db.session.rollback()
                message = f"Équipement {equipment.id} ({equipment.name}) : {str(exc)[:500]}"
                task_errors.append(message)
                current_app.logger.exception('Échec génération tâche préventive - %s', message)
                try:
                    from app_new.watchdog_logger import log_watchdog
                    log_watchdog('wizard_equipements', message, level='error')
                except Exception:
                    pass
        return jsonify({'success': True, 'created_count': len(created), 'families': len(items), 'rooms': len(rooms),
                        'task_errors': task_errors})
    except (TypeError, ValueError) as exc:
        db.session.rollback()
        return jsonify({'error': str(exc)}), 400
    except Exception:
        db.session.rollback()
        current_app.logger.exception('Échec de la création massive du patrimoine')
        return jsonify({'error': 'La création a été annulée intégralement.'}), 500


@wizard_bp.route('/api/rooms/<int:building_id>')
@login_required
def get_rooms(building_id):
    """Récupère les salles d'un bâtiment."""
    rooms = Room.query.filter_by(building_id=building_id).order_by(Room.name).all()
    return jsonify([{
        'id': r.id,
        'name': r.name,
        'zone': r.zone.name if r.zone else None
    } for r in rooms])


@wizard_bp.route('/api/zones/<int:building_id>')
@login_required
def get_zones(building_id):
    """Récupère les zones d'un bâtiment."""
    zones = Zone.query.filter_by(building_id=building_id).order_by(Zone.name).all()
    return jsonify([{
        'id': z.id,
        'name': z.name
    } for z in zones])


@wizard_bp.route('/api/lot_tasks/<int:lot_id>')
@login_required
def get_lot_tasks(lot_id):
    """Récupère les tâches préventives d'un lot."""
    from app_new.core.models.maintenance import LotTask
    
    tasks = LotTask.query.filter_by(lot_id=lot_id).order_by(LotTask.num_tache).all()
    return jsonify([{
        'id': t.id,
        'num_tache': t.num_tache,
        'tache': t.tache,
        'periodicite': t.periodicite,
        'contrat': t.contrat,
        'gestionnaire': t.gestionnaire,
        'type_maintenance': t.type_maintenance
    } for t in tasks])


@wizard_bp.route('/equipments/create', methods=['POST'])
@login_required
def create_equipments():
    """Crée les équipements selon les paramètres du wizard."""
    try:
        data = request.get_json()
        
        lot_id = data.get('lot_id')
        category_id = data.get('category_id')
        equipment_name = data.get('name', '').strip()  # Nom personnalisé
        parent_name = data.get('parent_name')
        create_parent = data.get('create_parent', False)
        building_id = data.get('building_id')
        zone_id = data.get('zone_id')
        rooms_data = data.get('rooms', [])  # [{room_id, count}, ...]
        tracked_individually = data.get('tracked_individually', False)
        
        # Debug
        current_app.logger.info(f"Création équipements: tracked_individually={tracked_individually}, rooms={rooms_data}")
        
        if category_id and not db.session.get(EquipmentCategory, category_id):
            return jsonify({'error': 'Catégorie invalide'}), 400
        if lot_id and not db.session.get(Lot, lot_id):
            return jsonify({'error': 'Lot invalide'}), 400
        
        if not rooms_data:
            return jsonify({'error': 'Au moins une salle requise'}), 400
        
        lot = db.session.get(Lot, lot_id) if lot_id else None
        category = db.session.get(EquipmentCategory, category_id) if category_id else None
        
        # Nom de base: personnalisé ou catégorie
        base_name = equipment_name if equipment_name else (category.name if category else 'Équipement')
        
        created_equipments = []
        created_instances = []
        
        # Étape 1: Créer le parent global (si demandé)
        parent = None
        if create_parent and parent_name:
            parent = create_equipment(
                name=parent_name,
                lot_id=lot_id,
                category_id=category_id,
                is_group=True,
                parent_id=None, create_schedule=False,
            )
            created_instances.append(parent)
        
        # Étape 2: Pour chaque salle, créer le groupe et les individuels
        for room_data in rooms_data:
            room_id = room_data.get('room_id')
            count = room_data.get('count', 1)
            
            room = Room.query.get(room_id)
            if not room:
                continue
            
            if tracked_individually:
                # Avec suivi individuel: créer un groupe + des individus
                room_group = create_equipment(
                    name=f"{base_name} {room.name}",
                    lot_id=lot_id if not parent else None,
                    category_id=category_id if not parent else None,
                    is_group=True,
                    parent_id=parent.id if parent else None,
                    room_id=room_id,
                    quantity=1, create_schedule=False,
                )
                created_instances.append(room_group)
                
                created_equipments.append({
                    'type': 'group',
                    'name': room_group.name,
                    'room': room.name,
                    'quantity': 1
                })
                
                # Créer les équipements individuels
                if count > 1:
                    for i in range(1, count + 1):
                        individual = create_equipment(
                            name=f"{base_name} {i}",
                            lot_id=lot_id,  # Hériter du lot
                            category_id=category_id,  # Hériter de la catégorie
                            is_group=False,
                            tracked_individually=True,
                            parent_id=room_group.id,
                            room_id=room_id,
                            position=f"{base_name} n°{i}", create_schedule=False,
                        )
                        created_instances.append(individual)
                        
                        created_equipments.append({
                            'type': 'individual',
                            'name': individual.name,
                            'room': room.name
                        })
            else:
                # Sans suivi individuel: créer un seul équipement avec quantity
                equipment = create_equipment(
                    name=f"{base_name} {room.name}",
                    lot_id=lot_id if not parent else None,
                    category_id=category_id if not parent else None,
                    is_group=False,
                    parent_id=parent.id if parent else None,
                    room_id=room_id,
                    quantity=count, create_schedule=False,
                )
                created_instances.append(equipment)
                
                created_equipments.append({
                    'type': 'equipment',
                    'name': equipment.name,
                    'room': room.name,
                    'quantity': count
                })
        
        db.session.commit()
        for equipment in created_instances:
            if equipment.effective_lot_id:
                equipment.create_scheduled_tasks_from_lot()
        
        # Les instances créées sont conservées en mémoire : aucune recherche
        # fragile par nom (deux équipements peuvent porter le même libellé).

        return jsonify({
            'success': True,
            'count': len(created_equipments),
            'equipments': created_equipments
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@wizard_bp.route('/equipments/preview', methods=['POST'])
@login_required
def preview_equipments():
    """Prévisualise les équipements qui seront créés."""
    data = request.get_json()
    
    lot_id = data.get('lot_id')
    category_id = data.get('category_id')
    parent_name = data.get('parent_name')
    create_parent = data.get('create_parent', False)
    rooms_data = data.get('rooms', [])
    tracked_individually = data.get('tracked_individually', False)
    
    lot = Lot.query.get(lot_id) if lot_id else None
    category = EquipmentCategory.query.get(category_id) if category_id else None
    
    preview = []
    
    # Parent global
    if create_parent and parent_name:
        preview.append({
            'level': 0,
            'name': parent_name,
            'type': 'Groupe parent',
            'lot': lot.name if lot else '-',
            'category': category.name if category else '-',
            'room': '-'
        })
    
    # Par salle
    for room_data in rooms_data:
        room_id = room_data.get('room_id')
        count = room_data.get('count', 1)
        
        room = Room.query.get(room_id)
        if not room:
            continue
        
        # Groupe salle
        level = 1 if create_parent else 0
        preview.append({
            'level': level,
            'name': f"{category.name} {room.name}",
            'type': 'Groupe salle',
            'lot': lot.name if lot else '-',
            'category': category.name if category else '-',
            'room': room.name
        })
        
        # Individuels
        if tracked_individually:
            for i in range(1, count + 1):
                preview.append({
                    'level': level + 1,
                    'name': f"{category.name} {i}",
                    'type': 'Individuel',
                    'lot': '(hérité)',
                    'category': '(hérité)',
                    'room': room.name
                })
    
    return jsonify({
        'preview': preview,
        'total': len(preview)
    })
