# Fichier: blueprints/audit.py (VERSION CORRIGÉE - CHECKBOXES)

from flask import Blueprint, render_template, request, redirect, url_for, flash, current_app, send_file, abort
from flask_login import login_required, current_user
import json
import uuid as uuid_lib
from datetime import datetime, timezone, timedelta

# Importations
from extensions import db, limiter
from models import Rapport, User
from services.scoring_service import calculer_cybernote_et_rapport
from decorators import audit_permission_required

audit = Blueprint('audit', __name__, template_folder='../templates')

# ========================================================================
# FONCTIONS UTILITAIRES
# ========================================================================

def validate_uuid(uuid_string):
    """Valide qu'une chaîne est un UUID valide (défense en profondeur)."""
    try:
        uuid_lib.UUID(uuid_string, version=4)
        return True
    except (ValueError, AttributeError, TypeError):
        return False

# ========================================================================
# ROUTES DE CRÉATION ET LECTURE
# ========================================================================

@audit.route("/nouveau_audit", methods=['GET', 'POST']) 
@login_required
@audit_permission_required
@limiter.limit("100 per hour")
def nouveau_audit():
    """Affiche le formulaire du questionnaire d'audit et gère sa soumission."""
    
    if request.method == 'POST':
        # 1. Validation du nom client
        nom_client = request.form.get('nom_client', '').strip()
        
        if not nom_client:
            flash("Le nom de l'entreprise/client est requis.", 'danger')
            return render_template('questionnaire.html'), 400
        
        if len(nom_client) > 150:
            flash("Le nom de l'entreprise ne peut pas dépasser 150 caractères.", 'danger')
            return render_template('questionnaire.html'), 400
        
        # 2. Vérification anti-doublon (optionnel)
        recent_cutoff = datetime.now(timezone.utc) - timedelta(minutes=5)
        existing = Rapport.query.filter(
            Rapport.user_id == current_user.id,
            Rapport.nom_client == nom_client,
            Rapport.date_creation >= recent_cutoff
        ).first()
        
        if existing:
            flash(f"⚠️ Vous avez déjà créé un rapport pour '{nom_client}' il y a moins de 5 minutes.", 'warning')
        
        # ========================================================================
        # 3. Nettoyage et Calcul - ✅ CORRIGÉ : PRÉSERVE LES LISTES
        # ========================================================================
        
        form_data = {}
        
        # Récupérer les champs simples
        for key, value in request.form.items():
            if key not in ['q_sauvegarde_types', 'q_frequence', 'q_os_postes', 'q_os_serveurs']:
                form_data[key] = value
        
        # ✅ Récupérer les checkboxes (arrays)
        form_data['q_sauvegarde_types'] = request.form.getlist('q_sauvegarde_types')
        form_data['q_frequence'] = request.form.getlist('q_frequence')
        form_data['q_os_postes'] = request.form.getlist('q_os_postes')
        form_data['q_os_serveurs'] = request.form.getlist('q_os_serveurs')
        
        # ✅ SANITIZE UNIQUEMENT LES STRINGS (pas les listes)
        sanitized_data = {}
        for key, value in form_data.items():
            if isinstance(value, list):
                # Les listes restent intactes (déjà validées par getlist())
                sanitized_data[key] = value
            elif isinstance(value, str):
                # Tronquer les strings
                sanitized_data[key] = value[:500]
            elif isinstance(value, (int, float)):
                # Les nombres restent intacts
                sanitized_data[key] = value
            else:
                # Autres types convertis en string
                sanitized_data[key] = str(value)[:500]
        
        form_data = sanitized_data
        
        # ========================================================================
        # 4. Calcul du score
        # ========================================================================
        
        try:
            score_total, preconisations_data = calculer_cybernote_et_rapport(form_data)
            score_total = max(0, min(100, score_total))
        except Exception as e:
            current_app.logger.error(f"Erreur calcul Cybernote user {current_user.id}: {e}", exc_info=True)
            flash("Erreur interne lors du calcul. Veuillez réessayer.", 'danger')
            return redirect(url_for('main.dashboard'))

        # Création du rapport (L'ID UUID est généré automatiquement par le modèle)
        nouvel_audit = Rapport(
            user_id=current_user.id,
            nom_client=nom_client,
            score_total=score_total,
            date_creation=datetime.now(timezone.utc),
            raw_data=json.dumps(form_data),
            preconisations_json=json.dumps(preconisations_data)
        )
        
        try:
            db.session.add(nouvel_audit)
            db.session.commit()
            
            current_app.logger.info(f"Rapport créé: {nouvel_audit.id} par user {current_user.id}")
            
            # ✅ LOG ACTIVITÉ
            from services.logger_service import log_report_created
            log_report_created(current_user.id, nouvel_audit.id, nom_client, score_total)
            
            flash(f"✅ Cybernote calculée ! Score : {score_total}/100.", 'success')
            return redirect(url_for('audit.rapport_detail', rapport_id=nouvel_audit.id))
        
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Erreur DB save rapport user {current_user.id}: {e}", exc_info=True)
            
            # ✅ LOG ERREUR
            from services.logger_service import log_db_error
            log_db_error('REPORT', 'REPORT_CREATED', f"Échec création rapport pour {nom_client}", e)
            
            flash("Erreur lors de l'enregistrement. Veuillez réessayer.", 'danger')
            return redirect(url_for('main.dashboard'))

    return render_template('questionnaire.html')


@audit.route("/rapport/<string:rapport_id>")
@login_required
def rapport_detail(rapport_id):
    """Affiche les détails et les préconisations d'un rapport spécifique."""
    
    # Validation UUID (défense en profondeur)
    if not validate_uuid(rapport_id):
        current_app.logger.warning(f"UUID invalide tenté: {rapport_id} par user {current_user.id}")
        abort(404)
    
    rapport = Rapport.query.get_or_404(rapport_id)
    
    # CONTRÔLE D'ACCÈS
    is_owner = (rapport.user_id == current_user.id)
    is_manager = (getattr(current_user, 'role', '') == 'manager' and 
                  getattr(rapport.auteur, 'manager_id', None) == current_user.id)
    is_admin = (getattr(current_user, 'role', '') == 'admin')
    
    if not (is_owner or is_manager or is_admin):
        current_app.logger.warning(
            f"Accès refusé rapport {rapport_id}: user {current_user.id} (role: {current_user.role})"
        )
        flash("Vous n'avez pas l'autorisation d'accéder à ce rapport.", 'danger')
        abort(403)
    
    try:
        if rapport.preconisations_json:
            data_json = json.loads(rapport.preconisations_json)
            scores_blocs = data_json.get('detail_scores', {})
            preconisations_finales = data_json.get('preconisations_detail', [])
        else:
            scores_blocs = {}
            preconisations_finales = []
        max_score = 100
        
    except (json.JSONDecodeError, TypeError) as e:
        current_app.logger.error(f"Erreur data rapport {rapport_id}: {e}", exc_info=True)
        flash(f"Données du rapport corrompues.", 'danger')
        scores_blocs = {}
        preconisations_finales = []
        max_score = 100

    return render_template(
        'rapport.html', 
        rapport=rapport,
        max_score=max_score,
        scores_blocs=scores_blocs,
        preconisations_finales=preconisations_finales
    )

# ========================================================================
# SUPPRESSION ET EXPORT
# ========================================================================

@audit.route("/rapport/delete/<string:rapport_id>", methods=['POST'])
@login_required
def delete_rapport(rapport_id):
    """Supprime un rapport d'audit (CSRF protégé)."""
    
    # Validation UUID
    if not validate_uuid(rapport_id):
        current_app.logger.warning(f"UUID invalide tenté: {rapport_id} par user {current_user.id}")
        abort(404)
    
    rapport = Rapport.query.get_or_404(rapport_id)
    
    # CONTRÔLE D'ACCÈS
    is_owner = (rapport.user_id == current_user.id)
    is_admin = (getattr(current_user, 'role', '') == 'admin')

    if not (is_owner or is_admin):
        current_app.logger.warning(
            f"Tentative suppression non autorisée rapport {rapport_id}: user {current_user.id}"
        )
        flash("Action non autorisée.", 'danger')
        abort(403)

    owner_id = rapport.user_id
    nom_client = rapport.nom_client

    try:
        db.session.delete(rapport)
        db.session.commit()
        current_app.logger.info(f"Rapport {rapport_id} supprimé par user {current_user.id}")
        
        # ✅ LOG ACTIVITÉ
        from services.logger_service import log_report_deleted
        log_report_deleted(current_user.id, nom_client)
        
        flash(f'✅ Rapport "{nom_client}" supprimé.', 'success')
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Erreur suppression rapport {rapport_id}: {e}", exc_info=True)
        
        # ✅ LOG ERREUR
        from services.logger_service import log_db_error
        log_db_error('REPORT', 'REPORT_DELETED', f"Échec suppression rapport {rapport_id}", e)
        
        flash('Erreur technique lors de la suppression.', 'danger')
        return redirect(request.referrer or url_for('main.dashboard'))

    # REDIRECTION INTELLIGENTE
    if is_admin and not is_owner:
        return redirect(url_for('admin.admin_user_detail', user_id=owner_id))
    else:
        return redirect(url_for('main.dashboard'))


@audit.route("/rapport/<string:rapport_id>/pdf")
@login_required
@limiter.limit("100 per hour")
def rapport_pdf(rapport_id):
    """Génère et télécharge le rapport au format PDF."""
    
    # Validation UUID
    if not validate_uuid(rapport_id):
        current_app.logger.warning(f"UUID invalide tenté PDF: {rapport_id} par user {current_user.id}")
        abort(404)
    
    rapport = Rapport.query.get_or_404(rapport_id)
    
    # CONTRÔLE D'ACCÈS
    is_owner = (rapport.user_id == current_user.id)
    is_manager = (getattr(current_user, 'role', '') == 'manager' and 
                  getattr(rapport.auteur, 'manager_id', None) == current_user.id)
    is_admin = (getattr(current_user, 'role', '') == 'admin')
    
    if not (is_owner or is_manager or is_admin):
        current_app.logger.warning(
            f"Accès refusé PDF rapport {rapport_id}: user {current_user.id}"
        )
        abort(403)
    
    try:
        # Extraction et préparation des données
        if rapport.preconisations_json:
            data_json = json.loads(rapport.preconisations_json)
            raw_scores = data_json.get('detail_scores', {})
            preconisations_finales = data_json.get('preconisations_detail', [])
        else:
            raw_scores = {}
            preconisations_finales = []

        donnees_formulaire = json.loads(rapport.raw_data) if rapport.raw_data else {}
        
        scores_blocs = {}
        for k, v in raw_scores.items():
            if v is None: 
                scores_blocs[k] = None
            else:
                try: 
                    scores_blocs[k] = float(v)
                except: 
                    scores_blocs[k] = 0.0

        from services.pdf_service import generer_pdf_rapport
        pdf_buffer = generer_pdf_rapport(rapport, scores_blocs, preconisations_finales, donnees_formulaire)
        
        # NOM DE FICHIER OPTIMISÉ AVEC SHORT ID
        safe_client_name = "".join([c for c in rapport.nom_client if c.isalnum() or c in (' ', '-', '_')]).strip().replace(' ', '_')
        short_id = str(rapport.id)[:8]  # Les 8 premiers chars de l'UUID
        
        filename = f"Rapport_{safe_client_name}_{short_id}.pdf"
        
        response = send_file(
            pdf_buffer,
            mimetype='application/pdf',
            as_attachment=True,
            download_name=filename
        )
        
        response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
        
        current_app.logger.info(f"PDF généré rapport {rapport_id} par user {current_user.id}")
        
        # ✅ LOG ACTIVITÉ
        from services.logger_service import log_pdf_downloaded
        log_pdf_downloaded(current_user.id, rapport_id, rapport.nom_client)
        
        return response
        
    except Exception as e:
        current_app.logger.error(f"Erreur PDF rapport {rapport_id}: {e}", exc_info=True)
        
        # ✅ LOG ERREUR
        from services.logger_service import log_pdf_error
        log_pdf_error(current_user.id, rapport_id, e)
        
        flash("Erreur lors de la génération du PDF.", 'danger')
        return redirect(url_for('audit.rapport_detail', rapport_id=rapport_id))