"""
Django management command to migrate from tenant-filtered approach to schema separation.

This command:
1. Creates separate PostgreSQL schemas for each tenant
2. Migrates existing data from the default schema to tenant-specific schemas
3. Handles all models: Customer, Product, Category, Sale, etc.
"""

from django.core.management.base import BaseCommand
from django.db import connection
from tenants.models import Tenant
from tenants.schema_utils import (
    get_tenant_schema_name,
    create_tenant_schema,
    schema_exists,
    SchemaManager
)
import logging

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = 'Migrate from tenant-filtered approach to PostgreSQL schema separation'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Show what would be done without actually doing it',
        )
        parser.add_argument(
            '--force',
            action='store_true',
            help='Force migration even if schemas already exist',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']
        force = options['force']
        
        if dry_run:
            self.stdout.write(
                self.style.WARNING('DRY RUN MODE - No changes will be made')
            )

        # Get all tenants
        tenants = Tenant.objects.all()
        if not tenants.exists():
            self.stdout.write(
                self.style.ERROR('No tenants found. Create a tenant first.')
            )
            return

        self.stdout.write(f'Found {tenants.count()} tenant(s) to migrate')

        for tenant in tenants:
            self.migrate_tenant(tenant, dry_run, force)

        self.stdout.write(
            self.style.SUCCESS('Schema separation migration completed!')
        )

    def migrate_tenant(self, tenant, dry_run=False, force=False):
        """Migrate a single tenant to its own schema"""
        schema_name = get_tenant_schema_name(tenant.tenant_code)
        
        self.stdout.write(f'\n=== Migrating tenant: {tenant.name} (code: {tenant.tenant_code}) ===')
        self.stdout.write(f'Target schema: {schema_name}')

        if not dry_run:
            # Create the tenant schema
            try:
                created = create_tenant_schema(tenant.tenant_code)
                if created:
                    self.stdout.write(
                        self.style.SUCCESS(f'✓ Created schema: {schema_name}')
                    )
                else:
                    if force:
                        self.stdout.write(
                            self.style.WARNING(f'⚠ Schema {schema_name} already exists (continuing due to --force)')
                        )
                    else:
                        self.stdout.write(
                            self.style.ERROR(f'✗ Schema {schema_name} already exists. Use --force to continue.')
                        )
                        return  # Exit this tenant migration
            except Exception as e:
                self.stdout.write(
                    self.style.ERROR(f'✗ Failed to create schema {schema_name}: {e}')
                )
                return  # Exit this tenant migration

        # Migrate data for each app/model
        self.migrate_tenant_data(tenant, schema_name, dry_run)

    def migrate_tenant_data(self, tenant, schema_name, dry_run=False):
        """Migrate tenant data from default schema to tenant schema"""
        
        # Models to migrate with their table names
        models_to_migrate = [
            ('customers', 'customers_customer'),
            ('inventory', 'inventory_category'),
            ('inventory', 'inventory_product'),
            ('inventory', 'inventory_productimage'),
            ('inventory', 'inventory_batch'),
            ('sales', 'sales_sale'),
            ('sales', 'sales_saleitem'),
            ('sales', 'sales_salepayment'),
            # Add other models as needed
        ]

        with connection.cursor() as cursor:
            for app_name, table_name in models_to_migrate:
                try:
                    # Check if table exists in default schema
                    cursor.execute("""
                        SELECT EXISTS (
                            SELECT 1 FROM information_schema.tables 
                            WHERE table_schema = 'public' AND table_name = %s
                        )
                    """, [table_name])
                    
                    table_exists = cursor.fetchone()[0]
                    if not table_exists:
                        self.stdout.write(f'  - Skipping {table_name} (table not found)')
                        continue

                    # Check if table has tenant field (for old data)
                    cursor.execute("""
                        SELECT column_name 
                        FROM information_schema.columns 
                        WHERE table_schema = 'public' 
                        AND table_name = %s 
                        AND column_name = 'tenant_id'
                    """, [table_name])
                    
                    has_tenant_field = cursor.fetchone() is not None

                    if has_tenant_field:
                        # Migrate tenant-filtered data
                        self.migrate_filtered_data(cursor, tenant, table_name, schema_name, dry_run)
                    else:
                        # Migrate all data (for models that never had tenant fields)
                        self.migrate_all_data(cursor, table_name, schema_name, dry_run)

                except Exception as e:
                    self.stdout.write(
                        self.style.ERROR(f'  ✗ Error migrating {table_name}: {e}')
                    )

    def migrate_filtered_data(self, cursor, tenant, table_name, schema_name, dry_run=False):
        """Migrate data filtered by tenant_id"""
        # Count records for this tenant
        cursor.execute(f"""
            SELECT COUNT(*) FROM public.{table_name} 
            WHERE tenant_id = %s
        """, [tenant.id])
        
        count = cursor.fetchone()[0]
        
        if count == 0:
            self.stdout.write(f'  - {table_name}: No records to migrate')
            return

        if dry_run:
            self.stdout.write(f'  - {table_name}: Would migrate {count} records')
            return

        # Copy tenant data to new schema (excluding tenant_id field)
        cursor.execute(f"""
            SELECT column_name 
            FROM information_schema.columns 
            WHERE table_schema = 'public' 
            AND table_name = %s
            AND column_name != 'tenant_id'
            ORDER BY ordinal_position
        """, [table_name])
        
        columns = [row[0] for row in cursor.fetchall()]
        columns_str = ', '.join(columns)
        
        try:
            cursor.execute(f"""
                INSERT INTO {schema_name}.{table_name} ({columns_str})
                SELECT {columns_str}
                FROM public.{table_name}
                WHERE tenant_id = %s
            """, [tenant.id])
            
            self.stdout.write(f'  ✓ {table_name}: Migrated {count} records')
        except Exception as e:
            self.stdout.write(f'  ✗ {table_name}: Migration failed - {e}')

    def migrate_all_data(self, cursor, table_name, schema_name, dry_run=False):
        """Migrate all data (for models without tenant filtering)"""
        # Count all records
        cursor.execute(f"SELECT COUNT(*) FROM public.{table_name}")
        count = cursor.fetchone()[0]
        
        if count == 0:
            self.stdout.write(f'  - {table_name}: No records to migrate')
            return

        if dry_run:
            self.stdout.write(f'  - {table_name}: Would migrate {count} records')
            return

        # Copy all data to new schema
        try:
            cursor.execute(f"""
                INSERT INTO {schema_name}.{table_name}
                SELECT * FROM public.{table_name}
            """)
            
            self.stdout.write(f'  ✓ {table_name}: Migrated {count} records')
        except Exception as e:
            self.stdout.write(f'  ✗ {table_name}: Migration failed - {e}')