"""
Run maintenance jobs registered with Entrypoint.contribute_to_maintenance

A job is a dotted modules path to a function that takes no argument and
will mark the maintenance job as completed when finishing without errors.
Jobs results are collected in Maintenance models.
Jobs that do not return results will run every deployment.
"""

from django.core.management.base import BaseCommand
from django.db import OperationalError, ProgrammingError

from ocyan.core.plugins import get_maintenances

from ocyan.main.models import Maintenance


class Command(BaseCommand):
    help = __doc__

    def add_arguments(self, parser):
        parser.add_argument("--list", action="store_true", help="Show maintenance jobs")
        parser.add_argument(
            "--force",
            help="force rerunning an allready ran job, requires maintenance job key, try --list",
            action="append",
        )

    def handle(self, *args, **options):
        jobs = get_maintenances()
        if options["list"]:
            open_maintenances = [
                henk.key for henk in Maintenance.objects.open_maintenance(jobs)
            ]
            for job in jobs:
                if job in open_maintenances:
                    self.stdout.write("%s: open" % job)
                else:
                    self.stdout.write("%s: completed" % job)

        elif options["force"]:
            for job in options["force"]:
                try:
                    Maintenance.objects.get(key=job).run()
                except (OperationalError, ProgrammingError, Maintenance.DoesNotExist):
                    Maintenance(key=job).run()
        else:
            for job in Maintenance.objects.open_maintenance(jobs):
                job.run()
