import os

from flask import Flask
from flask_migrate import Migrate
from werkzeug.security import generate_password_hash
from extensions import db, login_manager, csrf

from routes.auth import auth_bp
from routes.category import category_bp
from routes.product import product_bp
from routes.cart import cart_bp
from routes.checkout import checkout_bp
from routes.dashboard import dashboard_bp
from routes.home import home_bp
from routes.reviews import reviews_bp
from models import User
from routes.orders import orders_bp
from routes.settings import settings_bp
from routes.stock import stock_bp
from routes.performance import performance_bp


# =========================================================
# REQUIRED ENVIRONMENT VARIABLE
# =========================================================

def get_required_env(name):

    value = os.environ.get(name)

    if not value:
        raise RuntimeError(
            f"{name} environment variable is not configured."
        )

    return value


# =========================================================
# SEED WEBSITE OWNER
# =========================================================

def seed_owner():

    owner = User.query.filter_by(
        role="owner"
    ).first()

    # Owner already exists.
    # Do not create another one.
    if owner:
        return

    owner_password = get_required_env(
        "OWNER_PASSWORD"
    )

    owner = User(
        username="owner",
        password_hash=generate_password_hash(
            owner_password
        ),
        role="owner",
        is_active=True
    )

    db.session.add(owner)

    db.session.commit()

    print(
        "Owner account created successfully."
    )


# =========================================================
# CREATE APPLICATION
# =========================================================

def create_app():

    app = Flask(__name__)

    # ---------------------------------------------------------
    # APPLICATION CONFIGURATION
    # ---------------------------------------------------------

    app.config["SECRET_KEY"] = get_required_env(
        "SECRET_KEY"
    )

    app.config["SQLALCHEMY_DATABASE_URI"] = (
        get_required_env(
            "DATABASE_URL"
        )
    )

    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

    # ---------------------------------------------------------
    # SESSION COOKIE SECURITY
    # ---------------------------------------------------------

    app.config["SESSION_COOKIE_HTTPONLY"] = True

    app.config["SESSION_COOKIE_SAMESITE"] = "Lax"

    app.config["SESSION_COOKIE_SECURE"] = (
        os.environ.get(
            "SESSION_COOKIE_SECURE",
            "False"
        ).lower() == "true"
    )

    app.config["PERMANENT_SESSION_LIFETIME"] = 7200

    # ---------------------------------------------------------
    # UPLOAD SETTINGS
    # ---------------------------------------------------------

    app.config["MAX_CONTENT_LENGTH"] = (
        50 * 1024 * 1024
    )

    app.config["UPLOAD_FOLDER"] = os.path.join(
        os.path.dirname(
            os.path.abspath(__file__)
        ),
        "static",
        "uploads"
    )

    # ---------------------------------------------------------
    # EXTENSIONS
    # ---------------------------------------------------------

    db.init_app(app)
    login_manager.init_app(app)
    csrf.init_app(app)
    Migrate(app, db)

    # ---------------------------------------------------------
    # SEED INITIAL OWNER
    # ---------------------------------------------------------

    with app.app_context():

        seed_owner()

    # ---------------------------------------------------------
    # BLUEPRINTS
    # ---------------------------------------------------------

    app.register_blueprint(
        auth_bp
    )

    app.register_blueprint(
        category_bp
    )

    app.register_blueprint(
        product_bp
    )

    app.register_blueprint(
        cart_bp
    )

    app.register_blueprint(
        checkout_bp
    )

    app.register_blueprint(
        dashboard_bp
    )

    app.register_blueprint(
        home_bp
    )

    app.register_blueprint(
        reviews_bp
    )

    app.register_blueprint(
        orders_bp
    )

    app.register_blueprint(
        settings_bp
    )

    app.register_blueprint(
        stock_bp
    )

    app.register_blueprint(
        performance_bp
    )

    return app


# =========================================================
# APPLICATION INSTANCE
# =========================================================

app = create_app()


# =========================================================
# DEVELOPMENT SERVER
# =========================================================

if __name__ == "__main__":

    app.run(
        debug=True
    )