"""_____________________________________________________________________

:PROJECT: lara-django

*lara-django-database maintainance*

:details: lara-django-database maintainance


:authors: mark doerr (mark@uni-greifswald.de)

:date: (creation)          20220927

.. note:: -
.. todo:: -
________________________________________________________________________

**Copyright**:
  This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
  INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

  For further Information see LICENSE file that comes with this distribution.
________________________________________________________________________
"""

__version__ = "0.0.1"

import os
import logging
from pathlib import Path


from django.core.management.base import BaseCommand, CommandError
from django.core.management import call_command
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style, no_style
from django.db import DEFAULT_DB_ALIAS, connections
from django.conf import settings

from ..simpleinstall import query_yes_no


class Command(BaseCommand):
    """see https://docs.djangoproject.com/en/1.9/howto/custom-management-commands/ for more details
       using now new argparse mechanism of django > 1.8
    """
    logging.basicConfig(format='%(levelname)s| %(module)s.%(funcName)s:%(message)s',
                        level=logging.DEBUG)  # level=logging.ERROR

    help = 'DJANGO database maintainace.'

    def add_arguments(self, parser):
        """ command line arguments s. https://docs.python.org/2/library/argparse.html#module-argparse """

        # defining named commandline arguments
        parser.add_argument('--delete-database',
                            action='store_true',
                            help='delete DJANGO database')
        parser.add_argument('--migrations',
                            action='store_true',
                            help='make all migrations')
        parser.add_argument('--delete-migrations',
                            action='store_true',
                            help='delete all migrations')

        parser.add_argument(
            '--force', action='store_true',
            help='Force execution of the initialization process.',
        )

    def handle(self, *args, **options):
        """Dispatcher based on commandline arguments/options"""

        if options['migrations']:
            self.make_all_migrations()

        if options['delete_migrations']:
            self.delete_all_migrations()

        if options['delete_database']:
            self.delete_db()

    def make_all_migrations(self):

        call_command('wait_for_db')

        call_command('makemigrations')

        if self.num_migrations() > 0:
            logging.debug("unresolved migrations")
            self.make_app_migrations()

        call_command('migrate')

    def delete_all_migrations(self, force=False):
        # TODO: not working yet
        for app in settings.LARA_APPS:
            try:
                #logging.debug("migrating : {}".format(app))
                # os.remove(settings.)
                migration_dir = os.path.join(
                    settings.BASE_DIR, '..', '..', app, 'migrations/*')
                print("remove migrations of app", app,
                      " in migr. dir:",  migration_dir)
            except FileNotFoundError as err:
                logging.error(
                    "Migrations dir {0} not found ! [{1}]".format(migration_dir, err))

    def delete_db(self, force=False):
        "removing database"
        logging.info("rather use:\n lara-django-dev reset_db")

        if force:
            del_db = True
        else:
            db_filename = settings.DATABASES['default']['NAME']

            del_db = query_yes_no("Shall I REALLY delete the LARA database\n{}\nand re-initialise it ?".format(db_filename),
                                  default_answer="no", help="This removes the sqlite database and fills it with fresh data")
        if del_db:
            #~ run("pwd; echo deleting db...")

            try:
                logging.debug("deleting db [{}]...".format(db_filename))
                # os.remove(db_filename)
                #~ call_command('flush')
                #~ call_command('migrate')
                # try flush instead !! https://docs.djangoproject.com/en/2.1/ref/django-admin/#django-admin-dumpdata
            except FileNotFoundError as err:
                logging.error(
                    "Database {0} not found ! [{1}]".format(db_filename, err))

    def num_migrations(self):
        """return number of migrations
           :param options:
        """
        from django.db.migrations.executor import MigrationExecutor
        try:
            executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
        except ImproperlyConfigured:
            # No databases are configured (or the dummy one)
            return

        plan = executor.migration_plan(executor.loader.graph.leaf_nodes())
        if plan:
            return len(plan)
        else:
            return 0

    def make_app_migrations(self, options=None):
        """make individual app migrations
           s. https://docs.djangoproject.com/en/2.0/ref/django-admin/
           :param options:
        """
        #db_filename = settings.DATABASES['default']['NAME']
        for app in settings.LARA_APPS:
            logging.debug("migrating : {}".format(app))
            call_command('makemigrations', app)

    def load_fixtures(self, options=None):
        """load fixtures the LARA database
           :param options:
        """
        for fixture in settings.FIXTURES:
            call_command('loaddata', fixture)
