import json
import os
import shutil
import tarfile
import tempfile
from os.path import dirname, exists, isdir, isfile, join

from django.conf import settings
from django.core import serializers
from django.core.management.base import BaseCommand
from django.db import transaction

from wagtail.images.models import Image
from wagtail.models import Page, get_page_models

from ocyan.core.fender import config

try:
    from rr.models import Template
except ImportError:
    from roadrunner.models import Template


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

    def add_arguments(self, parser):
        parser.add_argument("path", help="path to the tarbal")

    def handle(self, *args, **options):
        path = options["path"]
        if isfile(path):
            tarname = path
        elif isdir(path):
            tarname = join(path, "%s.tar.gz" % self.project)
        elif path.endswith("tar.gz"):
            tarname = path
        else:
            tarname = "%s.tar.gz" % path

        with tarfile.open(tarname, "w:gz") as tar:
            data = []

            with transaction.atomic():
                # Set revisions to None before exporting
                Page.objects.update(live_revision=None, latest_revision=None)

                # Export all models needed for wagtail
                for Model in [Template, Image] + get_page_models():
                    data.extend(
                        json.loads(
                            serializers.serialize(
                                "json",
                                Model.objects.all(),
                                use_natural_foreign_keys=True,
                                use_natural_primary_keys=True,
                            )
                        )
                    )

                # Rollback the transaction so the revisions are put back
                transaction.set_rollback(True)

            os.umask(0)
            with tempfile.TemporaryDirectory() as tmp:
                export_dir = join(tmp, self.project)
                os.chmod(tmp, 0o777)
                os.mkdir(export_dir, 0o777)

                # Write json output file
                db_dump_path = join(export_dir, "db.json")
                with open(db_dump_path, "w", encoding="utf-8") as f:
                    f.write(json.dumps(data, indent=4))

                # We export only the wagtail images since we don't want to tamper with the existing images
                wagtail_image_export_path = join(export_dir, "media")
                os.mkdir(wagtail_image_export_path, 0o777)
                for filepath in list(
                    Image.objects.all().values_list("file", flat=True)
                ):
                    temp_path = join(wagtail_image_export_path, filepath)
                    original_path = join(settings.MEDIA_ROOT, filepath)
                    directory = dirname(temp_path)
                    if not exists(directory):
                        os.makedirs(directory)
                    shutil.copy2(original_path, temp_path)

                tar.add(export_dir, arcname=self.project)
