from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app, session
from datetime import datetime, timedelta
import uuid
import os

from database import db
from models import User, Company, AnalysisJob, AnalysisResult, ActivityLog, Invitation, Session
from auth_routes import admin_required, company_admin_required, login_required, log_activity

# Create a Blueprint for admin routes
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')

# Admin dashboard
@admin_bp.route('/')
@admin_required
def dashboard():
    # Get statistics
    user_count = User.query.count()
    company_count = Company.query.count()
    analysis_count = AnalysisJob.query.count()
    active_analyses = AnalysisJob.query.filter_by(status='processing').count()

    # Get recent activity
    recent_activity = ActivityLog.query.order_by(ActivityLog.created_at.desc()).limit(10).all()

    # Get recent users
    recent_users = User.query.order_by(User.created_at.desc()).limit(5).all()

    # Get recent analyses
    recent_analyses = AnalysisJob.query.order_by(AnalysisJob.created_at.desc()).limit(5).all()

    return render_template(
        'admin/dashboard.html',
        user_count=user_count,
        company_count=company_count,
        analysis_count=analysis_count,
        active_analyses=active_analyses,
        recent_activity=recent_activity,
        recent_users=recent_users,
        recent_analyses=recent_analyses
    )

# User management routes
@admin_bp.route('/users')
@admin_required
def users():
    users = User.query.order_by(User.username).all()
    return render_template('admin/users.html', users=users)

@admin_bp.route('/users/new', methods=['GET', 'POST'])
@admin_required
def new_user():
    companies = Company.query.order_by(Company.name).all()

    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        password = request.form.get('password')
        confirm_password = request.form.get('confirm_password')
        first_name = request.form.get('first_name')
        last_name = request.form.get('last_name')
        role = request.form.get('role')
        company_id = request.form.get('company_id')

        # Validation
        if not all([username, email, password, confirm_password, role]):
            flash('Required fields are missing', 'danger')
            return render_template('admin/new_user.html', companies=companies)

        if password != confirm_password:
            flash('Passwords do not match', 'danger')
            return render_template('admin/new_user.html', companies=companies)

        # Check if username or email already exists
        if User.query.filter_by(username=username).first():
            flash('Username already exists', 'danger')
            return render_template('admin/new_user.html', companies=companies)

        if User.query.filter_by(email=email).first():
            flash('Email already exists', 'danger')
            return render_template('admin/new_user.html', companies=companies)

        # Convert company_id to int or None
        if company_id:
            try:
                company_id = int(company_id)
            except ValueError:
                company_id = None
        else:
            company_id = None

        # Create new user
        user = User(
            username=username,
            email=email,
            first_name=first_name,
            last_name=last_name,
            role=role,
            company_id=company_id
        )
        user.set_password(password)

        db.session.add(user)
        db.session.commit()

        # Log the activity
        current_user_id = session.get('user_id')
        log_activity(
            current_user_id,
            'user_creation',
            f"Administrator created new user: {username}",
            'user',
            user.id
        )

        flash('User created successfully', 'success')
        return redirect(url_for('admin.users'))

    return render_template('admin/new_user.html', companies=companies)
# Add this to admin_routes.py

@admin_bp.route('/fix-user-subscriptions', methods=['GET', 'POST'])
@admin_required
def fix_user_subscriptions():
    """Fix user subscriptions to match their company plans"""
    
    # Import models at function level
    from models import Company, User, Subscription, SubscriptionPlan

    if request.method == 'POST':
        action = request.form.get('action')
        
        if action == 'fix_all':
            # Fix all users across all companies
            
            companies = Company.query.all()
            total_users_fixed = 0
            
            for company in companies:
                company_subscription = Subscription.query.filter_by(
                    company_id=company.id,
                    status='active'
                ).first()
                
                if company_subscription:
                    users_fixed = fix_company_users_subscription(company.id)
                    total_users_fixed += users_fixed
                    flash(f'Fixed {users_fixed} users in {company.name}', 'info')
            
            flash(f'Successfully fixed subscriptions for {total_users_fixed} users total', 'success')
            
        elif action == 'fix_company':
            company_id = request.form.get('company_id')
            if company_id:
                users_fixed = fix_company_users_subscription(int(company_id))
                company = Company.query.get(company_id)
                flash(f'Fixed subscriptions for {users_fixed} users in {company.name if company else "Unknown Company"}', 'success')
        
        return redirect(url_for('admin.fix_user_subscriptions'))
    
    # GET request - show the form and current status
    
    # Get companies with subscription issues
    companies_with_issues = []
    
    companies = Company.query.all()
    for company in companies:
        company_subscription = Subscription.query.filter_by(
            company_id=company.id,
            status='active'
        ).first()
        
        if company_subscription:
            # Count users with wrong subscription
            company_users = User.query.filter_by(
                company_id=company.id,
                active=True
            ).all()
            
            users_with_wrong_plan = 0
            users_without_subscription = 0
            
            for user in company_users:
                user_subscription = user.get_subscription()
                if not user_subscription:
                    users_without_subscription += 1
                elif user_subscription.plan_id != company_subscription.plan_id:
                    users_with_wrong_plan += 1
            
            if users_with_wrong_plan > 0 or users_without_subscription > 0:
                companies_with_issues.append({
                    'company': company,
                    'company_plan': company_subscription.plan.name,
                    'total_users': len(company_users),
                    'wrong_plan': users_with_wrong_plan,
                    'no_subscription': users_without_subscription
                })
    
    return render_template('admin/fix_subscriptions.html', 
                         companies_with_issues=companies_with_issues)

def fix_company_users_subscription(company_id):
    """Fix all users in a company to have the correct subscription - returns count of users fixed"""
    from models import User, Subscription
    
    # Get company's active subscription
    company_subscription = Subscription.query.filter_by(
        company_id=company_id,
        status='active'
    ).first()
    
    if not company_subscription:
        return 0
    
    # Get all active users in the company
    company_users = User.query.filter_by(
        company_id=company_id,
        active=True
    ).all()
    
    users_fixed = 0
    for user in company_users:
        user_subscription = user.get_subscription()
        
        # If user has no subscription or wrong plan, fix it
        if (not user_subscription or 
            user_subscription.plan_id != company_subscription.plan_id):
            
            if user_subscription:
                # Update existing subscription
                user_subscription.plan_id = company_subscription.plan_id
                user_subscription.monthly_analyses_used = 0  # Reset usage
                user_subscription.monthly_reset_date = datetime.utcnow() + timedelta(days=30)
            else:
                # Create new subscription
                new_subscription = Subscription(
                    user_id=user.id,
                    company_id=company_id,
                    plan_id=company_subscription.plan_id,
                    status='active',
                    monthly_analyses_used=0,
                    monthly_reset_date=datetime.utcnow() + timedelta(days=30)
                )
                db.session.add(new_subscription)  # ✅ FIXED: Use db.session instead of db_session
            
            users_fixed += 1
    
    if users_fixed > 0:
        db.session.commit()  # ✅ FIXED: Use db.session instead of db_session
    
    return users_fixed

@admin_bp.route('/users/edit/<int:user_id>', methods=['GET', 'POST'])
@admin_required
def edit_user(user_id):
    user = User.query.filter_by(id=user_id).first_or_404()
    companies = Company.query.order_by(Company.name).all()

    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        first_name = request.form.get('first_name')
        last_name = request.form.get('last_name')
        role = request.form.get('role')
        company_id = request.form.get('company_id')
        active = 'active' in request.form

        # Check if username changed and already exists
        if username != user.username and User.query.filter_by(username=username).first():
            flash('Username already exists', 'danger')
            return render_template('admin/edit_user.html', user=user, companies=companies)

        # Check if email changed and already exists
        if email != user.email and User.query.filter_by(email=email).first():
            flash('Email already exists', 'danger')
            return render_template('admin/edit_user.html', user=user, companies=companies)

        # Convert company_id to int or None
        if company_id:
            try:
                company_id = int(company_id)
            except ValueError:
                company_id = None
        else:
            company_id = None

        # Update user
        user.username = username
        user.email = email
        user.first_name = first_name
        user.last_name = last_name
        user.role = role
        user.company_id = company_id
        user.active = active

        # Update password if provided
        password = request.form.get('password')
        if password:
            confirm_password = request.form.get('confirm_password')
            if password != confirm_password:
                flash('Passwords do not match', 'danger')
                return render_template('admin/edit_user.html', user=user, companies=companies)

            user.set_password(password)

        db.session.commit()

        # Log the activity
        current_user_id = session.get('user_id')
        log_activity(
            current_user_id,
            'user_update',
            f"Administrator updated user: {username}",
            'user',
            user.id
        )

        flash('User updated successfully', 'success')
        return redirect(url_for('admin.users'))

    return render_template('admin/edit_user.html', user=user, companies=companies)

@admin_bp.route('/users/delete/<int:user_id>', methods=['POST'])
@admin_required
def delete_user(user_id):
    user = User.query.filter_by(id=user_id).first_or_404()

    # Don't allow deleting yourself
    current_user_id = session.get('user_id')
    if user.id == current_user_id:
        flash('You cannot delete your own account', 'danger')
        return redirect(url_for('admin.users'))

    username = user.username

    try:
        # Import all models we need to delete
        from models import SummarizationJob, SummarizationResult, CaseNote, CaseActivity, CaseDocument, PasswordReset

        # Delete user's sessions first to avoid foreign key constraint errors
        user_sessions = Session.query.filter_by(user_id=user.id).all()
        for session_record in user_sessions:
            db.session.delete(session_record)

        # Delete activity logs
        activity_logs = ActivityLog.query.filter_by(user_id=user.id).all()
        for log in activity_logs:
            db.session.delete(log)

        # Delete summarization jobs and their results
        summarization_jobs = SummarizationJob.query.filter_by(user_id=user.id).all()
        for job in summarization_jobs:
            # Delete associated results if they exist
            if hasattr(job, 'results') and job.results:
                db.session.delete(job.results)
            db.session.delete(job)

        # Delete analysis jobs and their results
        analysis_jobs = AnalysisJob.query.filter_by(user_id=user.id).all()
        for job in analysis_jobs:
            # Delete associated results if they exist
            if hasattr(job, 'results') and job.results:
                db.session.delete(job.results)
            db.session.delete(job)

        # Delete case notes
        case_notes = CaseNote.query.filter_by(user_id=user.id).all()
        for note in case_notes:
            db.session.delete(note)

        # Delete case activities
        case_activities = CaseActivity.query.filter_by(user_id=user.id).all()
        for activity in case_activities:
            db.session.delete(activity)

        # Delete case documents uploaded by user
        case_documents = CaseDocument.query.filter_by(uploaded_by_id=user.id).all()
        for document in case_documents:
            db.session.delete(document)

        # Delete password reset tokens
        password_resets = PasswordReset.query.filter_by(user_id=user.id).all()
        for reset in password_resets:
            db.session.delete(reset)

        # Delete invitations created by this user
        invitations = Invitation.query.filter_by(created_by=user.id).all()
        for invitation in invitations:
            db.session.delete(invitation)

        # Delete user
        db.session.delete(user)
        db.session.commit()

        # Log the activity
        log_activity(
            current_user_id,
            'user_deletion',
            f"Administrator deleted user: {username}"
        )

        flash('User deleted successfully', 'success')

    except Exception as e:
        db.session.rollback()
        flash(f'Error deleting user: {str(e)}', 'danger')

    return redirect(url_for('admin.users'))

# Company management routes
@admin_bp.route('/companies')
@admin_required
def companies():
    companies = Company.query.order_by(Company.name).all()
    return render_template('admin/companies.html', companies=companies)

@admin_bp.route('/companies/new', methods=['GET', 'POST'])
@admin_required
def new_company():
    if request.method == 'POST':
        name = request.form.get('name')
        description = request.form.get('description')
        subscription_tier = request.form.get('subscription_tier', 'free')

        # Validation
        if not name:
            flash('Company name is required', 'danger')
            return render_template('admin/new_company.html')

        # Check if company name already exists
        if Company.query.filter_by(name=name).first():
            flash('Company name already exists', 'danger')
            return render_template('admin/new_company.html')

        # Create new company
        company = Company(
            name=name,
            description=description,
            subscription_tier=subscription_tier
        )

        db.session.add(company)
        db.session.commit()

        # Log the activity
        current_user_id = session.get('user_id')
        log_activity(
            current_user_id,
            'company_creation',
            f"Administrator created new company: {name}",
            'company',
            company.id
        )

        flash('Company created successfully', 'success')
        return redirect(url_for('admin.companies'))

    return render_template('admin/new_company.html')

@admin_bp.route('/companies/edit/<int:company_id>', methods=['GET', 'POST'])
@admin_required
def edit_company(company_id):
    company = Company.query.filter_by(id=company_id).first_or_404()

    if request.method == 'POST':
        name = request.form.get('name')
        description = request.form.get('description')
        subscription_tier = request.form.get('subscription_tier')
        active = 'active' in request.form

        # Check if name changed and already exists
        if name != company.name and Company.query.filter_by(name=name).first():
            flash('Company name already exists', 'danger')
            return render_template('admin/edit_company.html', company=company)

        # Update company
        company.name = name
        company.description = description
        company.subscription_tier = subscription_tier
        company.active = active

        db.session.commit()

        # Log the activity
        current_user_id = session.get('user_id')
        log_activity(
            current_user_id,
            'company_update',
            f"Administrator updated company: {name}",
            'company',
            company.id
        )

        flash('Company updated successfully', 'success')
        return redirect(url_for('admin.companies'))

    return render_template('admin/edit_company.html', company=company)

@admin_bp.route('/companies/delete/<int:company_id>', methods=['POST'])
@admin_required
def delete_company(company_id):
    company = Company.query.filter_by(id=company_id).first_or_404()

    # Check if company has users
    if company.users:
        flash('Cannot delete company that has users', 'danger')
        return redirect(url_for('admin.companies'))

    company_name = company.name

    # Delete company
    db.session.delete(company)
    db.session.commit()

    # Log the activity
    current_user_id = session.get('user_id')
    log_activity(
        current_user_id,
        'company_deletion',
        f"Administrator deleted company: {company_name}"
    )

    flash('Company deleted successfully', 'success')
    return redirect(url_for('admin.companies'))

# Invitation management
@admin_bp.route('/invitations')
@admin_required
def invitations():
    invitations = Invitation.query.order_by(Invitation.created_at.desc()).all()
    return render_template('admin/invitations.html', invitations=invitations)

@admin_bp.route('/invitations/new', methods=['GET', 'POST'])
@admin_required
def new_invitation():
    companies = Company.query.order_by(Company.name).all()

    if request.method == 'POST':
        email = request.form.get('email')
        company_id = request.form.get('company_id')
        role = request.form.get('role', 'user')

        # Validation
        if not email or not company_id:
            flash('Email and company are required', 'danger')
            return render_template('admin/new_invitation.html', companies=companies)

        # Check if user already exists with this email
        if User.query.filter_by(email=email).first():
            flash('A user with this email already exists', 'danger')
            return render_template('admin/new_invitation.html', companies=companies)

        # Check if invitation already exists for this email
        if Invitation.query.filter_by(email=email, accepted=False).first():
            flash('An invitation has already been sent to this email', 'danger')
            return render_template('admin/new_invitation.html', companies=companies)

        # Convert company_id to int
        try:
            company_id = int(company_id)
        except ValueError:
            flash('Invalid company selected', 'danger')
            return render_template('admin/new_invitation.html', companies=companies)

        # Create invitation
        current_user_id = session.get('user_id')
        invitation = Invitation.create_invitation(
            email=email,
            company_id=company_id,
            role=role,
            created_by=current_user_id
        )

        db.session.add(invitation)
        db.session.commit()

        # Send the invitation email - FORCE HTTPS
        print("🔧 Debug: Admin generating invitation URL...")
        print(f"  Flask PREFERRED_URL_SCHEME: {current_app.config.get('PREFERRED_URL_SCHEME', 'NOT SET')}")
        print(f"  Request scheme: {request.scheme}")

        # Generate the URL normally first
        invitation_url = url_for(
            'auth.accept_invitation',
            token=invitation.invitation_token,
            _external=True
        )

        print(f"🔗 Original URL: {invitation_url}")

        # FORCE HTTPS if it's HTTP (fix for anti-spam issues)
        if invitation_url.startswith('http://'):
            invitation_url = invitation_url.replace('http://', 'https://', 1)
            print(f"🔗 Forced HTTPS URL: {invitation_url}")
        else:
            print(f"🔗 URL already HTTPS: {invitation_url}")

        # Get company name for the email
        company = Company.query.get(company_id)
        company_name = company.name if company else "Your Organization"

        # Import and call the email function
        from email_config import send_invitation_email
        try:
            if send_invitation_email(email, invitation_url, company_name):
                flash('Invitation sent successfully', 'success')
            else:
                flash(f'Invitation created but email failed. Manual URL: {invitation_url}', 'warning')
                print(f"Invitation URL for {email}: {invitation_url}")
        except Exception as e:
            flash(f'Invitation created but email error: {str(e)}', 'warning')
            print(f"Invitation URL for {email}: {invitation_url}")

        # Log the activity
        log_activity(
            current_user_id,
            'invitation_sent',
            f"Administrator sent invitation to: {email}",
            'invitation',
            invitation.id
        )

        return redirect(url_for('admin.invitations'))

    return render_template('admin/new_invitation.html', companies=companies)

@admin_bp.route('/invitations/cancel/<int:invitation_id>', methods=['POST'])
@admin_required
def cancel_invitation(invitation_id):
    invitation = Invitation.query.filter_by(id=invitation_id).first_or_404()

    # Only cancel if not already accepted
    if not invitation.accepted:
        email = invitation.email

        # Delete invitation
        db.session.delete(invitation)
        db.session.commit()

        # Log the activity
        current_user_id = session.get('user_id')
        log_activity(
            current_user_id,
            'invitation_cancelled',
            f"Administrator cancelled invitation to: {email}"
        )

        flash('Invitation cancelled successfully', 'success')
    else:
        flash('This invitation has already been accepted', 'warning')

    return redirect(url_for('admin.invitations'))

# Analysis jobs management
@admin_bp.route('/analyses')
@admin_required
def analyses():
    analyses = AnalysisJob.query.order_by(AnalysisJob.created_at.desc()).all()
    return render_template('admin/analyses.html', analyses=analyses)

@admin_bp.route('/analyses/view/<job_uuid>')
@admin_required
def view_analysis(job_uuid):
    analysis = AnalysisJob.query.filter_by(job_uuid=job_uuid).first_or_404()
    return redirect(url_for('show_analysis', job_id=job_uuid))

@admin_bp.route('/analyses/delete/<job_uuid>', methods=['POST'])
@admin_required
def delete_analysis(job_uuid):
    analysis = AnalysisJob.query.filter_by(job_uuid=job_uuid).first_or_404()

    # Save info for logging
    filename = analysis.filename

    # Delete associated results if they exist
    if analysis.results:
        db.session.delete(analysis.results)

    # Delete analysis job
    db.session.delete(analysis)
    db.session.commit()

    # Log the activity
    current_user_id = session.get('user_id')
    log_activity(
        current_user_id,
        'analysis_deletion',
        f"Administrator deleted analysis: {filename}"
    )

    flash('Analysis deleted successfully', 'success')
    return redirect(url_for('admin.analyses'))

# Activity logs
@admin_bp.route('/activity')
@admin_required
def activity():
    page = request.args.get('page', 1, type=int)
    per_page = 50

    logs_query = ActivityLog.query.order_by(ActivityLog.created_at.desc())
    # Get total count for pagination
    total = logs_query.count()
    # Manual pagination
    offset = (page - 1) * per_page
    logs = logs_query.limit(per_page).offset(offset).all()

    return render_template('admin/activity.html', logs=logs)

# System settings
@admin_bp.route('/settings', methods=['GET', 'POST'])
@admin_required
def settings():
    if request.method == 'POST':
        # Update application settings
        # These would typically be stored in a settings table or config file
        flash('Settings updated successfully', 'success')
        return redirect(url_for('admin.settings'))

    return render_template('admin/settings.html')

# Maintenance - cleanup old jobs
@admin_bp.route('/maintenance/cleanup', methods=['POST'])
@admin_required
def cleanup_old_jobs():
    """Admin route to remove old analysis jobs to free up memory"""
    try:
        # Get age threshold in days (default to 7 days)
        days = int(request.form.get('days', 7))
        threshold = datetime.utcnow() - timedelta(days=days)

        # Find old jobs
        old_jobs = AnalysisJob.query.filter(AnalysisJob.created_at < threshold).all()

        removed_count = 0
        for job in old_jobs:
            # Clean up file if it exists
            if job.file_path and os.path.exists(job.file_path):
                try:
                    os.remove(job.file_path)
                except Exception as e:
                    print(f"Error removing file {job.file_path}: {e}")

            # Delete associated results
            if job.results:
                db.session.delete(job.results)

            # Delete job
            db.session.delete(job)
            removed_count += 1

        db.session.commit()

        # Log the activity
        user_id = session.get('user_id')
        log_activity(
            user_id,
            'cleanup',
            f"Administrator cleaned up {removed_count} old analysis jobs"
        )

        return jsonify({
            "success": True,
            "removed_count": removed_count,
            "remaining_count": AnalysisJob.query.count()
        })

    except Exception as e:
        return jsonify({
            "error": f"Cleanup failed: {str(e)}"
        }), 500
