"""
Application web Flask pour le dashboard de monitoring des sauvegardes
"""
from flask import Flask, render_template, jsonify, request
from flask_cors import CORS
from datetime import datetime, timedelta, timezone
import logging
import json

from database import BackupDatabase
from mail_reader import MailReader
from mail_analyzer import BackupAnalyzer
from config import WEB_CONFIG, MONITORING_CONFIG

# Configuration du logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialisation Flask
app = Flask(__name__)
app.config['SECRET_KEY'] = WEB_CONFIG['secret_key']
CORS(app)

# Instances des modules
db = BackupDatabase()
mail_reader = MailReader()
analyzer = BackupAnalyzer()

# ============================================================================
# ROUTES HTML
# ============================================================================

@app.route('/')
def index():
    """Page d'accueil - Dashboard principal"""
    return render_template('dashboard.html')

@app.route('/backup/<backup_name>')
def backup_detail(backup_name):
    """Page de détails d'une sauvegarde spécifique"""
    return render_template('backup_detail.html', backup_name=backup_name)

@app.route('/history')
def history():
    """Page d'historique complet"""
    return render_template('history.html')

@app.route('/alerts')
def alerts():
    """Page des alertes"""
    return render_template('alerts.html')

# ============================================================================
# API ENDPOINTS
# ============================================================================

@app.route('/api/status')
def api_status():
    """Statut global du système"""
    try:
        stats = db.get_statistics(days=7)
        latest = db.get_latest_backups()
        missing = db.check_missing_backups()
        failed = db.get_failed_backups(hours=24)
        
        # Calculer le statut global
        critical_issues = len(missing) + len([f for f in failed if is_critical_failure(f)])
        
        if critical_issues > 0:
            status = 'critical'
        elif len(failed) > 0:
            status = 'warning'
        else:
            status = 'healthy'
        
        return jsonify({
            'status': status,
            'last_update': datetime.now(timezone.utc).isoformat(),
            'statistics': {
                'total': stats.get('total', 0),
                'success_rate': round(stats.get('success_rate', 0), 1),
                'unique_backups': stats.get('unique_backups', 0),
                'by_status': stats.get('by_status', {}),
                'by_type': stats.get('by_type', {})
            },
            'issues': {
                'missing': len(missing),
                'failed': len(failed),
                'critical': critical_issues
            }
        })
    except Exception as e:
        logger.error(f"Erreur API status: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/backups/latest')
def api_latest_backups():
    """Liste des dernières sauvegardes par nom"""
    try:
        backups = db.get_latest_backups()
        
        # Filtrer RS1221-02 (le NAS qui fait les sauvegardes)
        backups = [b for b in backups if 'RS1221-02' not in b['backup_name']]
        
        # Enrichir avec l'âge
        for backup in backups:
            backup['age_hours'] = calculate_age_hours(backup['received_date'])
            backup['status_icon'] = get_status_icon(backup)
            backup['is_old'] = backup['age_hours'] > MONITORING_CONFIG['alert_threshold_hours']
        
        # Trier par statut (échecs en premier) puis par date
        backups.sort(key=lambda x: (
            0 if x['status'] == 'failure' else 1 if x['is_old'] else 2,
            x['received_date']
        ), reverse=True)
        
        return jsonify({
            'backups': backups,
            'total': len(backups),
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API latest backups: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/backups/all-recent')
def api_all_recent_backups():
    """NOUVEAU: Liste de TOUTES les sauvegardes des 3 derniers jours"""
    try:
        days = request.args.get('days', 3, type=int)
        
        # Récupérer TOUTES les sauvegardes des X derniers jours
        all_backups = db.get_all_recent_backups(days=days)
        
        # Filtrer RS1221-02 (le NAS qui fait les sauvegardes)
        all_backups = [b for b in all_backups if 'RS1221-02' not in b['backup_name']]
        
        # Enrichir avec l'âge
        for backup in all_backups:
            backup['age_hours'] = calculate_age_hours(backup['received_date'])
            backup['status_icon'] = get_status_icon(backup)
            backup['is_old'] = backup['age_hours'] > MONITORING_CONFIG['alert_threshold_hours']
        
        # Trier par date décroissante (plus récent en premier)
        all_backups.sort(key=lambda x: x['received_date'], reverse=True)
        
        return jsonify({
            'backups': all_backups,
            'total': len(all_backups),
            'days': days,
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API all recent backups: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/backups/history/<backup_name>')
def api_backup_history(backup_name):
    """Historique d'une sauvegarde spécifique"""
    try:
        days = request.args.get('days', 30, type=int)
        history = db.get_backup_history(backup_name, days=days)
        
        # Calculer les statistiques
        total = len(history)
        success = sum(1 for b in history if b['status'] == 'success')
        failure = sum(1 for b in history if b['status'] == 'failure')
        success_rate = (success / total * 100) if total > 0 else 0
        
        # Préparer les données pour les graphiques
        daily_stats = calculate_daily_stats(history)
        
        return jsonify({
            'backup_name': backup_name,
            'history': history,
            'statistics': {
                'total': total,
                'success': success,
                'failure': failure,
                'success_rate': round(success_rate, 1)
            },
            'daily_stats': daily_stats
        })
    except Exception as e:
        logger.error(f"Erreur API backup history: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/missing')
def api_missing_backups():
    """Sauvegardes manquantes"""
    try:
        missing = db.check_missing_backups()
        
        # Convertir en liste et enrichir
        missing_list = []
        for name, info in missing.items():
            # Filtrer RS1221-02
            if 'RS1221-02' in name:
                continue
                
            missing_list.append({
                'backup_name': name,
                'type': info['type'],
                'last_seen': info['last_seen'],
                'hours_ago': info['hours_ago'],
                'last_status': info['last_status'],
                'severity': 'critical' if info['hours_ago'] > 72 else 'warning'
            })
        
        # Trier par ancienneté
        missing_list.sort(key=lambda x: x['hours_ago'], reverse=True)
        
        return jsonify({
            'missing': missing_list,
            'count': len(missing_list),
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API missing: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/failed')
def api_failed_backups():
    """Sauvegardes en échec récentes"""
    try:
        hours = request.args.get('hours', 48, type=int)
        failed = db.get_failed_backups(hours=hours)
        
        # Filtrer RS1221-02
        failed = [f for f in failed if 'RS1221-02' not in f['backup_name']]
        
        # Enrichir avec des infos supplémentaires
        for backup in failed:
            backup['age_hours'] = calculate_age_hours(backup['received_date'])
            backup['is_critical'] = is_critical_failure(backup)
        
        return jsonify({
            'failed': failed,
            'count': len(failed),
            'hours': hours,
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API failed: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/statistics')
def api_statistics():
    """Statistiques détaillées"""
    try:
        days = request.args.get('days', 30, type=int)
        stats = db.get_statistics(days=days)
        
        return jsonify({
            'period_days': days,
            'statistics': stats,
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API statistics: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/refresh')
def api_refresh():
    """Force un rafraîchissement des données depuis les emails"""
    try:
        logger.info("Rafraîchissement des données demandé...")
        
        # Récupérer les emails récents
        emails = mail_reader.get_recent_emails(hours=48, sender_filter=None)
        
        # Analyser
        analyzed = []
        for email in emails:
            info = analyzer.extract_backup_info(email)
            if info and 'RS1221-02' not in info['backup_name']:  # Filtrer RS1221-02
                analyzed.append(info)
                db.insert_backup_record(info)
        
        logger.info(f"Rafraîchi {len(analyzed)} sauvegardes")
        
        return jsonify({
            'success': True,
            'processed': len(analyzed),
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API refresh: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/types')
def api_backup_types():
    """Liste des types de sauvegardes avec compteurs"""
    try:
        backups = db.get_latest_backups()
        
        # Filtrer RS1221-02
        backups = [b for b in backups if 'RS1221-02' not in b['backup_name']]
        
        # Grouper par type
        by_type = {}
        for backup in backups:
            btype = backup['backup_type']
            if btype not in by_type:
                by_type[btype] = {
                    'count': 0,
                    'success': 0,
                    'failure': 0,
                    'old': 0
                }
            
            by_type[btype]['count'] += 1
            if backup['status'] == 'success':
                by_type[btype]['success'] += 1
            elif backup['status'] == 'failure':
                by_type[btype]['failure'] += 1
            
            age = calculate_age_hours(backup['received_date'])
            if age > MONITORING_CONFIG['alert_threshold_hours']:
                by_type[btype]['old'] += 1
        
        return jsonify({
            'types': by_type,
            'timestamp': datetime.now(timezone.utc).isoformat()
        })
    except Exception as e:
        logger.error(f"Erreur API types: {e}")
        return jsonify({'error': str(e)}), 500

# ============================================================================
# FONCTIONS UTILITAIRES
# ============================================================================

def calculate_age_hours(date_str):
    """Calcule l'âge en heures depuis maintenant"""
    try:
        date = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
        now = datetime.now(timezone.utc)
        delta = now - date
        return round(delta.total_seconds() / 3600, 1)
    except:
        return 0

def get_status_icon(backup):
    """Retourne l'icône selon le statut"""
    if backup['status'] == 'success':
        return '✓'
    elif backup['status'] == 'failure':
        return '✗'
    else:
        return '?'

def is_critical_failure(backup):
    """Détermine si un échec est critique"""
    # Échec récent (< 2h) = critique
    age = calculate_age_hours(backup['received_date'])
    return age < 2

def calculate_daily_stats(history):
    """Calcule les stats journalières pour graphiques"""
    daily = {}
    
    for backup in history:
        try:
            date = datetime.fromisoformat(backup['received_date'].replace('Z', '+00:00'))
            day = date.strftime('%Y-%m-%d')
            
            if day not in daily:
                daily[day] = {'success': 0, 'failure': 0, 'total': 0}
            
            daily[day]['total'] += 1
            if backup['status'] == 'success':
                daily[day]['success'] += 1
            elif backup['status'] == 'failure':
                daily[day]['failure'] += 1
        except:
            continue
    
    # Convertir en liste triée
    result = []
    for day in sorted(daily.keys()):
        result.append({
            'date': day,
            **daily[day],
            'success_rate': round(daily[day]['success'] / daily[day]['total'] * 100, 1) if daily[day]['total'] > 0 else 0
        })
    
    return result

# ============================================================================
# ERROR HANDLERS
# ============================================================================

@app.errorhandler(404)
def not_found(error):
    return jsonify({'error': 'Not found'}), 404

@app.errorhandler(500)
def internal_error(error):
    return jsonify({'error': 'Internal server error'}), 500

# ============================================================================
# MAIN
# ============================================================================

if __name__ == '__main__':
    logger.info("=== Démarrage du serveur web ===")
    logger.info(f"Interface disponible sur http://{WEB_CONFIG['host']}:{WEB_CONFIG['port']}")
    
    app.run(
        host=WEB_CONFIG['host'],
        port=WEB_CONFIG['port'],
        debug=WEB_CONFIG['debug']
    )