"""
同步前端页面数据

从 docs/menu_keys.json 文件同步前端页面到数据库。

用法:
    python manage.py sync_frontend_pages
    python manage.py sync_frontend_pages --dry-run  # 仅预览，不实际写入
    python manage.py sync_frontend_pages --clear    # 清空后重新同步
"""
import json
from pathlib import Path

from django.core.management.base import BaseCommand
from django.db import transaction

from basic_info.models import FrontendPage, FrontendPageTypeEnum


class Command(BaseCommand):
    help = '从 docs/menu_keys.json 同步前端页面到数据库'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='仅预览变更，不实际写入数据库',
        )
        parser.add_argument(
            '--clear',
            action='store_true',
            help='清空现有数据后重新同步（谨慎使用）',
        )
        parser.add_argument(
            '--file',
            type=str,
            default='docs/menu_keys.json',
            help='JSON 文件路径（相对于项目根目录）',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']
        clear = options['clear']
        file_path = options['file']

        # 读取 JSON 文件
        # __file__ = .../basic_info/management/commands/sync_frontend_pages.py
        # parents[3] = 项目根目录 (flower/)
        json_path = Path(__file__).resolve().parents[3] / file_path
        if not json_path.exists():
            self.stderr.write(self.style.ERROR(f'文件不存在: {json_path}'))
            return

        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        menus = data.get('menus', [])
        if not menus:
            self.stderr.write(self.style.ERROR('JSON 文件中没有 menus 数据'))
            return

        self.stdout.write(f'读取到 {len(menus)} 个主菜单')

        # 统计
        created_count = 0
        updated_count = 0
        skipped_count = 0

        try:
            with transaction.atomic():
                # 清空现有数据
                if clear:
                    if dry_run:
                        self.stdout.write(self.style.WARNING('[DRY-RUN] 将清空所有前端页面数据'))
                    else:
                        deleted_count, _ = FrontendPage.objects.all().delete()
                        self.stdout.write(self.style.WARNING(f'已清空 {deleted_count} 条记录'))

                # 第一轮：创建/更新主菜单
                main_menu_map = {}  # key -> FrontendPage instance
                for sort_order, menu in enumerate(menus):
                    key = menu['key']
                    label = menu['label']

                    if dry_run:
                        self.stdout.write(f'[DRY-RUN] 主菜单: {key} ({label})')
                        created_count += 1
                    else:
                        page, created = FrontendPage.objects.update_or_create(
                            key=key,
                            defaults={
                                'label': label,
                                'page_type': FrontendPageTypeEnum.MAIN,
                                'parent': None,
                                'sort_order': sort_order * 100,  # 主菜单间隔100
                                'is_active': True,
                            }
                        )
                        main_menu_map[key] = page
                        if created:
                            created_count += 1
                            self.stdout.write(self.style.SUCCESS(f'创建主菜单: {key} ({label})'))
                        else:
                            updated_count += 1
                            self.stdout.write(f'更新主菜单: {key} ({label})')

                # 第二轮：创建/更新子菜单
                for menu in menus:
                    parent_key = menu['key']
                    children = menu.get('children', [])

                    parent_page = main_menu_map.get(parent_key) if not dry_run else None

                    for sub_order, child in enumerate(children):
                        child_key = child['key']
                        child_label = child['label']

                        if dry_run:
                            self.stdout.write(f'[DRY-RUN]   子菜单: {child_key} ({child_label}) <- {parent_key}')
                            created_count += 1
                        else:
                            # 计算排序：父级排序 + 子级偏移
                            parent_sort = parent_page.sort_order if parent_page else 0
                            child_sort = parent_sort + sub_order + 1

                            page, created = FrontendPage.objects.update_or_create(
                                key=child_key,
                                defaults={
                                    'label': child_label,
                                    'page_type': FrontendPageTypeEnum.SUB,
                                    'parent': parent_page,
                                    'sort_order': child_sort,
                                    'is_active': True,
                                }
                            )
                            if created:
                                created_count += 1
                                self.stdout.write(self.style.SUCCESS(f'  创建子菜单: {child_key} ({child_label})'))
                            else:
                                updated_count += 1
                                self.stdout.write(f'  更新子菜单: {child_key} ({child_label})')

                if dry_run:
                    # 回滚事务
                    raise DryRunException()

        except DryRunException:
            pass

        # 输出统计
        self.stdout.write('')
        self.stdout.write(self.style.SUCCESS('=' * 40))
        if dry_run:
            self.stdout.write(self.style.WARNING(f'[DRY-RUN] 预计创建: {created_count} 条'))
        else:
            self.stdout.write(self.style.SUCCESS(f'创建: {created_count} 条'))
            self.stdout.write(f'更新: {updated_count} 条')
            self.stdout.write(f'总计: {FrontendPage.objects.count()} 条')


class DryRunException(Exception):
    """用于 dry-run 模式回滚事务"""
    pass

