"""Plugin migration management using Alembic."""

from pathlib import Path
from typing import Optional
import logging
import subprocess
import sys

logger = logging.getLogger(__name__)


class PluginMigrationManager:
    """
    Manages database migrations for plugins.
    Each plugin has its own migrations directory.
    """

    def __init__(self, plugins_dir: Path, database_url: str):
        self.plugins_dir = plugins_dir
        self.database_url = database_url

    def get_migrations_dir(self, plugin_name: str) -> Optional[Path]:
        """Get migrations directory for a plugin."""
        migrations_dir = self.plugins_dir / plugin_name / 'migrations'
        if migrations_dir.exists():
            return migrations_dir
        return None

    def run_plugin_migrations(
        self,
        plugin_name: str,
        revision: str = 'head'
    ) -> bool:
        """
        Run migrations for a plugin.

        Uses flask db upgrade with the plugin's migrations directory.
        """
        migrations_dir = self.get_migrations_dir(plugin_name)

        if not migrations_dir:
            logger.info(f"No migrations directory for plugin {plugin_name}")
            return True  # No migrations to run

        try:
            # Use alembic directly with plugin's migrations
            from alembic.config import Config
            from alembic import command

            config = Config()
            config.set_main_option('script_location', str(migrations_dir))
            config.set_main_option('sqlalchemy.url', self.database_url)

            # Use plugin-specific version table
            config.set_main_option(
                'version_table',
                f'alembic_version_{plugin_name}'
            )

            command.upgrade(config, revision)
            logger.info(f"Migrations completed for {plugin_name}")
            return True

        except ImportError:
            # Fallback to subprocess if alembic not available in context
            logger.warning("Using subprocess for migrations")
            return self._run_migrations_subprocess(plugin_name, revision)

        except Exception as e:
            logger.error(f"Migration failed for {plugin_name}: {e}")
            return False

    def _run_migrations_subprocess(
        self,
        plugin_name: str,
        revision: str = 'head'
    ) -> bool:
        """Run migrations via subprocess as fallback."""
        migrations_dir = self.get_migrations_dir(plugin_name)
        if not migrations_dir:
            return True

        try:
            result = subprocess.run(
                [
                    sys.executable, '-m', 'alembic',
                    '-c', str(migrations_dir / 'alembic.ini'),
                    'upgrade', revision
                ],
                capture_output=True,
                text=True,
                env={
                    **dict(__import__('os').environ),
                    'DATABASE_URL': self.database_url
                }
            )

            if result.returncode != 0:
                logger.error(f"Migration error: {result.stderr}")
                return False

            return True

        except Exception as e:
            logger.error(f"Migration subprocess failed: {e}")
            return False

    def downgrade_plugin(
        self,
        plugin_name: str,
        revision: str = 'base'
    ) -> bool:
        """
        Downgrade/rollback plugin migrations.
        """
        migrations_dir = self.get_migrations_dir(plugin_name)

        if not migrations_dir:
            return True

        try:
            from alembic.config import Config
            from alembic import command

            config = Config()
            config.set_main_option('script_location', str(migrations_dir))
            config.set_main_option('sqlalchemy.url', self.database_url)
            config.set_main_option(
                'version_table',
                f'alembic_version_{plugin_name}'
            )

            command.downgrade(config, revision)
            logger.info(f"Downgrade completed for {plugin_name}")
            return True

        except Exception as e:
            logger.error(f"Downgrade failed for {plugin_name}: {e}")
            return False

    def get_current_revision(self, plugin_name: str) -> Optional[str]:
        """Get current migration revision for a plugin."""
        migrations_dir = self.get_migrations_dir(plugin_name)
        if not migrations_dir:
            return None

        try:
            from alembic.config import Config
            from alembic.script import ScriptDirectory

            config = Config()
            config.set_main_option('script_location', str(migrations_dir))

            script = ScriptDirectory.from_config(config)
            return script.get_current_head()

        except Exception:
            return None

    def has_pending_migrations(self, plugin_name: str) -> bool:
        """Check if plugin has pending migrations."""
        # Simplified check - would need DB connection for full check
        migrations_dir = self.get_migrations_dir(plugin_name)
        if not migrations_dir:
            return False

        versions_dir = migrations_dir / 'versions'
        if not versions_dir.exists():
            return False

        # Check if there are any migration files
        migration_files = list(versions_dir.glob('*.py'))
        return len(migration_files) > 0
