"""gvsdsdk init — 子服务器快速初始化 SAAS 表

用法：
    python manage.py gvsdsdk_init --db saas
    python manage.py gvsdsdk_init --db saas --dry-run  # 仅打印 SQL
    python manage.py gvsdsdk_init --db default --modules auth,commission,payment

此命令会根据 gvsdsdk 中的模型定义，在指定数据库中创建对应的表。
适用于子服务器独立部署时快速建表。
"""

from django.core.management.base import BaseCommand, CommandError
from django.db import connections
from django.apps import apps


class Command(BaseCommand):
    help = '初始化 gvsdsdk SAAS 表结构（子服务器建表工具）'

    def add_arguments(self, parser):
        parser.add_argument(
            '--db', default='saas',
            help='目标数据库别名（默认 saas）',
        )
        parser.add_argument(
            '--dry-run', action='store_true',
            help='仅打印建表 SQL，不执行',
        )
        parser.add_argument(
            '--modules', default='all',
            help='要初始化的模块，逗号分隔（all, auth, commission, payment）。默认 all',
        )

    def handle(self, *args, **options):
        db_alias = options['db']
        dry_run = options['dry_run']
        modules_str = options['modules']

        # 验证数据库连接
        try:
            connection = connections[db_alias]
        except KeyError:
            raise CommandError(f'数据库别名 "{db_alias}" 未配置，请在 DATABASES 中添加')

        # 收集 gvsdsdk 模型
        target_modules = self._parse_modules(modules_str)
        models_to_create = self._collect_models(target_modules)

        if not models_to_create:
            self.stdout.write(self.style.WARNING('没有找到需要创建的模型'))
            return

        self.stdout.write(f'找到 {len(models_to_create)} 个模型：')
        for model in models_to_create:
            self.stdout.write(f'  - {model.__name__} → {model._meta.db_table}')

        # 生成建表 SQL
        schema_editor = connection.schema_editor(collect_sql=True)
        for model in models_to_create:
            try:
                schema_editor.create_model(model)
            except Exception as e:
                self.stdout.write(self.style.ERROR(f'  生成 {model.__name__} SQL 失败: {e}'))

        sql_statements = schema_editor.collected_sql

        if dry_run:
            self.stdout.write(self.style.SUCCESS('\n=== DRY RUN: 建表 SQL ==='))
            for sql in sql_statements:
                self.stdout.write(sql)
            self.stdout.write(self.style.SUCCESS(f'\n共 {len(sql_statements)} 条 SQL'))
            return

        # 执行建表
        self.stdout.write(f'\n在数据库 "{db_alias}" 中创建表...')
        try:
            with connection.cursor() as cursor:
                for sql in sql_statements:
                    cursor.execute(sql)
            self.stdout.write(self.style.SUCCESS(f'成功创建 {len(sql_statements)} 个表'))
        except Exception as e:
            raise CommandError(f'建表失败: {e}')

    def _parse_modules(self, modules_str):
        if modules_str == 'all':
            return {'auth', 'commission', 'payment'}
        return set(m.strip() for m in modules_str.split(',') if m.strip())

    def _collect_models(self, target_modules):
        """收集 gvsdsdk 中需要建表的模型"""
        all_models = []

        # 核心模型（auth 相关：User, Role, Permission, UserRole 等）
        if 'auth' in target_modules:
            try:
                from gvsdsdk import models as core_models
                for name in dir(core_models):
                    obj = getattr(core_models, name)
                    if self._is_qmodel(obj):
                        all_models.append(obj)
            except Exception:
                pass

        # 分佣模型
        if 'commission' in target_modules:
            try:
                from gvsdsdk.commission import models as comm_models
                for name in dir(comm_models):
                    obj = getattr(comm_models, name)
                    if self._is_qmodel(obj):
                        all_models.append(obj)
            except Exception:
                pass

        # 支付模型
        if 'payment' in target_modules:
            try:
                from gvsdsdk.payment import models as pay_models
                for name in dir(pay_models):
                    obj = getattr(pay_models, name)
                    if self._is_qmodel(obj):
                        all_models.append(obj)
            except Exception:
                pass

        return all_models

    def _is_qmodel(self, obj):
        """判断是否为 QModel 子类（非抽象）"""
        from gvsdsdk.model_base import QModel
        return (
            isinstance(obj, type)
            and issubclass(obj, QModel)
            and not obj._meta.abstract
        )
