"""Outlook Auth Routes - GMAO Collège"""
from flask import Blueprint, render_template, redirect, url_for, request, flash, jsonify, send_file
from flask_login import login_required, current_user
from app_new.extensions import db
from ..outlook.models import OutlookAccount, OutlookMail, OutlookFolder, OutlookAttachment, OutlookMailInterpretation, GmaoContext
import os
import subprocess
import json
import tempfile

auth_bp = Blueprint('outlook_auth', __name__, template_folder='templates')

# ─── API OAuth2 ───────────────────────────────────────────────────────────

@auth_bp.route('/api/start-auth', methods=['POST'])
@login_required
def api_start_auth():
    """Démarre le processus d'authentification OAuth2."""
    import requests
    from datetime import datetime, timezone, timedelta
    
    email = request.json.get('email')
    if not email:
        return jsonify({'error': 'Email requis'}), 400
    
    # Constantes OAuth2
    CLIENT_ID = "9199bf20-a13f-4107-85dc-02114787ef48"
    SCOPES = "https://outlook.office365.com/Mail.ReadWrite https://outlook.office365.com/Mail.Send offline_access"
    
    # Vérifier si le compte existe déjà — si oui, le supprimer pour re-authentifier
    existing = OutlookAccount.query.filter_by(email=email, user_id=current_user.id).first()
    if existing:
        # Supprimer les données associées puis le compte
        from app_new.outlook.models import OutlookMail, OutlookFolder
        OutlookMail.query.filter_by(account_id=existing.id).delete()
        OutlookFolder.query.filter_by(account_id=existing.id).delete()
        db.session.delete(existing)
        db.session.commit()
    
    try:
        # Découvrir le tenant ID
        domain = email.split('@')[1]
        discovery_url = f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration"
        resp = requests.get(discovery_url, timeout=10)
        tenant_id = resp.json().get('token_endpoint', '').split('/')[3] if resp.status_code == 200 else "befa6ca1-bada-43da-958c-cafc3c57ec70"
        
        # Demander le device code
        token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/devicecode"
        dev_resp = requests.post(token_url, data={'client_id': CLIENT_ID, 'scope': SCOPES})
        if dev_resp.status_code != 200:
            return jsonify({'error': 'Erreur de configuration OAuth2'}), 500
        
        device_data = dev_resp.json()
        
        # Créer le compte en attente
        account = OutlookAccount(
            user_id=current_user.id,
            email=email,
            tenant_id=tenant_id,
            refresh_token='',
            device_code=device_data.get('device_code'),
            user_code=device_data.get('user_code'),
            connection_status='pending',
            device_code_expires_at=datetime.now(timezone.utc) + timedelta(minutes=device_data.get('expires_in', 900))
        )
        db.session.add(account)
        db.session.commit()
        
        return jsonify({
            'verification_uri': device_data.get('verification_uri'),
            'user_code': device_data.get('user_code'),
            'expires_in': device_data.get('expires_in'),
            'account_id': account.id
        })
        
    except Exception as e:
        return jsonify({'error': f'Erreur: {str(e)}'}), 500


@auth_bp.route('/api/poll-auth/<int:account_id>', methods=['POST'])
@login_required
def api_poll_auth(account_id):
    """Polling pour vérifier si l'authentification est terminée."""
    import requests
    from datetime import datetime, timezone
    
    account = OutlookAccount.query.get(account_id)
    if not account or account.user_id != current_user.id:
        return jsonify({'error': 'Compte non trouvé'}), 404
    
    if not account.device_code:
        return jsonify({'error': 'Device code non trouvé'}), 400
    
    # Vérifier si le device code a expiré
    expires_at = account.device_code_expires_at
    if expires_at:
        if expires_at.tzinfo is None:
            expires_at = expires_at.replace(tzinfo=timezone.utc)
        if expires_at < datetime.now(timezone.utc):
            db.session.delete(account)
            db.session.commit()
            return jsonify({'error': 'Code expiré, veuillez recommencer', 'expired': True}), 400
    
    CLIENT_ID = "9199bf20-a13f-4107-85dc-02114787ef48"
    
    try:
        # Polling Microsoft pour le token
        token_url = f"https://login.microsoftonline.com/{account.tenant_id}/oauth2/v2.0/token"
        resp = requests.post(token_url, data={
            'client_id': CLIENT_ID,
            'grant_type': 'urn:ietf:params:oauth:grant-type:device_code',
            'device_code': account.device_code
        })
        
        data = resp.json()
        
        if resp.status_code == 200 and 'refresh_token' in data:
            # Succès - sauvegarder le refresh token
            from cryptography.fernet import Fernet
            import os
            
            key = os.environ.get('OUTLOOK_ENCRYPTION_KEY', Fernet.generate_key())
            cipher = Fernet(key if isinstance(key, bytes) else key.encode())
            
            account.refresh_token = cipher.encrypt(data['refresh_token'].encode()).decode()
            account.connection_status = 'active'
            account.last_connected_at = datetime.now(timezone.utc)
            account.device_code = None
            account.user_code = None
            account.device_code_expires_at = None
            account.is_active = True
            
            db.session.commit()
            
            return jsonify({
                'success': True,
                'message': 'Authentification réussie',
                'account_id': account.id
            })
        
        if data.get('error') == 'authorization_pending':
            return jsonify({'pending': True, 'message': "En attente de l'autorisation"})
        
        return jsonify({'error': data.get('error_description', data.get('error', 'Erreur inconnue'))}), 400
        
    except Exception as e:
        return jsonify({'error': f'Erreur: {str(e)}'}), 500


# ─── API Synchronisation ───────────────────────────────────────────────────

def get_access_token(account):
    """Obtient un access_token à partir du refresh_token."""
    import requests
    from cryptography.fernet import Fernet
    import os
    
    if not account.refresh_token:
        return None, "Aucun token d'authentification"
    
    key = os.environ.get('OUTLOOK_ENCRYPTION_KEY')
    if not key:
        return None, "Clé de chiffrement non configurée"
    
    cipher = Fernet(key if isinstance(key, bytes) else key.encode())
    refresh_token = cipher.decrypt(account.refresh_token.encode()).decode()
    
    CLIENT_ID = "9199bf20-a13f-4107-85dc-02114787ef48"
    token_url = f"https://login.microsoftonline.com/{account.tenant_id}/oauth2/v2.0/token"
    
    resp = requests.post(token_url, data={
        'client_id': CLIENT_ID,
        'grant_type': 'refresh_token',
        'refresh_token': refresh_token,
        'scope': 'https://outlook.office365.com/Mail.ReadWrite https://outlook.office365.com/Mail.Send offline_access'
    })
    
    if resp.status_code != 200:
        return None, f"Erreur d'authentification: {resp.json().get('error_description', resp.text)}"
    
    return resp.json().get('access_token'), None


