# -*- coding: utf-8 -*-
"""
마크다운 문서 생성 모듈
"""

import re
from typing import Dict, List


def format_skill_description(desc: str, desc_values: List) -> str:
    """
    스킬 설명 문자열의 {0}, {1} 등을 descValues로 치환하고 줄바꿈 태그 제거

    Args:
        desc: 원본 설명 문자열 (예: "검을 휘둘러 {0}%만큼 번개 속성 물리 피해를 입힙니다.")
        desc_values: 치환할 값들의 배열 (예: [130, 0])

    Returns:
        완성된 설명 문자열
    """
    if not desc:
        return ''

    result = desc

    # {0}, {1}, {2} 등을 descValues로 치환
    for i, value in enumerate(desc_values):
        placeholder = '{' + str(i) + '}'
        result = result.replace(placeholder, str(value))

    # 줄바꿈 태그 제거 (\r\n, \n, <br>, <br/> 등)
    result = result.replace('\\r\\n', ' ')
    result = result.replace('\\n', ' ')
    result = result.replace('\r\n', ' ')
    result = result.replace('\n', ' ')
    result = re.sub(r'<br\s*/?>', ' ', result)

    # 연속된 공백을 하나로
    result = re.sub(r'\s+', ' ', result)

    return result.strip()


def format_stat_table(stats: Dict) -> str:
    """기본 스탯 테이블 생성"""
    stat_rows = [
        ('힘 (Str)', stats.get('str', 0)),
        ('민첩 (Dex)', stats.get('dex', 0)),
        ('지능 (Int)', stats.get('int', 0)),
        ('체력 (Con)', stats.get('con', 0)),
        ('지혜 (Wis)', stats.get('wis', 0)),
        ('HP', stats.get('hp', 0)),
        ('MP', stats.get('mp', 0)),
        ('마나 재생', stats.get('manaRegen', 0)),
        ('지구력 (Stamina)', stats.get('stamina', 0)),
        ('크리티컬 확률 (%)', stats.get('criticalPer', 0))
    ]

    lines = ['| 스탯 | 값 |', '|------|-----|']
    for name, value in stat_rows:
        lines.append(f'| {name} | {value} |')

    return '\n'.join(lines)


def format_skill_section(skill_data: Dict, skill_montages: List[Dict]) -> str:
    """개별 스킬 섹션 생성"""
    lines = []

    # 스킬 기본 정보
    skill_id = skill_data.get('skillId', '')
    skill_name = skill_data.get('name', '')
    lines.append(f"#### {skill_id} - {skill_name}")
    lines.append('')

    # 스킬 설명 (descValues 적용)
    desc = skill_data.get('desc', '')
    desc_values = skill_data.get('descValues', [])
    formatted_desc = format_skill_description(desc, desc_values)
    if formatted_desc:
        lines.append(f'**설명**: {formatted_desc}')
        lines.append('')

    # 스킬 속성
    lines.append('**스킬 속성**')
    lines.append('| 항목 | 값 |')
    lines.append('|------|-----|')
    lines.append(f"| 공격 타입 | {skill_data.get('skillAttackType', '')} |")
    lines.append(f"| 원소 타입 | {skill_data.get('skillElementType', '')} |")

    damage_rate = skill_data.get('skillDamageRate', 1.0)
    lines.append(f"| 피해 배율 | {int(damage_rate * 100)}% |")

    if skill_data.get('walkSpeedMultiplier', 0) != 0:
        walk_speed = skill_data.get('walkSpeedMultiplier', 0)
        lines.append(f"| 이동 속도 배율 | {walk_speed}x |")

    casting_time = skill_data.get('castingTime', 0)
    if casting_time > 0:
        lines.append(f"| 시전 시간 | {casting_time}초 |")

    mana_cost = skill_data.get('manaCost', 0)
    if mana_cost > 0:
        lines.append(f"| 마나 비용 | {mana_cost} |")

    cool_time = skill_data.get('coolTime', 0)
    if cool_time > 0:
        lines.append(f"| 재사용 대기시간 | {cool_time}초 |")

    # 스택 정보
    if skill_data.get('bIsStackable', False):
        max_stack = skill_data.get('maxStackCount', 0)
        lines.append(f"| 스택 | 가능 (최대 {max_stack}) |")

    # 궁극기 여부
    if skill_data.get('bIsUltimate', False):
        lines.append(f"| 궁극기 | O |")

    # 지속 시간
    active_duration = skill_data.get('activeDuration', 0)
    if active_duration > 0:
        lines.append(f"| 지속 시간 | {active_duration}초 |")

    lines.append('')

    # 어빌리티 클래스
    ability_class = skill_data.get('abilityClass', '')
    if ability_class and ability_class != 'None':
        class_name = ability_class.split('/')[-1].replace('.', ' → ')
        lines.append(f'**어빌리티 클래스**: `{class_name}`')
        lines.append('')

    active_ability = skill_data.get('activeAbilityClass', '')
    if active_ability and active_ability != 'None':
        class_name = active_ability.split('/')[-1].replace('.', ' → ')
        lines.append(f'**활성 어빌리티**: `{class_name}`')
        lines.append('')

    # GameplayEffect
    ge_set = skill_data.get('gameplayEffectSet', [])
    if ge_set:
        lines.append('**Gameplay Effects**')
        for ge in ge_set:
            trigger = ge.get('trigger', '')
            ge_class = ge.get('gEClass', '')
            ge_name = ge_class.split('/')[-1].replace('.', ' → ') if ge_class else ''
            lines.append(f'- `{trigger}`: {ge_name}')
        lines.append('')

    # 몽타주 정보
    if skill_montages:
        lines.append('---')
        lines.append('')
        for i, montage in enumerate(skill_montages, 1):
            asset_name = montage.get('assetName', '')
            lines.append(f'**몽타주 {i}: {asset_name}**')
            lines.append('')

            seq_len = montage.get('sequenceLength', 0)
            rate_scale = montage.get('rateScale', 1.0)
            lines.append(f'- 시퀀스 길이: {seq_len:.2f}초')
            lines.append(f'- 재생 속도: {rate_scale}x')
            lines.append('')

            # AnimNotifies
            anim_notifies = montage.get('animNotifies', [])
            if anim_notifies:
                lines.append('**주요 타이밍**')
                for notify in anim_notifies:
                    notify_class = notify.get('notifyClass', '')
                    trigger_time = notify.get('triggerTime', 0)
                    duration = notify.get('duration', 0)

                    notify_name = notify_class.replace('_C', '').replace('AnimNotifyState_', '')

                    if duration > 0:
                        end_time = trigger_time + duration
                        lines.append(f'- **{notify_name}**: {trigger_time:.2f}~{end_time:.2f}초 (지속: {duration:.2f}초)')
                    else:
                        lines.append(f'- **{notify_name}**: {trigger_time:.2f}초')

                    # Properties
                    props = notify.get('properties', {})
                    if props:
                        for key, value in props.items():
                            if key == 'AttackTag':
                                lines.append(f'  - 공격 태그: `{value}`')
                            elif key == 'EventTag':
                                lines.append(f'  - 이벤트 태그: `{value}`')
                            elif key == 'AddNormalAttackPer':
                                lines.append(f'  - 일반 공격력 증가: {value}%')
                            elif key == 'AddPhysicalAttackPer':
                                lines.append(f'  - 물리 공격력 증가: {value}%')

                lines.append('')

            lines.append('')

    lines.append('')
    return '\n'.join(lines)


def format_basic_attack_section(weapon_type: str, montages: List[Dict]) -> str:
    """기본 공격 섹션 생성"""
    lines = []
    lines.append(f'### 기본 공격: {weapon_type}')
    lines.append('')

    for i, montage in enumerate(montages, 1):
        asset_name = montage.get('assetName', '')
        lines.append(f'#### 콤보 {i}: {asset_name}')
        lines.append('')

        seq_len = montage.get('sequenceLength', 0)
        rate_scale = montage.get('rateScale', 1.0)
        lines.append(f'- 시퀀스 길이: {seq_len:.2f}초')
        lines.append(f'- 재생 속도: {rate_scale}x')
        lines.append('')

        # AnimNotifies
        anim_notifies = montage.get('animNotifies', [])
        if anim_notifies:
            lines.append('**주요 타이밍**')
            for notify in anim_notifies:
                notify_class = notify.get('notifyClass', '')
                trigger_time = notify.get('triggerTime', 0)
                duration = notify.get('duration', 0)

                notify_name = notify_class.replace('_C', '').replace('AnimNotifyState_', '')

                if duration > 0:
                    end_time = trigger_time + duration
                    lines.append(f'- **{notify_name}**: {trigger_time:.2f}~{end_time:.2f}초 (지속: {duration:.2f}초)')
                else:
                    lines.append(f'- **{notify_name}**: {trigger_time:.2f}초')

                # Properties
                props = notify.get('properties', {})
                if props:
                    for key, value in props.items():
                        if key == 'AttackTag':
                            lines.append(f'  - 공격 태그: `{value}`')
                        elif key == 'AddNormalAttackPer':
                            lines.append(f'  - 일반 공격력 증가: {value}%')
                        elif key == 'AddPhysicalAttackPer':
                            lines.append(f'  - 물리 공격력 증가: {value}%')

            lines.append('')

        lines.append('')

    return '\n'.join(lines)


def generate_stalker_markdown(stalker_name: str, stalker_data: Dict) -> str:
    """
    스토커 개별 마크다운 문서 생성

    Args:
        stalker_name: 스토커 이름 (소문자)
        stalker_data: 스토커 전투 데이터

    Returns:
        마크다운 문서 문자열
    """
    lines = []

    # 타이틀
    display_name = stalker_data.get('basic_info', {}).get('name', stalker_name.capitalize())
    job_name = stalker_data.get('basic_info', {}).get('jobName', '')
    lines.append(f'# {display_name} ({stalker_name.capitalize()}) - 전투 데이터')
    lines.append('')

    # 기본 정보
    lines.append('## 기본 정보')
    lines.append('')
    lines.append(f'- **직업**: {job_name}')
    ultimate_point = stalker_data.get('skills', {}).get('ultimatePoint', 0)
    lines.append(f'- **궁극기 포인트**: {ultimate_point}')
    equip_types = stalker_data.get('stats', {}).get('equipableTypes', [])
    if equip_types:
        lines.append(f'- **장착 가능 장비**: {", ".join(equip_types)}')
    lines.append('')

    # 기본 스탯
    lines.append('## 기본 스탯')
    lines.append('')
    stats = stalker_data.get('stats', {})
    lines.append(format_stat_table(stats))
    lines.append('')

    # 스킬
    lines.append('## 스킬')
    lines.append('')

    # 기본 스킬
    default_skills = stalker_data.get('skills', {}).get('default', [])
    if default_skills:
        lines.append('### 기본 스킬')
        lines.append('')
        skill_details = stalker_data.get('skill_details', {})
        for skill_id in default_skills:
            skill_data = skill_details.get(skill_id)
            if skill_data:
                skill_montages = skill_data.get('montages', [])
                lines.append(format_skill_section(skill_data, skill_montages))

    # 서브 스킬
    sub_skill = stalker_data.get('skills', {}).get('sub', '')
    if sub_skill:
        lines.append('### 서브 스킬')
        lines.append('')
        skill_details = stalker_data.get('skill_details', {})
        skill_data = skill_details.get(sub_skill)
        if skill_data:
            skill_montages = skill_data.get('montages', [])
            lines.append(format_skill_section(skill_data, skill_montages))

    # 궁극기
    ultimate_skill = stalker_data.get('skills', {}).get('ultimate', '')
    if ultimate_skill:
        lines.append('### 궁극기')
        lines.append('')
        skill_details = stalker_data.get('skill_details', {})
        skill_data = skill_details.get(ultimate_skill)
        if skill_data:
            skill_montages = skill_data.get('montages', [])
            lines.append(format_skill_section(skill_data, skill_montages))

    # 기본 공격
    basic_attacks = stalker_data.get('basic_attacks', {})
    if basic_attacks:
        lines.append('## 기본 공격')
        lines.append('')
        for weapon_type, montages in basic_attacks.items():
            if montages:
                lines.append(format_basic_attack_section(weapon_type, montages))

    return '\n'.join(lines)
