"""
Run scheduled jobs.
Not meant for running job at precise time (+- 1h)
"""
import time

import arrow

from app.config import JOB_ONBOARDING_1
from app.email_utils import (
    send_email,
    render,
)
from app.extensions import db
from app.log import LOG
from app.models import (
    User,
    Job,
)
from server import create_app


# fix the database connection leak issue
# use this method instead of create_app
def new_app():
    app = create_app()

    @app.teardown_appcontext
    def shutdown_session(response_or_exc):
        # same as shutdown_session() in flask-sqlalchemy but this is not enough
        db.session.remove()

        # dispose the engine too
        db.engine.dispose()

    return app


def onboarding_1(user):
    if not user.activated:
        LOG.d("User %s is not activated", user)
        return

    if not user.notification:
        LOG.d("User %s disable notification setting", user)
        return

    send_email(
        user.email,
        f"Do you know you can send emails to anyone from your alias?",
        render("com/onboarding-1.txt", user=user),
        render("com/onboarding-1.html", user=user),
    )


if __name__ == "__main__":
    while True:
        # run a job 1h earlier or later is not a big deal ...
        min_dt = arrow.now().shift(hours=-1)
        max_dt = arrow.now().shift(hours=1)

        app = new_app()

        with app.app_context():
            for job in Job.query.filter(
                Job.taken == False, Job.run_at > min_dt, Job.run_at <= max_dt
            ).all():
                LOG.d("Take job %s", job)

                # mark the job as taken, whether it will be executed successfully or not
                job.taken = True
                db.session.commit()

                if job.name == JOB_ONBOARDING_1:
                    user_id = job.payload.get("user_id")
                    user = User.get(user_id)

                    # user might delete their account in the meantime
                    if user:
                        LOG.d("run onboarding_1 for user %s", user)
                        onboarding_1(user)
                else:
                    LOG.error("Unknown job name %s", job.name)

        time.sleep(10)
