from flask import Blueprint, render_template, request, jsonify, make_response
from flask_login import login_required, current_user
from app import db
from app.models import Folder, AIRuleCache
from app.ai_service import AIService
from datetime import datetime, timedelta
import logging
import json

# Initialize the AI service instance
ai_service = AIService()

folders_bp = Blueprint('folders', __name__)

@folders_bp.route('/')
@login_required
def index():
    """Main page showing all folders."""
    # Get folders for the current authenticated user
    folders = Folder.query.filter_by(user_id=current_user.id).all()
    
    return render_template('index.html',
                          folders=folders,
                          show_hidden=False)

@folders_bp.route('/api/folders/new', methods=['GET'])
@login_required
def new_folder_modal():
    """Return the add folder modal."""
    response = make_response(render_template('partials/folder_modal.html', folder_data={'rule_text': folder.rule_text,
                                                               'show_ai_rules': True,
                                                              'errors': None }))
    response.headers['HX-Trigger'] = 'open-modal'
    return response

@folders_bp.route('/api/folders', methods=['POST'])
@login_required
def add_folder():
    """Add a new folder."""
    try:
        # Get form data instead of JSON
        name = request.form.get('name')
        rule_text = request.form.get('rule_text')
        priority = request.form.get('priority')
        
        # Server-side validation
        errors = {}
        if not name or not name.strip():
            errors['name'] = 'Folder name is required'
        elif len(name.strip()) < 3:
            errors['name'] = 'Folder name must be at least 3 characters'
        elif len(name.strip()) > 50:
            errors['name'] = 'Folder name must be less than 50 characters'
            
        if not rule_text or not rule_text.strip():
            errors['rule_text'] = 'Rule text is required'
        elif len(rule_text.strip()) < 10:
            errors['rule_text'] = 'Rule text must be at least 10 characters'
        elif len(rule_text.strip()) > 200:
            errors['rule_text'] = 'Rule text must be less than 200 characters'
            
        # If there are validation errors, return the modal with errors
        if errors:
            response = make_response(render_template('partials/folder_modal.html', errors=errors, name=name, rule_text=rule_text, priority=priority, 
                                                     folder_data={'rule_text': '',
                                                               'show_ai_rules': True,
                                                              'errors': None }))
            response.headers['HX-Retarget'] = '#folder-modal'
            response.headers['HX-Reswap'] = 'outerHTML'
            return response
            
        # Create new folder for the current user
        # Default to 'destination' type for manually created folders
        folder_type = 'tidy' if name.strip().lower() == 'inbox' else 'destination'
        
        # If folder_type is 'ignore', reset emails_count to 0
        if folder_type == 'ignore':
            emails_count = 0
        
        folder = Folder(
            user_id=current_user.id,
            name=name.strip(),
            rule_text=rule_text.strip(),
            priority=int(priority) if priority else 0,
            folder_type=folder_type,
            emails_count=0 if folder_type == 'ignore' else None
        )
        
        db.session.add(folder)
        db.session.commit()
        
        response = make_response('')
        response.headers['HX-Trigger'] = 'close-modal, folder-list-invalidated'
        response.status_code = 201
        return response
        
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error adding folder: %s", e)
        db.session.rollback()
        # Return error in modal
        errors = {'general': 'An unexpected error occurred. Please try again.'}
        # Get updated lists of folders by type for error fallback
        
        response = make_response(render_template('partials/folder_modal.html', errors=errors, name=name, rule_text=rule_text, priority=priority))
        response.headers['HX-Retarget'] = '#folder-modal'
        response.headers['HX-Reswap'] = 'outerHTML'
        return response

@folders_bp.route('/api/folders/<folder_id>', methods=['DELETE'])
@login_required
def delete_folder(folder_id):
    """Delete a folder."""
    try:
        # Find the folder by ID and ensure it belongs to the current user
        folder = Folder.query.filter_by(id=folder_id, user_id=current_user.id).first()
        
        if not folder:
            # Folder not found
            response = make_response('')
            response.headers['HX-Trigger'] = 'folder-list-invalidated'
            return response
            
        # Delete all associated processed emails first
        from app.models import ProcessedEmail
        ProcessedEmail.query.filter_by(folder_id=folder.id).delete()
        
        # Delete the folder
        db.session.delete(folder)
        db.session.commit()
        
        response = make_response('')
        response.headers['HX-Trigger'] = 'folder-list-invalidated'
        return response
        
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error deleting folder: %s", e)
        db.session.rollback()
        # Return the folders list unchanged
        response = make_response('')
        response.headers['HX-Trigger'] = 'folder-list-invalidated'
        return response

@folders_bp.route('/api/folders/<folder_id>/type', methods=['PUT'])
@login_required
def update_folder_type(folder_id):
    """Update the type of a folder."""
    try:
        # Find the folder by ID and ensure it belongs to the current user
        folder = Folder.query.filter_by(id=folder_id, user_id=current_user.id).first()
        
        if not folder:
            return jsonify({'error': 'Folder not found'}), 404
            
        # Get the new folder type from form data
        new_folder_type = request.form.get('folder_type')
        
        # Validate the folder type
        if new_folder_type not in ['tidy', 'destination', 'ignore']:
            return jsonify({'error': 'Invalid folder type'}), 400
            
        # If changing to 'ignore', reset the emails_count to 0
        if new_folder_type == 'ignore' and folder.folder_type != 'ignore':
            folder.emails_count = 0
        
        # Update the folder type
        folder.folder_type = new_folder_type
        
        db.session.commit()
        
        response = make_response('')
        response.headers['HX-Trigger'] = 'folder-list-invalidated'
        return response
        
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error updating folder type: %s", e)
        db.session.rollback()
        return jsonify({'error': 'An unexpected error occurred'}), 500

@folders_bp.route('/api/folders/<folder_id>/edit', methods=['GET'])
@login_required
def edit_folder_modal(folder_id):
    """Return the edit folder modal with folder data."""
    try:
        # Find the folder by ID and ensure it belongs to the current user
        folder = Folder.query.filter_by(id=folder_id, user_id=current_user.id).first()
        
        if not folder:
            return jsonify({'error': 'Folder not found'}), 404
            
        # Return the edit folder modal with folder data
        response = make_response(render_template('partials/folder_modal.html', folder=folder,
                                                 folder_data={'rule_text': folder.rule_text,
                                                               'show_ai_rules': True,
                                                              'errors': None }))
        response.headers['HX-Trigger'] = 'open-modal'
        return response
        
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error getting folder for edit: %s", e)
        return jsonify({'error': 'Error retrieving folder'}), 500

@folders_bp.route('/api/folders/<folder_id>', methods=['PUT'])
@login_required
def update_folder(folder_id):
    """Update an existing folder."""
    try:
        # Find the folder by ID and ensure it belongs to the current user
        folder = Folder.query.filter_by(id=folder_id, user_id=current_user.id).first()
        
        if not folder:
            # Folder not found
            response = make_response('')
            response.headers['HX-Trigger'] = 'close-modal, folder-list-invalidated'
            return response
 
        # Get form data
        name = request.form.get('name')
        rule_text = request.form.get('rule_text')
        priority = request.form.get('priority')
        
        # Server-side validation
        errors = {}
        if not name or not name.strip():
            errors['name'] = 'Folder name is required'
        elif len(name.strip()) < 3:
            errors['name'] = 'Folder name must be at least 3 characters'
        elif len(name.strip()) > 50:
            errors['name'] = 'Folder name must be less than 50 characters'
            
        if not rule_text or not rule_text.strip():
            errors['rule_text'] = 'Rule text is required'
        elif len(rule_text.strip()) < 10:
            errors['rule_text'] = 'Rule text must be at least 10 characters'
        elif len(rule_text.strip()) > 200:
            errors['rule_text'] = 'Rule text must be less than 200 characters'
            
        # If there are validation errors, return the modal with errors
        if errors:
            response = make_response(render_template('partials/folder_modal.html', folder=folder, errors=errors, name=name, rule_text=rule_text, priority=priority,
                                                     folder_data={'rule_text': folder.rule_text,
                                                               'show_ai_rules': True,
                                                              'errors': None }))
            return response
    
        # Update folder
        folder.name = name.strip()
        folder.rule_text = rule_text.strip()
        folder.priority = int(priority) if priority else 0
        
        # Check if folder type is being changed to 'ignore'
        old_folder_type = folder.folder_type
        folder.folder_type = 'tidy' if name.strip().lower() == 'inbox' else 'destination'
        
        # If changing to 'ignore', reset emails_count to 0
        if folder.folder_type == 'ignore' and old_folder_type != 'ignore':
            folder.emails_count = 0
        
        db.session.commit()
        
        response = make_response('')
        response.headers['HX-Trigger'] = 'close-modal, folder-list-invalidated'
        return response
        
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error updating folder: %s", e)
        db.session.rollback()
        # Return error in modal
        errors = {'general': 'An unexpected error occurred. Please try again.'}
        response = make_response(render_template('partials/folder_modal.html', folder=folder, errors=errors, name=name, rule_text=rule_text, priority=priority,
                                                 folder_data={'rule_text': folder.rule_text,
                                                               'show_ai_rules': True,
                                                              'errors': None }))
        response.headers['HX-Retarget'] = '#folder-modal'
        response.headers['HX-Reswap'] = 'outerHTML'
        return response

@folders_bp.route('/api/folders', methods=['GET'])
@login_required
def get_folders():
    """Get folders with optional filtering."""
    # Check if this is an event-triggered request
    is_event_triggered = request.headers.get('HX-Trigger') == 'folder-list-invalidated'
    
    # Get filter parameter from query string
    filter_type = request.args.get('filter', 'all')
    folder_type = request.args.get('type', None)
    show_hidden = request.args.get('show_hidden', 'off').lower() == 'on'
    
    # For event-triggered requests, maintain current filter state
    if is_event_triggered:
        # If this is an event trigger, we need to preserve the current filter state
        # The event listener will have the current state in the DOM
        # So we just return the full list with current show_hidden state
        folders = Folder.query.filter_by(user_id=current_user.id).all()
        return render_template('partials/folders_list.html', folders=folders, show_hidden=show_hidden)
    
    # Get folders for the current authenticated user
    if folder_type:
        # Filter by folder type
        folders = Folder.query.filter_by(user_id=current_user.id, folder_type=folder_type).all()
    elif filter_type == 'high':
        # Get high priority folders (priority = 1)
        folders = Folder.query.filter_by(user_id=current_user.id, priority=1).all()
    elif filter_type == 'normal':
        # Get normal priority folders (priority = 0 or not set)
        folders = Folder.query.filter_by(user_id=current_user.id).filter(Folder.priority != 1).all()
    else:
        # Get all folders
        folders = Folder.query.filter_by(user_id=current_user.id).all()
    
    if folder_type == 'tidy':
        response = make_response(render_template('partials/folders_to_tidy_section.html', folders=folders, show_hidden=show_hidden))
        response.headers["HX-Retarget"] = "#folders-to-tidy"
        return response
    elif folder_type == 'destination':
        response = make_response(render_template('partials/destination_folders_section.html', folders=folders, show_hidden=show_hidden))
        response.headers["HX-Retarget"] = "#destination-folders"
        return response
    elif folder_type == 'ignore':
        response = make_response(render_template('partials/hidden_folders_section.html', folders=folders, show_hidden=show_hidden))
        response.headers["HX-Retarget"] = "#hidden-folders"
        
        # Show or hide the hidden folders section based on the show_hidden parameter
        if show_hidden:
            response.headers['HX-Trigger'] = 'show-hidden'
        else:
            response.headers['HX-Trigger'] = 'hide-hidden'
            
        return response
    else:
        return render_template('partials/folders_list.html', folders=folders, show_hidden=show_hidden)

@folders_bp.route('/api/folders/generate-rule', methods=['POST'])
@login_required
def generate_rule():
    """Generate an email organization rule using AI."""
    try:
        # Get form data
        folder_name = request.form.get('name', '').strip()
        folder_type = request.form.get('folder_type', 'destination')
        rule_type = request.form.get('rule_type', 'single')  # 'single' or 'multiple'
        rule_text = request.form.get('rule_text', '')
        
        # Validate inputs
        if not folder_name:
            return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Folder name is required'})
            
        if folder_type not in ['destination', 'tidy', 'ignore']:
            return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Invalid folder type'})
            
        if rule_type not in ['single', 'multiple']:
            return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Invalid rule type'})
            
        # Check cache first
        cache_key = AIRuleCache.generate_cache_key(folder_name, folder_type, rule_type, rule_text)
        cached_rule = AIRuleCache.query.filter_by(
            cache_key=cache_key,
            user_id=current_user.id,
            is_active=True
        ).first()
        
        if cached_rule and not cached_rule.is_expired():
            # Return cached result
            result = {
                'success': True,
                'cached': True,
                'rule': cached_rule.rule_text,
                'metadata': cached_rule.rule_metadata,
                'quality_score': cached_rule.rule_metadata.get('quality_score', 0) if cached_rule.rule_metadata else 0
            }
            return render_template('partials/ai_rule_result.html', result=result)
        
        # Generate new rule using AI service
        # Only support multiple rules now
        rules, metadata = ai_service.generate_multiple_rules(folder_name, folder_type, rule_text)
        
        if rules is None:
            # AI service failed, return fallback
            fallback_rule = ai_service.get_fallback_rule(folder_name, folder_type)
            result = {
                'success': True,
                'fallback': True,
                'rules': [{'text': fallback_rule, 'quality_score': 50}],
                'message': 'AI service unavailable, using fallback rule'
            }
            return render_template('partials/ai_rule_result.html', result=result)
            
        # Cache the first rule as representative
        expires_at = datetime.utcnow() + timedelta(hours=1)
        cache_entry = AIRuleCache(
            user_id=current_user.id,
            folder_name=folder_name,
            folder_type=folder_type,
            rule_text=rules[0]['text'] if rules else '',
            rule_metadata=metadata,
            cache_key=cache_key,
            expires_at=expires_at
        )
        db.session.add(cache_entry)
        
        db.session.commit()
        
        result = {
            'success': True,
            'rules': rules,
            'metadata': metadata
        }
        return render_template('partials/ai_rule_result.html', result=result)
            
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error generating rule: %s", e)
        return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'An unexpected error occurred'})

@folders_bp.route('/api/folders/assess-rule', methods=['POST'])
@login_required
def assess_rule():
    """Assess the quality of an email organization rule."""
    try:
        # Get form data
        rule_text = request.form.get('rule_text', '').strip()
        folder_name = request.form.get('folder_name', '').strip()
        folder_type = request.form.get('folder_type', 'destination')
        
        # Validate inputs
        if not rule_text:
            return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Rule text is required'})
            
        if not folder_name:
            return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Folder name is required'})
            
        if folder_type not in ['destination', 'tidy', 'ignore']:
            return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Invalid folder type'})
            
        # Assess rule quality
        quality_assessment = ai_service.assess_rule_quality(rule_text, folder_name, folder_type)
        
        result = {
            'success': True,
            'assessment': quality_assessment,
            'rule': rule_text,
            'quality_score': quality_assessment['score']
        }
        return render_template('partials/ai_rule_result.html', result=result)
        
    except Exception as e:
        # Print unhandled exceptions to the console as required
        logging.exception("Error assessing rule: %s", e)
        return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'An unexpected error occurred'})