python
from flask import Flask, render_template, request, redirect, url_for, session, flash
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from functools import wraps
from datetime import datetime
import os

app = Flask(__name__)

# ============================================================
# CONFIGURATION
# ============================================================

app.config["SECRET_KEY"] = os.getenv(
    "SECRET_KEY",
    "change-this-secret-key"
)

app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv(
    "DATABASE_URL",
    "postgresql://postgres:postgres@localhost:5432/python_app"
)

app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db = SQLAlchemy(app)


# ============================================================
# DATABASE MODEL
# ============================================================

class User(db.Model):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    full_name = db.Column(db.String(150), nullable=False)
    username = db.Column(db.String(100), unique=True, nullable=False)
    email = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(255), nullable=False)
    role = db.Column(db.String(50), nullable=False, default="User")
    status = db.Column(db.Boolean, default=True)
    created_at = db.Column(
        db.DateTime,
        default=datetime.utcnow
    )

    def __repr__(self):
        return f"<User {self.username}>"


# ============================================================
# LOGIN DECORATOR
# ============================================================

def login_required(function):

    @wraps(function)
    def decorated_function(*args, **kwargs):

        if "user_id" not in session:
            flash("Please login first.", "warning")
            return redirect(url_for("login"))

        return function(*args, **kwargs)

    return decorated_function


# ============================================================
# ADMIN DECORATOR
# ============================================================

def admin_required(function):

    @wraps(function)
    def decorated_function(*args, **kwargs):

        if "user_id" not in session:
            flash("Please login first.", "warning")
            return redirect(url_for("login"))

        user = db.session.get(User, session["user_id"])

        if not user or user.role != "Administrator":
            flash("Administrator access required.", "danger")
            return redirect(url_for("dashboard"))

        return function(*args, **kwargs)

    return decorated_function


# ============================================================
# HOME
# ============================================================

@app.route("/")
def index():

    if "user_id" in session:
        return redirect(url_for("dashboard"))

    return redirect(url_for("login"))


# ============================================================
# LOGIN
# ============================================================

@app.route("/login", methods=["GET", "POST"])
def login():

    if request.method == "POST":

        username = request.form.get("username", "").strip()
        password = request.form.get("password", "")

        user = User.query.filter_by(
            username=username
        ).first()

        if user and user.status and check_password_hash(
            user.password,
            password
        ):

            session["user_id"] = user.id
            session["username"] = user.username
            session["full_name"] = user.full_name
            session["role"] = user.role

            flash("Login successful.", "success")

            return redirect(url_for("dashboard"))

        flash(
            "Invalid username or password.",
            "danger"
        )

    return render_template("login.html")


# ============================================================
# LOGOUT
# ============================================================

@app.route("/logout")
def logout():

    session.clear()

    flash(
        "You have been logged out.",
        "success"
    )

    return redirect(url_for("login"))


# ============================================================
# DASHBOARD
# ============================================================

@app.route("/dashboard")
@login_required
def dashboard():

    total_users = User.query.count()

    active_users = User.query.filter_by(
        status=True
    ).count()

    inactive_users = User.query.filter_by(
        status=False
    ).count()

    administrators = User.query.filter_by(
        role="Administrator"
    ).count()

    recent_users = User.query.order_by(
        User.created_at.desc()
    ).limit(5).all()

    return render_template(
        "dashboard.html",
        total_users=total_users,
        active_users=active_users,
        inactive_users=inactive_users,
        administrators=administrators,
        recent_users=recent_users
    )


# ============================================================
# USERS
# ============================================================

@app.route("/users")
@admin_required
def users():

    users = User.query.order_by(
        User.created_at.desc()
    ).all()

    return render_template(
        "users.html",
        users=users
    )


# ============================================================
# ADD USER
# ============================================================

@app.route("/users/add", methods=["GET", "POST"])
@admin_required
def add_user():

    if request.method == "POST":

        full_name = request.form.get(
            "full_name",
            ""
        ).strip()

        username = request.form.get(
            "username",
            ""
        ).strip()

        email = request.form.get(
            "email",
            ""
        ).strip()

        password = request.form.get(
            "password",
            ""
        )

        role = request.form.get(
            "role",
            "User"
        )

        if not full_name or not username or not email or not password:

            flash(
                "All required fields must be completed.",
                "danger"
            )

            return redirect(
                url_for("add_user")
            )

        existing_username = User.query.filter_by(
            username=username
        ).first()

        if existing_username:

            flash(
                "Username already exists.",
                "danger"
            )

            return redirect(
                url_for("add_user")
            )

        existing_email = User.query.filter_by(
            email=email
        ).first()

        if existing_email:

            flash(
                "Email address already exists.",
                "danger"
            )

            return redirect(
                url_for("add_user")
            )

        new_user = User(
            full_name=full_name,
            username=username,
            email=email,
            password=generate_password_hash(password),
            role=role,
            status=True
        )

        db.session.add(new_user)
        db.session.commit()

        flash(
            "User created successfully.",
            "success"
        )

        return redirect(
            url_for("users")
        )

    return render_template("add_user.html")


# ============================================================
# DELETE USER
# ============================================================

@app.route("/users/delete/<int:user_id>", methods=["POST"])
@admin_required
def delete_user(user_id):

    user = db.session.get(
        User,
        user_id
    )

    if not user:

        flash(
            "User not found.",
            "danger"
        )

        return redirect(
            url_for("users")
        )

    if user.id == session["user_id"]:

        flash(
            "You cannot delete your own account.",
            "danger"
        )

        return redirect(
            url_for("users")
        )

    db.session.delete(user)
    db.session.commit()

    flash(
        "User deleted successfully.",
        "success"
    )

    return redirect(
        url_for("users")
    )


# ============================================================
# TOGGLE USER STATUS
# ============================================================

@app.route("/users/toggle/<int:user_id>", methods=["POST"])
@admin_required
def toggle_user(user_id):

    user = db.session.get(
        User,
        user_id
    )

    if not user:

        flash(
            "User not found.",
            "danger"
        )

        return redirect(
            url_for("users")
        )

    if user.id == session["user_id"]:

        flash(
            "You cannot deactivate your own account.",
            "danger"
        )

        return redirect(
            url_for("users")
        )

    user.status = not user.status

    db.session.commit()

    flash(
        "User status updated.",
        "success"
    )

    return redirect(
        url_for("users")
    )


# ============================================================
# CREATE DATABASE TABLES
# ============================================================

@app.cli.command("init-db")
def init_db():

    db.create_all()

    print("Database tables created successfully.")


# ============================================================
# CREATE DEFAULT ADMINISTRATOR
# ============================================================

@app.cli.command("create-admin")
def create_admin():

    existing = User.query.filter_by(
        username="admin"
    ).first()

    if existing:

        print("Administrator account already exists.")
        return

    admin = User(
        full_name="System Administrator",
        username="admin",
        email="admin@example.com",
        password=generate_password_hash("admin123"),
        role="Administrator",
        status=True
    )

    db.session.add(admin)
    db.session.commit()

    print("Administrator created.")
    print("Username: admin")
    print("Password: admin123")


# ============================================================
# APPLICATION START
# ============================================================

if __name__ == "__main__":

    app.run(
        host="0.0.0.0",
        port=5000,
        debug=True
    )

