"""
Destroy the database and replace with a dump from a tar.gz file. Also import media files
"""

import os
import subprocess
import tarfile
import tempfile
from os.path import exists, join

from django.conf import settings
from django.core.management import call_command
from django.core.management.base import BaseCommand
from django.db import connection

from ocyan.core.fender import config

from ocyan.main import utils
from ocyan.main.signals import pre_import_destructive


class Command(BaseCommand):
    help = __doc__
    project = config.get("django", "name", "myproject")

    def add_arguments(self, parser):
        parser.add_argument("path", help="path to the tarbal")
        parser.add_argument(
            "--skip-db",
            action="store_true",
            default=False,
            help="Do not import the database",
        )
        parser.add_argument(
            "--skip-media",
            action="store_true",
            default=False,
            help="Do not import the media folder",
        )
        parser.add_argument(
            "--command",
            help="command to use for importing, default is loaddata",
            default="loaddata",
        )
        parser.add_argument(
            "--ignorenonexistent",
            "-i",
            action="store_true",
            dest="ignore",
            help="Ignores entries in the serialized data for fields that do not currently exist on the model.",
        )
        parser.add_argument(
            "--disable-constraint-checking",
            help="Disable constraint checking while importing, which helps when importing a broken database",
            action="store_true",
        )
        parser.add_argument(
            "--anon",
            action="store_true",
            help="anoymise user data using the destroy_userata command",
        )

    def handle(self, *args, **options):
        os.umask(0)
        with tempfile.TemporaryDirectory() as tmp:
            os.chmod(tmp, 0o777)
            with tarfile.open(options["path"]) as tar:
                tar.extractall(tmp)

                if options["skip_media"]:
                    self.stdout.write(self.style.WARNING("skipping media"))
                else:
                    if not exists(settings.MEDIA_ROOT):
                        os.mkdir(settings.MEDIA_ROOT)
                    subprocess.check_call(
                        [
                            "/usr/bin/rsync",
                            "--archive",
                            "--verbose",
                            join(tmp, self.project, "media", ""),
                            join(settings.MEDIA_ROOT, ""),
                        ]
                    )

                    if not exists(settings.STATIC_ROOT):
                        os.mkdir(settings.STATIC_ROOT)
                    subprocess.check_call(
                        [
                            "/usr/bin/rsync",
                            "--archive",
                            "--verbose",
                            join(tmp, self.project, "static", ""),
                            join(settings.STATIC_ROOT, ""),
                        ]
                    )

                if options["skip_db"]:
                    self.stdout.write(self.style.WARNING("skipping database"))
                else:
                    db_dump_path = join(tmp, self.project, "db.json")

                    with utils.disable_searchengine_updates():
                        call_command("flushall")
                        if options["disable_constraint_checking"]:
                            connection.disable_constraint_checking()
                        pre_import_destructive.send(sender=self.__class__)
                        command_args = [db_dump_path]
                        if options["ignore"]:
                            command_args.append("--ignorenonexistent")
                        call_command(options["command"], *command_args)
                        if options["disable_constraint_checking"]:
                            connection.enable_constraint_checking()

                        call_command("migrate", "--fake")

        if options["anon"]:
            call_command("destroy_userdata")

        self.stdout.write(self.style.SUCCESS("done."))
