from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, send_file
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, logout_user, current_user, login_required
from flask_mail import Mail, Message
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from datetime import datetime, timedelta
import secrets
import csv
import io
import requests
import os
from functools import wraps

app = Flask(__name__)
app.config['SECRET_KEY'] = secrets.token_hex(32)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///medlab_cooperative.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Email configuration
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')

# Paystack configuration
app.config['PAYSTACK_SECRET_KEY'] = os.environ.get('PAYSTACK_SECRET_KEY')
app.config['PAYSTACK_PUBLIC_KEY'] = os.environ.get('PAYSTACK_PUBLIC_KEY')

db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message = 'Please log in to access this page.'
mail = Mail(app)

# Define models inline to avoid circular imports
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    full_name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    phone = db.Column(db.String(20), nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)
    registration_number = db.Column(db.String(10), unique=True, nullable=False)
    role = db.Column(db.String(20), default='Member', nullable=False)
    is_verified = db.Column(db.Boolean, default=False, nullable=False)
    verification_token = db.Column(db.String(255), nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # New registration fields
    gender = db.Column(db.String(10), nullable=True)  # Male, Female, Other
    state_of_residence = db.Column(db.String(50), nullable=True)
    lga_of_residence = db.Column(db.String(50), nullable=True)
    work_study_address = db.Column(db.Text, nullable=True)
    expected_monthly_contribution = db.Column(db.Float, nullable=True)
    nin = db.Column(db.String(20), nullable=True)  # National Identification Number
    next_of_kin_name = db.Column(db.String(100), nullable=True)
    next_of_kin_mobile = db.Column(db.String(20), nullable=True)
    photo_path = db.Column(db.String(255), nullable=True)  # ID card photo
    
    # Member status
    is_approved = db.Column(db.Boolean, default=False, nullable=False)  # Admin approval
    registration_fee_paid = db.Column(db.Boolean, default=False, nullable=False)
    activation_date = db.Column(db.DateTime, nullable=True)
    
    # Bank details
    account_number = db.Column(db.String(20), nullable=True)
    account_name = db.Column(db.String(100), nullable=True)
    bank_name = db.Column(db.String(100), nullable=True)
    
    # Relationships
    wallet = db.relationship('Wallet', backref='user', uselist=False)
    transactions = db.relationship('Transaction', foreign_keys='Transaction.user_id', backref='user_transactions', lazy=True)
    contributions = db.relationship('Contribution', foreign_keys='Contribution.user_id', backref='user_contributions', lazy=True)
    loans = db.relationship('Loan', foreign_keys='Loan.user_id', backref='user_loans', lazy=True)
    referrals = db.relationship('Referral', backref='user_referrals', lazy=True, foreign_keys='Referral.referrer_id')
    insurance_policies = db.relationship('Insurance', backref='member', lazy=True)

class Wallet(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    balance = db.Column(db.Float, default=0.0, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

class Transaction(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    type = db.Column(db.String(50), nullable=False)
    amount = db.Column(db.Float, nullable=False)
    status = db.Column(db.String(20), default='pending', nullable=False)
    reference = db.Column(db.String(100), nullable=True)
    description = db.Column(db.Text, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class Contribution(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    amount = db.Column(db.Float, nullable=False)
    status = db.Column(db.String(20), default='pending', nullable=False)
    payment_method = db.Column(db.String(20), nullable=True)
    transaction_reference = db.Column(db.String(100), nullable=True)
    approved_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    approved_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Savings/Shares split (80%/20%)
    savings_amount = db.Column(db.Float, nullable=True)  # 80% of contribution
    shares_amount = db.Column(db.Float, nullable=True)   # 20% of contribution
    
    # Relationships
    user = db.relationship('User', foreign_keys=[user_id], backref='user_contributions')
    approver = db.relationship('User', foreign_keys=[approved_by])

class Loan(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    amount = db.Column(db.Float, nullable=False)
    interest_rate = db.Column(db.Float, default=10.0, nullable=False)
    total_payable = db.Column(db.Float, nullable=False)
    duration_months = db.Column(db.Integer, nullable=False)
    purpose = db.Column(db.Text, nullable=False)
    status = db.Column(db.String(20), default='pending', nullable=False)
    due_date = db.Column(db.DateTime, nullable=True)
    approved_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    approved_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Loan type
    loan_type = db.Column(db.String(20), default='financial', nullable=False)  # financial, commodity, housing
    
    # Relationships
    user = db.relationship('User', foreign_keys=[user_id], backref='user_loans')
    approver = db.relationship('User', foreign_keys=[approved_by])
    repayments = db.relationship('LoanRepayment', backref='loan', lazy=True)

class LoanRepayment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    loan_id = db.Column(db.Integer, db.ForeignKey('loan.id'), nullable=False)
    amount = db.Column(db.Float, nullable=False)
    payment_method = db.Column(db.String(20), nullable=True)
    transaction_reference = db.Column(db.String(100), nullable=True)
    status = db.Column(db.String(20), default='pending', nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class PasswordReset(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), nullable=False)
    token = db.Column(db.String(255), unique=True, nullable=False)
    expiration = db.Column(db.DateTime, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class ActivityLog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    action = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=True)
    ip_address = db.Column(db.String(45), nullable=True)
    user_agent = db.Column(db.Text, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    user = db.relationship('User', backref='activity_logs')

# New models for enhanced cooperative management
class RegistrationFee(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    amount = db.Column(db.Float, default=1000.0, nullable=False)  # Registration fee amount
    status = db.Column(db.String(20), default='pending', nullable=False)  # pending, paid, waived
    payment_method = db.Column(db.String(20), nullable=True)
    transaction_reference = db.Column(db.String(100), nullable=True)
    paid_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    paid_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    user = db.relationship('User', backref='registration_fees')
    payer = db.relationship('User', foreign_keys=[paid_by])

class MemberApproval(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    approved_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    status = db.Column(db.String(20), default='pending', nullable=False)  # pending, approved, rejected
    rejection_reason = db.Column(db.Text, nullable=True)
    notes = db.Column(db.Text, nullable=True)
    approved_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    user = db.relationship('User', foreign_keys=[user_id], backref='approval_requests')
    approver = db.relationship('User', foreign_keys=[approved_by])

class IDCard(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    card_number = db.Column(db.String(20), unique=True, nullable=False)
    issue_date = db.Column(db.DateTime, default=datetime.utcnow)
    expiry_date = db.Column(db.DateTime, nullable=True)
    status = db.Column(db.String(20), default='active', nullable=False)  # active, expired, revoked
    qr_code = db.Column(db.String(255), nullable=True)  # QR code for verification
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    user = db.relationship('User', backref='id_cards')

class Insurance(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    insurance_type = db.Column(db.String(50), nullable=False)  # group_life, health, spouse, kids
    policy_number = db.Column(db.String(50), nullable=True)
    coverage_amount = db.Column(db.Float, nullable=True)
    premium_amount = db.Column(db.Float, nullable=True)
    status = db.Column(db.String(20), default='active', nullable=False)  # active, expired, cancelled
    start_date = db.Column(db.DateTime, nullable=True)
    end_date = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    user = db.relationship('User', backref='insurance_policies')

class Referral(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    referrer_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    referred_email = db.Column(db.String(120), nullable=False)
    referred_name = db.Column(db.String(100), nullable=True)
    referred_phone = db.Column(db.String(20), nullable=True)
    status = db.Column(db.String(20), default='pending', nullable=False)  # pending, registered, bonus_paid
    bonus_amount = db.Column(db.Float, nullable=True)
    bonus_paid_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    referrer = db.relationship('User', foreign_keys=[referrer_id], backref='referrals_made')

class CDF(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    amount = db.Column(db.Float, nullable=False)
    purpose = db.Column(db.Text, nullable=False)
    status = db.Column(db.String(20), default='pending', nullable=False)  # pending, approved, disbursed
    approved_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    approved_at = db.Column(db.DateTime, nullable=True)
    disbursed_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relationships
    user = db.relationship('User', backref='cdf_applications')
    approver = db.relationship('User', foreign_keys=[approved_by])

with app.app_context():
    db.create_all()

# Blueprints disabled to avoid circular imports - routes are now inline

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

def generate_registration_number():
    last_user = User.query.order_by(User.id.desc()).first()
    if last_user and last_user.registration_number:
        last_num = int(last_user.registration_number[3:])
        new_num = last_num + 1
    else:
        new_num = 1
    return 'NLB' + f"{new_num:06d}"

def send_email(subject, recipient, html_body):
    try:
        msg = Message(
            subject,
            sender=app.config['MAIL_USERNAME'],
            recipients=[recipient]
        )
        msg.html = html_body
        mail.send(msg)
        return True
    except Exception as e:
        print('Email sending failed: ' + str(e))
        return False

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

# Routes
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        # Get all form fields
        full_name = request.form.get('full_name')
        email = request.form.get('email')
        phone = request.form.get('phone')
        password = request.form.get('password')
        gender = request.form.get('gender')
        state_of_residence = request.form.get('state_of_residence')
        lga_of_residence = request.form.get('lga_of_residence')
        work_study_address = request.form.get('work_study_address')
        expected_monthly_contribution = float(request.form.get('expected_monthly_contribution', 0))
        nin = request.form.get('nin')
        next_of_kin_name = request.form.get('next_of_kin_name')
        next_of_kin_mobile = request.form.get('next_of_kin_mobile')
        
        # Handle photo upload
        photo_path = None
        if 'photo' in request.files:
            photo = request.files['photo']
            if photo and photo.filename:
                filename = secure_filename(f"{full_name.replace(' ', '_')}_photo_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg")
                photo.save(os.path.join('static/uploads/photos', filename))
                photo_path = f"uploads/photos/{filename}"
        
        if User.query.filter_by(email=email).first():
            flash('Email already registered.', 'danger')
            return redirect(url_for('register'))
        
        registration_number = generate_registration_number()
        verification_token = secrets.token_urlsafe(32)
        
        # Create user with all new fields
        user = User(
            full_name=full_name,
            email=email,
            phone=phone,
            password_hash=generate_password_hash(password),
            registration_number=registration_number,
            verification_token=verification_token,
            gender=gender,
            state_of_residence=state_of_residence,
            lga_of_residence=lga_of_residence,
            work_study_address=work_study_address,
            expected_monthly_contribution=expected_monthly_contribution,
            nin=nin,
            next_of_kin_name=next_of_kin_name,
            next_of_kin_mobile=next_of_kin_mobile,
            photo_path=photo_path,
            is_approved=False,  # Requires admin approval
            is_verified=False
        )
        
        db.session.add(user)
        db.session.commit()
        
        # Create wallet for user
        wallet = Wallet(user_id=user.id, balance=0.0)
        db.session.add(wallet)
        
        # Create registration fee record
        registration_fee = RegistrationFee(
            user_id=user.id,
            amount=1000.0,  # ₦1,000 registration fee
            status='pending'
        )
        db.session.add(registration_fee)
        
        # Create member approval request
        approval_request = MemberApproval(
            user_id=user.id,
            status='pending'
        )
        db.session.add(approval_request)
        
        db.session.commit()
        
        # Send verification email
        verification_url = url_for('verify_email', token=verification_token, _external=True)
        html_body = f"""
        <h2>Welcome to National Medlab Cooperative!</h2>
        <p>Dear {full_name},</p>
        <p>Your registration is successful! Your registration number is: <strong>{registration_number}</strong></p>
        <p>Please click on link below to verify your email:</p>
        <p><a href="{verification_url}">Verify Email</a></p>
        <p><strong>Next Steps:</strong></p>
        <ol>
            <li>Verify your email address</li>
            <li>Pay registration fee of ₦1,000</li>
            <li>Wait for admin approval</li>
            <li>Receive your ID card and full account access</li>
        </ol>
        <p>Thank you for joining us!</p>
        """
        
        if send_email('Verify Your Email - National Medlab Cooperative', email, html_body):
            flash('Registration successful! Please check your email to verify your account.', 'success')
        else:
            # For development: provide manual verification link
            verification_url = url_for('verify_email', token=verification_token, _external=True)
            flash(f'Registration successful! Email verification could not be sent. For testing, <a href="{verification_url}" class="alert-link">click here to verify manually</a>', 'info')
        
        return redirect(url_for('login'))
    
    return render_template('register.html')

@app.route('/verify-email/<token>')
def verify_email(token):
    user = User.query.filter_by(verification_token=token).first()
    if user:
        user.is_verified = True
        user.verification_token = None
        db.session.commit()
        flash('Email verified successfully! You can now log in.', 'success')
    else:
        flash('Invalid verification link.', 'danger')
    return redirect(url_for('login'))

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form.get('email')
        password = request.form.get('password')
        
        user = User.query.filter_by(email=email).first()
        
        if user and check_password_hash(user.password_hash, password):
            if not user.is_verified:
                flash('Please verify your email before logging in.', 'warning')
                return redirect(url_for('login'))
            
            login_user(user)
            next_page = request.args.get('next')
            return redirect(next_page) if next_page else redirect(url_for('dashboard'))
        else:
            flash('Invalid email or password.', 'danger')
    
    return render_template('login.html')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('You have been logged out.', 'info')
    return redirect(url_for('index'))

@app.route('/forgot-password', methods=['GET', 'POST'])
def forgot_password():
    if request.method == 'POST':
        email = request.form.get('email')
        user = User.query.filter_by(email=email).first()
        
        if user:
            token = secrets.token_urlsafe(32)
            expiration = datetime.utcnow() + timedelta(minutes=30)
            
            password_reset = PasswordReset(
                email=email,
                token=token,
                expiration=expiration
            )
            
            db.session.add(password_reset)
            db.session.commit()
            
            reset_url = url_for('reset_password', token=token, _external=True)
            html_body = f"""
            <h2>Password Reset Request</h2>
            <p>Dear {user.full_name},</p>
            <p>Click the link below to reset your password:</p>
            <p><a href="{reset_url}">Reset Password</a></p>
            <p>This link will expire in 30 minutes.</p>
            """
            
            send_email('Password Reset - National Medlab Cooperative', email, html_body)
        
        flash('If an account with that email exists, a password reset link has been sent.', 'info')
        return redirect(url_for('login'))
    
    return render_template('forgot_password.html')

@app.route('/reset-password/<token>', methods=['GET', 'POST'])
def reset_password(token):
    password_reset = PasswordReset.query.filter_by(token=token).first()
    
    if not password_reset or password_reset.expiration < datetime.utcnow():
        flash('Invalid or expired reset link.', 'danger')
        return redirect(url_for('forgot_password'))
    
    if request.method == 'POST':
        password = request.form.get('password')
        user = User.query.filter_by(email=password_reset.email).first()
        
        if user:
            user.password_hash = generate_password_hash(password)
            db.session.delete(password_reset)
            db.session.commit()
            
            flash('Password reset successfully! You can now log in.', 'success')
            return redirect(url_for('login'))
    
    return render_template('reset_password.html')

@app.route('/dashboard')
@login_required
def dashboard():
    if current_user.role == 'Super Admin' or current_user.role == 'Admin':
        return redirect(url_for('admin_dashboard'))
    else:
        return redirect(url_for('user_dashboard'))

@app.route('/user-dashboard')
@login_required
def user_dashboard():
    wallet = Wallet.query.filter_by(user_id=current_user.id).first()
    contributions = Contribution.query.filter_by(user_id=current_user.id).order_by(Contribution.created_at.desc()).limit(5).all()
    loans = Loan.query.filter_by(user_id=current_user.id).order_by(Loan.created_at.desc()).limit(5).all()
    transactions = Transaction.query.filter_by(user_id=current_user.id).order_by(Transaction.created_at.desc()).limit(5).all()
    
    total_contributions = sum(c.amount for c in contributions if c.status == 'approved')
    
    # Calculate savings and shares amounts (80%/20% split)
    for contribution in contributions:
        if contribution.status == 'approved' and not contribution.savings_amount:
            contribution.savings_amount = contribution.amount * 0.8  # 80% savings
            contribution.shares_amount = contribution.amount * 0.2   # 20% shares
            db.session.commit()
    
    return render_template('user_dashboard_enhanced.html', 
                         wallet=wallet, 
                         contributions=contributions, 
                         loans=loans,
                         transactions=transactions,
                         total_contributions=total_contributions)

# User Contribution Routes
@app.route('/user/contribute', methods=['GET', 'POST'])
@login_required
def user_contribute():
    wallet = Wallet.query.filter_by(user_id=current_user.id).first()
    
    if request.method == 'POST':
        amount = float(request.form.get('amount'))
        payment_method = request.form.get('payment_method', 'manual')
        
        # Create contribution record
        contribution = Contribution(
            user_id=current_user.id,
            amount=amount,
            payment_method=payment_method,
            status='pending' if payment_method == 'manual' else 'completed'
        )
        
        db.session.add(contribution)
        db.session.commit()
        
        if payment_method == 'manual':
            flash('Contribution submitted for approval. Please wait for admin confirmation.', 'info')
        else:
            # Update wallet for manual contributions that are auto-approved
            wallet.balance += amount
            db.session.commit()
            
            # Create transaction record
            transaction = Transaction(
                user_id=current_user.id,
                type='deposit',
                amount=amount,
                status='completed',
                description='Online contribution',
                reference=f'CONT-{contribution.id}'
            )
            db.session.add(transaction)
            db.session.commit()
            
            flash('Contribution added successfully!', 'success')
        
        return redirect(url_for('user_dashboard'))
    
    return render_template('user/contribute.html', wallet=wallet)

@app.route('/user/loan-application', methods=['GET', 'POST'])
@login_required
def user_loan_application():
    wallet = Wallet.query.filter_by(user_id=current_user.id).first()
    
    if request.method == 'POST':
        amount = float(request.form.get('amount'))
        duration_months = int(request.form.get('duration_months'))
        purpose = request.form.get('purpose')
        interest_rate = 5.0  # 5% interest rate
        
        # Calculate total payable
        total_interest = (amount * interest_rate / 100) * (duration_months / 12)
        total_payable = amount + total_interest
        
        # Create loan application
        loan = Loan(
            user_id=current_user.id,
            amount=amount,
            interest_rate=interest_rate,
            duration_months=duration_months,
            purpose=purpose,
            total_payable=total_payable,
            status='pending'
        )
        
        db.session.add(loan)
        db.session.commit()
        
        flash('Loan application submitted successfully! Please wait for approval.', 'success')
        return redirect(url_for('user_dashboard'))
    
    return render_template('user/loan_application.html', wallet=wallet)

@app.route('/user/transactions')
@login_required
def user_transactions():
    transactions = Transaction.query.filter_by(user_id=current_user.id).order_by(Transaction.created_at.desc()).all()
    return render_template('user/transactions.html', transactions=transactions)

@app.route('/user/profile', methods=['GET', 'POST'])
@login_required
def user_profile():
    if request.method == 'POST':
        current_user.full_name = request.form.get('full_name')
        current_user.email = request.form.get('email')
        current_user.phone = request.form.get('phone')
        
        # Check if password change is requested
        old_password = request.form.get('old_password')
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')
        
        if old_password and new_password:
            if check_password_hash(current_user.password_hash, old_password):
                if new_password == confirm_password:
                    current_user.password_hash = generate_password_hash(new_password)
                    flash('Password updated successfully!', 'success')
                else:
                    flash('New passwords do not match!', 'danger')
                    return redirect(url_for('user_profile'))
            else:
                flash('Current password is incorrect!', 'danger')
                return redirect(url_for('user_profile'))
        
        db.session.commit()
        flash('Profile updated successfully!', 'success')
        return redirect(url_for('user_profile'))
    
    return render_template('user/profile.html')

@app.route('/admin-dashboard')
@login_required
@role_required('Super Admin', 'Admin', 'Treasurer', 'Loan Officer')
def admin_dashboard():
    total_users = User.query.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
    
    recent_transactions = Transaction.query.order_by(Transaction.created_at.desc()).limit(10).all()
    pending_loans = Loan.query.filter_by(status='pending').all()
    
    return render_template('admin_dashboard.html',
                         total_users=total_users,
                         total_contributions=total_contributions,
                         total_loans=total_loans,
                         recent_transactions=recent_transactions,
                         pending_loans=pending_loans)

# Admin User Management Routes
@app.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)

@app.route('/admin/users/<int:user_id>/view')
@login_required
@role_required('Super Admin', 'Admin', 'Treasurer', 'Loan Officer')
def view_user_details(user_id):
    user = User.query.get_or_404(user_id)
    
    # Get user's wallet
    wallet = Wallet.query.filter_by(user_id=user.id).first()
    
    # Get user's contributions
    contributions = Contribution.query.filter_by(user_id=user.id).order_by(Contribution.created_at.desc()).all()
    total_contributions = sum(c.amount for c in contributions if c.status == 'approved')
    pending_contributions = sum(c.amount for c in contributions if c.status == 'pending')
    
    # Get user's loans
    loans = Loan.query.filter_by(user_id=user.id).order_by(Loan.created_at.desc()).all()
    total_loans = sum(l.amount for l in loans if l.status == 'approved')
    pending_loans = sum(l.amount for l in loans if l.status == 'pending')
    
    # Get user's transactions
    transactions = Transaction.query.filter_by(user_id=user.id).order_by(Transaction.created_at.desc()).limit(20).all()
    
    # Calculate loan statistics
    approved_loans = [l for l in loans if l.status == 'approved']
    total_repayments = sum(sum(r.amount for r in l.repayments if r.status == 'completed') for l in approved_loans)
    
    return render_template('admin/user_details.html', 
                         user=user, 
                         wallet=wallet,
                         contributions=contributions,
                         loans=loans,
                         transactions=transactions,
                         total_contributions=total_contributions,
                         pending_contributions=pending_contributions,
                         total_loans=total_loans,
                         pending_loans=pending_loans,
                         total_repayments=total_repayments)

@app.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('manage_users'))
    
    return render_template('admin/edit_user.html', user=user)

@app.route('/admin/users/<int:user_id>/toggle-verification')
@login_required
@role_required('Super Admin', 'Admin')
def toggle_verification(user_id):
    user = User.query.get_or_404(user_id)
    user.is_verified = not user.is_verified
    db.session.commit()
    
    status = "verified" if user.is_verified else "unverified"
    flash(f'User {user.full_name} has been {status}.', 'success')
    return redirect(url_for('manage_users'))

@app.route('/admin/users/<int:user_id>/delete')
@login_required
@role_required('Super Admin')
def delete_user(user_id):
    user = User.query.get_or_404(user_id)
    
    if user.id == current_user.id:
        flash('You cannot delete your own account.', 'danger')
        return redirect(url_for('manage_users'))
    
    db.session.delete(user)
    db.session.commit()
    
    flash(f'User {user.full_name} has been deleted.', 'success')
    return redirect(url_for('manage_users'))

# Admin Contribution Management Routes
@app.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)

@app.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('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('manage_contributions'))

@app.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('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('manage_contributions'))

# Admin Loan Management Routes
@app.route('/admin/loans')
@login_required
@role_required('Super Admin', 'Admin', 'Loan Officer')
def manage_loans():
    pending_loans = Loan.query.filter_by(status='pending').order_by(Loan.created_at.desc()).all()
    approved_loans = Loan.query.filter_by(status='approved').order_by(Loan.created_at.desc()).all()
    rejected_loans = Loan.query.filter_by(status='rejected').order_by(Loan.created_at.desc()).all()
    
    return render_template('admin/loans.html', 
                         pending_loans=pending_loans,
                         approved_loans=approved_loans,
                         rejected_loans=rejected_loans)

@app.route('/admin/loans/<int:loan_id>/approve')
@login_required
@role_required('Super Admin', 'Admin', 'Loan Officer')
def approve_loan(loan_id):
    loan = Loan.query.get_or_404(loan_id)
    
    if loan.status != 'pending':
        flash('This loan cannot be approved.', 'danger')
        return redirect(url_for('manage_loans'))
    
    # Update loan status
    loan.status = 'approved'
    loan.approved_by = current_user.id
    loan.approved_at = datetime.utcnow()
    loan.due_date = datetime.utcnow() + timedelta(days=loan.duration_months * 30)
    
    # Disburse loan to user's wallet
    wallet = Wallet.query.filter_by(user_id=loan.user_id).first()
    wallet.balance += loan.amount
    
    # Create transaction record
    transaction = Transaction(
        user_id=loan.user_id,
        type='loan_disbursement',
        amount=loan.amount,
        status='completed',
        description=f'Loan disbursement - Ref: {loan.id}',
        reference=f'LOAN-{loan.id}'
    )
    
    db.session.add(transaction)
    db.session.commit()
    
    flash(f'Loan of ₦{loan.amount:.2f} has been approved and disbursed to {loan.user.full_name}.', 'success')
    return redirect(url_for('manage_loans'))

@app.route('/admin/loans/<int:loan_id>/reject')
@login_required
@role_required('Super Admin', 'Admin', 'Loan Officer')
def reject_loan(loan_id):
    loan = Loan.query.get_or_404(loan_id)
    
    if loan.status != 'pending':
        flash('This loan cannot be rejected.', 'danger')
        return redirect(url_for('manage_loans'))
    
    loan.status = 'rejected'
    loan.approved_by = current_user.id
    loan.approved_at = datetime.utcnow()
    
    db.session.commit()
    
    flash(f'Loan application from {loan.user.full_name} has been rejected.', 'info')
    return redirect(url_for('manage_loans'))

# Member Approval Gateway Routes
@app.route('/admin/approvals')
@login_required
@role_required('Super Admin', 'Admin')
def manage_approvals():
    pending_users = User.query.filter_by(is_approved=False, is_verified=True).all()
    return render_template('admin/approvals.html', users=pending_users)

@app.route('/admin/approvals/<int:user_id>/approve')
@login_required
@role_required('Super Admin', 'Admin')
def approve_member(user_id):
    user = User.query.get_or_404(user_id)
    
    if user.is_approved:
        flash('Member is already approved.', 'warning')
        return redirect(url_for('manage_approvals'))
    
    # Update user status
    user.is_approved = True
    user.activation_date = datetime.utcnow()
    
    # Update approval request
    approval = MemberApproval.query.filter_by(user_id=user_id).first()
    if approval:
        approval.status = 'approved'
        approval.approved_by = current_user.id
        approval.approved_at = datetime.utcnow()
    
    # Generate ID card
    card_number = 'NLB-ID-' + user.registration_number
    id_card = IDCard(
        user_id=user.id,
        card_number=card_number,
        expiry_date=datetime.utcnow() + timedelta(days=1095),  # 3 years validity
        status="active"
    )
    db.session.add(id_card)
    
    
    db.session.commit()
    
    flash('Member ' + user.full_name + ' has been approved and activated!', 'success')
    return redirect(url_for('manage_approvals'))
@app.route('/admin/approvals/<int:user_id>/reject')
@login_required
@role_required('Super Admin', 'Admin')
def reject_member(user_id):
    user = User.query.get_or_404(user_id)
    rejection_reason = request.form.get('rejection_reason', '')
    
    if user.is_approved:
        flash('Member is already approved.', 'warning')
        return redirect(url_for('manage_approvals'))
    
    # Update user status
    user.is_approved = False
    
    # Update approval request
    approval = MemberApproval.query.filter_by(user_id=user_id).first()
    if approval:
        approval.status = 'rejected'
        approval.approved_by = current_user.id
        approval.approved_at = datetime.utcnow()()
        approval.rejection_reason = rejection_reason
    
    db.session.commit()
    
    flash(f'Member {user.full_name} has been rejected.', 'info')
    return redirect(url_for('manage_approvals'))

@app.route('/admin/registration-fees')
@login_required
@role_required('Super Admin', 'Admin')
def manage_registration_fees():
    pending_fees = RegistrationFee.query.filter_by(status='pending').all()
    paid_fees = RegistrationFee.query.filter_by(status='paid').all()
    return render_template('admin/registration_fees.html', pending_fees=pending_fees, paid_fees=paid_fees)

@app.route('/admin/registration-fees/<int:fee_id>/confirm')
@login_required
@role_required('Super Admin', 'Admin')
def confirm_registration_fee(fee_id):
    fee = RegistrationFee.query.get_or_404(fee_id)
    
    if fee.status != 'pending':
        flash('This registration fee has already been processed.', 'warning')
        return redirect(url_for('manage_registration_fees'))
    
    fee.status = 'paid'
    fee.paid_by = current_user.id
    fee.paid_at = datetime.utcnow()
    
    db.session.commit()
    
    flash(f'Registration fee for {fee.user.full_name} has been confirmed as paid.', 'success')
    return redirect(url_for('manage_registration_fees'))

if __name__ == '__main__':
    app.run(debug=True)
