from logging import getLogger
from pathlib import Path

from django.core.management import BaseCommand, CommandParser
from django.db import DEFAULT_DB_ALIAS, connections
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.recorder import MigrationRecorder

logger = getLogger(__name__)


class Command(BaseCommand):
    help = "Export migrations to SQL"

    def add_arguments(self, parser: CommandParser) -> None:
        parser.add_argument("app", action="store", type=str, help="Django app")
        parser.add_argument(
            "from_id", action="store", type=int, help="Migration id to start from"
        )
        parser.add_argument(
            "--output-folder",
            action="store",
            default="export_migrations",
            help="Output folder",
        )

    def handle(self, **options) -> None:
        # Get the database we're operating from
        connection = connections[DEFAULT_DB_ALIAS]

        # Load up a loader to get all the migration data, but don't replace migrations
        loader = MigrationLoader(connection, replace_migrations=False)

        # Create output folder
        output_folder = Path(options["output_folder"])
        output_folder.mkdir(parents=True, exist_ok=True)

        # Find migration record to start from
        migration_match = MigrationRecorder.Migration.objects.get(
            app=options["app"],
            name__istartswith=f"{options['from_id']:04d}",
        )

        migrations_to_export = MigrationRecorder.Migration.objects.filter(
            id__gte=migration_match.id,
            app=options["app"],
        )

        for migration in migrations_to_export:
            migration: MigrationRecorder.Migration

            logger.info(f"Exporting {migration.id}")

            # Generate SQL
            target = (migration.app, migration.name)
            plan = [(loader.graph.nodes[target], False)]
            sql_statements = loader.collect_sql(plan)

            # Write SQL to file
            output_file = (
                output_folder
                / f"{migration.id:04d}.{migration.app}.{migration.name}.sql"
            )
            output_file.write_text("\n".join(sql_statements))
