from flask import Blueprint, redirect, url_for, flash, jsonify
from flask_admin import Admin, BaseView, expose
from flask_admin.contrib.sqla import ModelView
from flask_admin.contrib.fileadmin import FileAdmin
from flask_admin.menu import MenuLink
from flask_admin.actions import action
try:
    from flask_admin.theme import Bootstrap4Theme
    _FLASK_ADMIN_V2 = True
except ImportError:
    _FLASK_ADMIN_V2 = False
from flask_login import current_user, login_required
from musicround.models import Song, Tag, SongTag, Round, User, Role, UserPreferences, SystemSetting, db
from functools import wraps
import os
import json

# Create a basic authentication wrapper
def admin_required(view_func):
    @wraps(view_func)
    def wrapper(*args, **kwargs):
        # Check if user is logged in and is an admin
        if not current_user.is_authenticated:
            return redirect(url_for('users.login'))
        
        if not current_user.is_admin:
            flash('Admin access required.', 'danger')
            return redirect(url_for('core.index'))
            
        return view_func(*args, **kwargs)
    return wrapper

# Create the blueprint
db_admin_bp = Blueprint('db_admin', __name__, url_prefix='/admin')

# Define routes on the blueprint before it gets registered
@db_admin_bp.route('/raw')
@admin_required
def raw_db_access():
    return redirect(url_for('admin.index'))

# Base model view with authentication
class AuthModelView(ModelView):
    def is_accessible(self):
        return current_user.is_authenticated and current_user.is_admin
    
    def inaccessible_callback(self, name, **kwargs):
        if not current_user.is_authenticated:
            return redirect(url_for('users.login'))
        return redirect(url_for('core.index'))
    
    # Add basic search functionality to all models
    column_searchable_list = []
    column_filters = []
    
    # Enable export to CSV
    can_export = True
    export_types = ['csv', 'json']

# Enhanced Song ModelView
class SongModelView(AuthModelView):
    column_searchable_list = ['title', 'artist', 'spotify_id']
    column_filters = ['title', 'artist', 'year', 'genre', 'used_count']
    column_default_sort = ('id', False)
    
    @action('reset_used_count', 'Reset Used Count', 'Are you sure you want to reset used count to 0?')
    def action_reset_used_count(self, ids):
        try:
            query = Song.query.filter(Song.id.in_(ids))
            
            # Update all songs
            for song in query.all():
                song.used_count = 0
            
            db.session.commit()
            flash(f'Used count reset for {len(ids)} songs.', 'success')
        except Exception as ex:
            db.session.rollback()
            flash(f'Error resetting used count: {str(ex)}', 'danger')

# Enhanced Round ModelView
class RoundModelView(AuthModelView):
    column_searchable_list = ['name', 'round_type', 'round_criteria_used']
    column_filters = ['name', 'round_type', 'round_criteria_used']
    column_list = ['id', 'name', 'round_type', 'round_criteria_used', 'created_at', 'mp3_generated', 'pdf_generated']
    column_default_sort = ('id', False)

# Enhanced Tag ModelView
class TagModelView(AuthModelView):
    column_searchable_list = ['name']
    column_filters = ['name']

# Enhanced SongTag ModelView
class SongTagModelView(AuthModelView):
    column_filters = ['song_id', 'tag_id']

# Enhanced User ModelView
class UserModelView(AuthModelView):
    column_searchable_list = ['username', 'email', 'first_name', 'last_name']
    column_filters = ['username', 'email', 'active', 'created_at', 'last_login']
    column_default_sort = ('id', False)
    
    # Protect password field in forms
    form_excluded_columns = ['password_hash', 'reset_token', 'reset_token_expiry']
    
    @action('activate_users', 'Activate Users', 'Are you sure you want to activate selected users?')
    def action_activate_users(self, ids):
        try:
            query = User.query.filter(User.id.in_(ids))
            
            # Update all selected users
            for user in query.all():
                user.active = True
            
            db.session.commit()
            flash(f'Successfully activated {len(ids)} users.', 'success')
        except Exception as ex:
            db.session.rollback()
            flash(f'Error activating users: {str(ex)}', 'danger')
            
    @action('deactivate_users', 'Deactivate Users', 'Are you sure you want to deactivate selected users?')
    def action_deactivate_users(self, ids):
        try:
            query = User.query.filter(User.id.in_(ids))
            
            # Update all selected users
            for user in query.all():
                user.active = False
            
            db.session.commit()
            flash(f'Successfully deactivated {len(ids)} users.', 'success')
        except Exception as ex:
            db.session.rollback()
            flash(f'Error deactivating users: {str(ex)}', 'danger')

# Enhanced Role ModelView
class RoleModelView(AuthModelView):
    column_searchable_list = ['name', 'description']
    column_filters = ['name']

# Enhanced UserPreferences ModelView
class UserPreferencesModelView(AuthModelView):
    column_filters = ['user_id', 'theme', 'enable_intro']
    
# Enhanced SystemSetting ModelView
class SystemSettingModelView(AuthModelView):
    column_searchable_list = ['key']
    column_filters = ['key']
    column_exclude_list = []  # Ensure any sensitive values are not excluded if needed

# Initialize the admin interface
admin = None

def init_admin(app):
    """Initialize the admin interface with the Flask app."""
    global admin
    
    # Set Flask-Admin configuration
    app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'  # Use a Bootstrap swatch theme
    
    # Create admin interface
    if _FLASK_ADMIN_V2:
        admin = Admin(
            app,
            name='MusicRound Admin',
            theme=Bootstrap4Theme(swatch='cerulean'),
            url='/admin'
        )
    else:
        admin = Admin(
            app,
            name='MusicRound Admin',
            template_mode='bootstrap3',
            url='/admin'
        )
    
    # Add model views
    # Data models
    admin.add_view(SongModelView(Song, db.session, category="Music Data"))
    admin.add_view(TagModelView(Tag, db.session, category="Music Data"))
    admin.add_view(SongTagModelView(SongTag, db.session, category="Music Data"))
    admin.add_view(RoundModelView(Round, db.session, category="Music Data"))
    
    # User management
    admin.add_view(UserModelView(User, db.session, category="User Management"))
    admin.add_view(RoleModelView(Role, db.session, category="User Management"))
    admin.add_view(UserPreferencesModelView(UserPreferences, db.session, category="User Management"))
    
    # System
    admin.add_view(SystemSettingModelView(SystemSetting, db.session, category="System"))
    
    # Add file admin for audio files
    path = os.path.join(os.path.dirname(__file__), '../static/audio')
    admin.add_view(FileAdmin(path, '/static/audio/', name='Audio Files', category="System", endpoint='static_audio_files'))
    
    # User MP3 files
    user_mp3_path = os.path.join(os.path.dirname(__file__), '../mp3')
    admin.add_view(FileAdmin(user_mp3_path, '/mp3/', name='User MP3 Files', category="System", endpoint='user_mp3_files'))
    
    # Add links
    admin.add_link(MenuLink(name='Back to App', url='/'))
    
    return admin