"""
批量为故事和音乐生成引导语 Opus 数据并写入数据库。

使用方法:
    python manage.py generate_intro_opus                  # 处理所有
    python manage.py generate_intro_opus --type story     # 仅故事
    python manage.py generate_intro_opus --type music     # 仅音乐
    python manage.py generate_intro_opus --dry-run        # 仅统计
    python manage.py generate_intro_opus --limit 10       # 只处理前 10 个
    python manage.py generate_intro_opus --force           # 重新生成已有引导语的记录
"""
import logging

from django.core.management.base import BaseCommand

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = '批量为故事和音乐生成引导语 Opus 数据'

    def add_arguments(self, parser):
        parser.add_argument(
            '--type', choices=['story', 'music', 'all'], default='all',
            help='处理类型：story / music / all（默认 all）',
        )
        parser.add_argument(
            '--dry-run', action='store_true',
            help='仅统计需要处理的数量，不实际执行',
        )
        parser.add_argument(
            '--limit', type=int, default=0,
            help='最多处理的数量（0=不限）',
        )
        parser.add_argument(
            '--force', action='store_true',
            help='重新生成已有引导语的记录',
        )

    def handle(self, *args, **options):
        content_type = options['type']
        dry_run = options['dry_run']
        limit = options['limit']
        force = options['force']

        if content_type in ('story', 'all'):
            self._process_stories(dry_run, limit, force)

        if content_type in ('music', 'all'):
            self._process_tracks(dry_run, limit, force)

    def _process_stories(self, dry_run, limit, force):
        from apps.stories.models import Story
        from apps.stories.services.intro_service import generate_intro_opus

        self.stdout.write(self.style.MIGRATE_HEADING('\n=== 故事引导语 ==='))

        qs = Story.objects.exclude(audio_url='')
        if not force:
            qs = qs.filter(intro_opus_data='')
        qs = qs.order_by('id')

        total = qs.count()
        self.stdout.write(f'需要处理的故事: {total} 个')

        if dry_run or total == 0:
            return

        items = qs[:limit] if limit > 0 else qs
        success_count = 0
        fail_count = 0

        for i, story in enumerate(items.iterator(), 1):
            self.stdout.write(f'[{i}/{total}] Story#{story.id} "{story.title}"')
            try:
                opus_json = generate_intro_opus(story.title, content_type='story')
                story.intro_opus_data = opus_json
                story.save(update_fields=['intro_opus_data'])
                success_count += 1
                self.stdout.write(self.style.SUCCESS(
                    f'  OK ({len(opus_json) / 1024:.1f} KB)'
                ))
            except Exception as e:
                fail_count += 1
                self.stdout.write(self.style.ERROR(f'  FAIL: {e}'))
                logger.error(f'Story#{story.id} intro generate failed: {e}')

        self.stdout.write(self.style.SUCCESS(
            f'故事完成: 成功 {success_count}, 失败 {fail_count}'
        ))

    def _process_tracks(self, dry_run, limit, force):
        from apps.music.models import Track
        from apps.stories.services.intro_service import generate_intro_opus

        self.stdout.write(self.style.MIGRATE_HEADING('\n=== 音乐引导语 ==='))

        qs = Track.objects.filter(
            generation_status='completed',
        ).exclude(audio_url='')
        if not force:
            qs = qs.filter(intro_opus_data='')
        qs = qs.order_by('id')

        total = qs.count()
        self.stdout.write(f'需要处理的曲目: {total} 个')

        if dry_run or total == 0:
            return

        items = qs[:limit] if limit > 0 else qs
        success_count = 0
        fail_count = 0

        for i, track in enumerate(items.iterator(), 1):
            self.stdout.write(f'[{i}/{total}] Track#{track.id} "{track.title}"')
            try:
                opus_json = generate_intro_opus(track.title, content_type='music')
                track.intro_opus_data = opus_json
                track.save(update_fields=['intro_opus_data'])
                success_count += 1
                self.stdout.write(self.style.SUCCESS(
                    f'  OK ({len(opus_json) / 1024:.1f} KB)'
                ))
            except Exception as e:
                fail_count += 1
                self.stdout.write(self.style.ERROR(f'  FAIL: {e}'))
                logger.error(f'Track#{track.id} intro generate failed: {e}')

        self.stdout.write(self.style.SUCCESS(
            f'音乐完成: 成功 {success_count}, 失败 {fail_count}'
        ))
