from flask import Blueprint, render_template, request, redirect, url_for, flash, send_file, jsonify
from flask_login import login_required, current_user
from datetime import datetime, timedelta
import csv
import io
from functools import wraps
import sys
sys.path.append('..')
from app import db, User, Contribution, Transaction, Loan

admin_bp = Blueprint('admin', __name__)

def role_required(*roles):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if not current_user.is_authenticated:
                return redirect(url_for('login'))
            if current_user.role not in roles:
                flash('You do not have permission to access this page.', 'danger')
                return redirect(url_for('dashboard'))
            return f(*args, **kwargs)
        return decorated_function
    return decorator

@admin_bp.route('/admin/users')
@login_required
@role_required('Super Admin', 'Admin')
def manage_users():
    users = User.query.order_by(User.created_at.desc()).all()
    return render_template('admin/users.html', users=users)

@admin_bp.route('/admin/users/<int:user_id>/edit', methods=['GET', 'POST'])
@login_required
@role_required('Super Admin', 'Admin')
def edit_user(user_id):
    user = User.query.get_or_404(user_id)
    
    if request.method == 'POST':
        user.full_name = request.form.get('full_name')
        user.email = request.form.get('email')
        user.phone = request.form.get('phone')
        user.role = request.form.get('role')
        
        db.session.commit()
        flash('User updated successfully!', 'success')
        return redirect(url_for('admin.manage_users'))
    
    return render_template('admin/edit_user.html', user=user)

@admin_bp.route('/admin/contributions')
@login_required
@role_required('Super Admin', 'Admin', 'Treasurer')
def manage_contributions():
    contributions = Contribution.query.order_by(Contribution.created_at.desc()).all()
    return render_template('admin/contributions.html', contributions=contributions)

@admin_bp.route('/admin/contributions/<int:contribution_id>/approve')
@login_required
@role_required('Super Admin', 'Admin', 'Treasurer')
def approve_contribution(contribution_id):
    contribution = Contribution.query.get_or_404(contribution_id)
    
    if contribution.status != 'pending':
        flash('This contribution has already been processed.', 'warning')
        return redirect(url_for('admin.manage_contributions'))
    
    # Update contribution status
    contribution.status = 'approved'
    contribution.approved_by = current_user.id
    contribution.approved_at = datetime.utcnow()
    
    # Update user's wallet
    wallet = Wallet.query.filter_by(user_id=contribution.user_id).first()
    wallet.balance += contribution.amount
    
    # Create transaction record
    transaction = Transaction(
        user_id=contribution.user_id,
        type='deposit',
        amount=contribution.amount,
        status='completed',
        description='Manual contribution approval',
        reference=f'MANUAL-{contribution.id}'
    )
    
    db.session.add(transaction)
    db.session.commit()
    
    flash(f'Contribution of ₦{contribution.amount:.2f} approved for {contribution.user.full_name}.', 'success')
    return redirect(url_for('admin.manage_contributions'))

@admin_bp.route('/admin/contributions/<int:contribution_id>/reject')
@login_required
@role_required('Super Admin', 'Admin', 'Treasurer')
def reject_contribution(contribution_id):
    contribution = Contribution.query.get_or_404(contribution_id)
    
    if contribution.status != 'pending':
        flash('This contribution has already been processed.', 'warning')
        return redirect(url_for('admin.manage_contributions'))
    
    contribution.status = 'rejected'
    contribution.approved_by = current_user.id
    contribution.approved_at = datetime.utcnow()
    
    db.session.commit()
    
    flash(f'Contribution from {contribution.user.full_name} has been rejected.', 'info')
    return redirect(url_for('admin.manage_contributions'))

@admin_bp.route('/admin/transactions')
@login_required
@role_required('Super Admin', 'Admin', 'Treasurer')
def manage_transactions():
    transactions = Transaction.query.order_by(Transaction.created_at.desc()).all()
    return render_template('admin/transactions.html', transactions=transactions)

@admin_bp.route('/admin/reports')
@login_required
@role_required('Super Admin', 'Admin')
def reports():
    return render_template('admin/reports.html')

@admin_bp.route('/admin/export/users')
@login_required
@role_required('Super Admin', 'Admin')
def export_users():
    users = User.query.all()
    
    output = io.StringIO()
    writer = csv.writer(output)
    
    writer.writerow(['ID', 'Registration Number', 'Full Name', 'Email', 'Phone', 'Role', 'Verified', 'Created At'])
    
    for user in users:
        writer.writerow([
            user.id,
            user.registration_number,
            user.full_name,
            user.email,
            user.phone,
            user.role,
            'Yes' if user.is_verified else 'No',
            user.created_at.strftime('%Y-%m-%d %H:%M:%S')
        ])
    
    output.seek(0)
    
    return send_file(
        io.BytesIO(output.getvalue().encode('utf-8')),
        mimetype='text/csv',
        as_attachment=True,
        download_name=f'users_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'
    )

@admin_bp.route('/admin/export/transactions')
@login_required
@role_required('Super Admin', 'Admin')
def export_transactions():
    transactions = Transaction.query.all()
    
    output = io.StringIO()
    writer = csv.writer(output)
    
    writer.writerow(['ID', 'User', 'Type', 'Amount', 'Status', 'Reference', 'Description', 'Created At'])
    
    for transaction in transactions:
        writer.writerow([
            transaction.id,
            transaction.user.full_name,
            transaction.type,
            transaction.amount,
            transaction.status,
            transaction.reference,
            transaction.description,
            transaction.created_at.strftime('%Y-%m-%d %H:%M:%S')
        ])
    
    output.seek(0)
    
    return send_file(
        io.BytesIO(output.getvalue().encode('utf-8')),
        mimetype='text/csv',
        as_attachment=True,
        download_name=f'transactions_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'
    )

@admin_bp.route('/admin/analytics')
@login_required
@role_required('Super Admin', 'Admin')
def analytics():
    # Basic analytics data
    total_users = User.query.count()
    verified_users = User.query.filter_by(is_verified=True).count()
    total_contributions = db.session.query(db.func.sum(Contribution.amount)).filter_by(status='approved').scalar() or 0
    total_loans = db.session.query(db.func.sum(Loan.amount)).filter_by(status='approved').scalar() or 0
    
    # Monthly data for the last 6 months
    monthly_data = []
    for i in range(6):
        month_start = datetime.utcnow().replace(day=1) - timedelta(days=30*i)
        month_end = (month_start + timedelta(days=32)).replace(day=1) - timedelta(days=1)
        
        month_contributions = db.session.query(db.func.sum(Contribution.amount)).filter(
            Contribution.status == 'approved',
            Contribution.created_at >= month_start,
            Contribution.created_at <= month_end
        ).scalar() or 0
        
        month_loans = db.session.query(db.func.sum(Loan.amount)).filter(
            Loan.status == 'approved',
            Loan.created_at >= month_start,
            Loan.created_at <= month_end
        ).scalar() or 0
        
        monthly_data.append({
            'month': month_start.strftime('%B %Y'),
            'contributions': month_contributions,
            'loans': month_loans
        })
    
    return render_template('admin/analytics.html',
                         total_users=total_users,
                         verified_users=verified_users,
                         total_contributions=total_contributions,
                         total_loans=total_loans,
                         monthly_data=monthly_data)
