import os
import sqlalchemy
from flask import Flask
from models import db


def database_uri() -> sqlalchemy.engine.url.URL:
    """
    A function to build the database connection string, using environment
    variable settings.
    """

    # If the connection string has been given, use it.
    url = os.environ.get("DB_CONNECTION_STRING", default="")
    if len(url) != 0:
        return url

    # Create a new DB connection string from components.
    host=os.environ.get("DB_SERVER", default="127.0.0.1")
    username = os.environ.get("DB_USER", default="none")
    username = f"{username}@{host}"

    url = sqlalchemy.engine.url.URL.create(
        drivername=os.environ.get("DB_DRIVER", default="mysql+pymysql"),
        username=username,
        password=os.environ.get("DB_PASSWORD", default="none"),
        host=host,
        port=os.environ.get("DB_PORT", default="3306"),
        database=os.environ.get("DB_NAME", default="mydb"))

    return url


def database_connection_args() -> dict:
    """
    A function to build the connection arguments, which are associated
    with an SSL connection.
    """
    connection_args = {}

    # Check for a SSL certificate.
    ssl_cert_file = os.environ.get("DB_SSL_CERT", default=None)
    if ssl_cert_file is not None:
        connection_args.update({
            'ssl': {'ca': ssl_cert_file}
        })

    return connection_args


def create_app(test_config: dict = {}):
    """
    A factory function to create a Flask app.
    """
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = database_uri()
    connection_args = database_connection_args()
    if len(connection_args) > 0:
        app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {"connect_args": connection_args}
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    if len(test_config) > 0:
        app.config.update(test_config)
    with app.app_context():
        db.init_app(app)
        db.create_all()
    from routes import books_bp
    app.register_blueprint(books_bp)
    return app


if __name__ == '__main__':
    """
    A test program to create one running Flask app.
    """
    app = create_app()
    svc_host = os.environ.get("SVC_HOST", default=None)
    app.run(debug=True, host=svc_host)