import json
from pathlib import Path


PROJECT_ROOT = Path(__file__).resolve().parent
CARD_PATH = PROJECT_ROOT / "data" / "monster_cards.json"


def load_cards():
    with CARD_PATH.open("r", encoding="utf-8") as f:
        data = json.load(f)
    if "cards" not in data or not isinstance(data["cards"], list):
        raise ValueError("monster_cards.json 格式错误：缺少 cards 列表")
    return data


def save_cards(data):
    # 确保可以被重新解析
    text = json.dumps(data, ensure_ascii=False, indent=2)
    json.loads(text)
    CARD_PATH.write_text(text + "\n", encoding="utf-8")


def update_battle_lines(data):
    """为缺少 battle_lines 的怪物补充台词。"""
    battle_lines_updates = {
        "mon_slime_ice": {
            "on_appear": "温度……下降。请，保持安静，别惊醒封印的记忆。",
            "on_attack": "冻结在此刻，就不会再向前坠落了。",
            "on_defeat": "封印……又松动了一点……对不起……",
            "on_victory": "至少这一段时间线，被重新按回了冰里。"
        },
        "mon_slime_poison": {
            "on_appear": "别靠太近……这是连我自己都控制不住的毒。",
            "on_attack": "一点点就够了，痛苦会慢慢渗进去。",
            "on_defeat": "看来，这一批试剂……还是失败品啊……",
            "on_victory": "配比记录完成，再来一批试验者……吗？"
        },
        "mon_slime_thunder": {
            "on_appear": "嗞啦——三百年没放电了，正好活动一下。",
            "on_attack": "别眨眼，闪电只说一次真话。",
            "on_defeat": "电势……归零……可战意，还在震荡……",
            "on_victory": "负载测试通过，下一次，就冲着更高的天空去。"
        },
        "mon_slime_shadow": {
            "on_appear": "别紧张，我只是你影子里，没来得及长大的那部分。",
            "on_attack": "看向光的瞬间，刀就已经到了背后。",
            "on_defeat": "影子……也会被踩碎的吗……",
            "on_victory": "放轻松，你什么都没看见，这只是路过的一团黑雾。"
        },
        "mon_slime_queen": {
            "on_appear": "孩子们，别怕。把哭声藏在我背后就好。",
            "on_attack": "以王后的名义，请你们停手——这是最后一次劝告。",
            "on_defeat": "原来……母亲，也会……先一步离开孩子啊……",
            "on_victory": "森林还在呼吸，史莱姆们还在笑，这就够了。"
        },
        "mon_elemental_slime": {
            "on_appear": "冷静点，一边想烧光世界，一边又想把一切冻住……真吵啊。",
            "on_attack": "火，往前一步。冰，替我封住退路。",
            "on_defeat": "吵架……终于停下来了……也好……",
            "on_victory": "结论：矛盾共存，并不妨碍一起打赢一场仗。"
        },
        "mon_slime_knight": {
            "on_appear": "两颗心，一个决定——这次换我们挡在前面。",
            "on_attack": "一刀不够？那就再来一刀！",
            "on_defeat": "看来……还不够完整……再……融合一次吧……",
            "on_victory": "嘿，配合得不错。下次再合一次，说不定就想起前世了。"
        },
        "mon_fire_sprite": {
            "on_appear": "欸？新的课题吗？是要点火还是灭火？",
            "on_attack": "看好了，这是老师教的第三种用法！",
            "on_defeat": "呜……这次实验，好像又……炸偏了……",
            "on_victory": "记下来！「在混乱战场中乱窜」也是一种有效战术！"
        },
        "mon_wood_fox": {
            "on_appear": "嘘——树叶会替我们挡住视线。",
            "on_attack": "你只会看到风掠过，不会看到爪子落下。",
            "on_defeat": "森林的味道……离我，好远了……",
            "on_victory": "安全路线已经探好，下次就不会迷路啦。"
        },
        "mon_earth_beetle": {
            "on_appear": "负重测试开始，小石头们，跟紧我。",
            "on_attack": "正面撞击，结果写进岩层里就好。",
            "on_defeat": "外壳破了……但里面的故事，还在。",
            "on_victory": "确认：此路勉强安全，可以再多撑几百年。"
        },
        "mon_water_fish": {
            "on_appear": "水流有点浑了呢……那就先帮你们洗一洗伤口吧。",
            "on_attack": "别怕，只是让你清醒一点点。",
            "on_defeat": "泉眼……在干涸，我却游不回源头了……",
            "on_victory": "水又清了一点，今天的泉底倒影，也能多看一会儿。"
        },
        "mon_void_wisp": {
            "on_appear": "……呼唤信号微弱，但，我听见了。",
            "on_attack": "把你的噪音，送回寂静里去吧。",
            "on_defeat": "原来，坠落也可以……不再怕黑……",
            "on_victory": "记录：又一段喧嚣，被顺利抹平。"
        },
        "mon_vine_treant": {
            "on_appear": "根系已确认，敌我位置标记完成。",
            "on_attack": "别乱动，缠一缠就不疼了——也动不了了。",
            "on_defeat": "树根……暂时，够不到这里了……",
            "on_victory": "坐好，等我慢慢松开，你们还是可以继续走路的。"
        },
        "mon_iron_puppet": {
            "on_appear": "接受新指令：保护通道。执行中。",
            "on_attack": "动力核心稳定，施加冲击。",
            "on_defeat": "系统……故障……等待……维修……",
            "on_victory": "任务阶段一完成，继续：守候与等待。"
        },
        "mon_young_dragon": {
            "on_appear": "哇，这里也是可以喷火的地方吗？",
            "on_attack": "看我——小号龙息版！",
            "on_defeat": "下次……我会飞得更高一点，再回来……",
            "on_victory": "好玩！如果这就是战斗，那我大概……还能再玩很久。"
        },
        "mon_wind_dancer": {
            "on_appear": "风说，有人需要一支快一点的舞。",
            "on_attack": "脚步比剑先到，剑比影子先落。",
            "on_defeat": "风……今天，也没能带我回到原来的路线上……",
            "on_victory": "路线修正完毕，这一片天空，暂时安全。"
        },
        "mon_frost_dragon": {
            "on_appear": "温度下降，时间流速，开始减缓。",
            "on_attack": "在这口吐息里，连悔恨都会结成霜。",
            "on_defeat": "封印……又裂开了一条缝……",
            "on_victory": "时间暂时稳住了，你们还能多活几页篇章。"
        },
        "mon_holy_knight": {
            "on_appear": "灵息守卫团，普通队员报到。把恐惧交给盾就好。",
            "on_attack": "这一剑，不是为功勋，只是为身后的人能睡个好觉。",
            "on_defeat": "看来……这一次，我只能守到这里了……",
            "on_victory": "没有人会记得我是谁，但他们会记得「今天很安全」。足够了。"
        },
        "mon_necromancer": {
            "on_appear": "别误会，我只是被拖下水的那一个。",
            "on_attack": "痛苦越多，公式就越完整——对不起。",
            "on_defeat": "也许……这一次，终于能睡一会儿了……",
            "on_victory": "实验继续。活着的，死去的，都只是样本。包括我自己。"
        },
        "mon_phoenix": {
            "on_appear": "又一次，从灰烬里睁开眼睛。",
            "on_attack": "记不清上一次烧到了哪里，那就从这里继续吧。",
            "on_defeat": "别急着告别，我的故事……总会续写下一章。",
            "on_victory": "燃尽之后，灰烬会记住今天的热度。下次重生，会更耀眼一点。"
        },
    }

    missing_ids = []
    for card in data["cards"]:
        cid = card.get("id")
        if "battle_lines" not in card:
            if cid in battle_lines_updates:
                card["battle_lines"] = battle_lines_updates[cid]
            else:
                missing_ids.append(cid)

    if missing_ids:
        raise ValueError(f"仍有怪物缺少 battle_lines，且脚本未覆盖: {missing_ids}")


def build_slime_paladin():
    return {
        "id": "mon_slime_paladin",
        "name": "史莱姆圣骑士",
        "description": "在史莱姆骑士的基础上凝聚出「意志」的稀有形态，兼具护卫与审判之力。",
        "icon": "✝️",
        "stars": 5,
        "attribute": "water",
        "element": "water",
        "race": "human",
        "class": "warrior",
        "hp": 1700,
        "base_atk": 1500,
        "base_def": 1300,
        "spd": 45,
        "passive": {
            "name": "粘质圣徽",
            "effect": "slime_ally_shield_10"
        },
        "tier_max": 5,
        "effects": {
            "summon": {
                "desc": "召唤时：己方其他史莱姆族怪兽本回合不会被战斗破坏",
                "type": "holy_slime_shield",
                "target": "ally_slime",
                "duration": 1
            },
            "passive": {
                "desc": "己方史莱姆族怪兽受到的伤害-10%",
                "type": "slime_ally_damage_reduce",
                "value": 10,
                "target": "ally_slime"
            },
            "active": {
                "desc": "每回合1次：选择1只己方史莱姆族怪兽，本回合ATK+300并获得「首次被破坏时以300HP残存」",
                "type": "holy_command_slime",
                "value": 300,
                "target": "ally_slime_one"
            }
        },
        "evolution": None,
        "sprite_path": "res://assets/sprites/characters/portrait/slime_paladin_portrait.png",
        "source": "evolution",
        "tags": ["史莱姆", "战士", "进化"],
        "created_at": "2026-02-24 00:00:00.000000+00",
        "updated_at": "2026-02-24 00:00:00.000000+00",
        "bonds": [
            {
                "desc": "与史莱姆王同时在场时，此卡ATK+300",
                "bonus_type": "atk",
                "partner_id": "mon_slime_king",
                "bonus_value": 300
            },
            {
                "desc": "与史莱姆皇后同时在场时，此卡每回合结束回复300HP",
                "bonus_type": "regen",
                "partner_id": "mon_slime_queen",
                "bonus_value": 300
            }
        ],
        "weaknesses": [
            {
                "attr": "void",
                "multiplier": 1.5
            }
        ],
        "skills": [
            {
                "id": "skill_holy_slime_shield",
                "desc": "被动：己方史莱姆族受到的伤害-10%",
                "icon": "🛡️",
                "name": "圣洁护膜"
            },
            {
                "id": "skill_holy_command",
                "desc": "主动：强化1只史莱姆族并赋予一次假死",
                "icon": "✝️",
                "name": "圣骑号令"
            }
        ],
        "cost": 4,
        "star": 4,
        "active_skill": {
            "name": "圣光制裁",
            "element": "water",
            "target_type": "single_enemy",
            "base_damage": 450,
            "atk_ratio": 0.8,
            "effect": "damage",
            "cooldown": 4,
            "range": 2,
            "extra_effect": {
                "type": "cleanse_slime",
                "desc": "若己方场上存在其他史莱姆族怪兽，则驱散目标1个正面状态"
            }
        },
        "lore": {
            "flavor_text": "在史莱姆骑士的基础上凝聚出「意志」的稀有形态。它的核心是一名灵息守卫团失踪骑士的残魂，与两只史莱姆在战斗中反复融合后诞生。与普通的史莱姆不同，它知道自己在守护什么——不是某一片森林，而是「仍然愿意相信希望的人」。",
            "origin": "灵息守卫团失踪骑士与史莱姆融合体",
            "era": "暗流纪元（本体）/ 残息纪元（再临）",
            "tragedy": "它偶尔会本能地举起不存在的旗帜，对着空无一人的城墙敬礼。那面旗帜早在三百年前就烧成了灰。"
        },
        "battle_lines": {
            "on_appear": "史莱姆圣骑士应召而来——软弱的身躯，也能承载誓约。",
            "on_attack": "以凝成铠甲的怯懦，为你们挡下一次黑暗。",
            "on_defeat": "盔甲碎了……但誓言，还能被别的谁捡起来……",
            "on_victory": "今天你们能向前一步，是因为有人选择留下不走。记得就好。"
        },
        "fullbody_path": "res://assets/sprites/characters/fullbody/slime_paladin_fullbody.png"
    }


def insert_slime_paladin(data):
    cards = data["cards"]
    ids = [c.get("id") for c in cards]
    if "mon_slime_paladin" in ids:
        # 已存在则不重复插入
        return

    try:
        idx = ids.index("mon_slime_knight")
    except ValueError as exc:
        raise ValueError("找不到 mon_slime_knight，无法插入 mon_slime_paladin") from exc

    paladin_card = build_slime_paladin()
    cards.insert(idx + 1, paladin_card)


def validate_structure(data):
    cards = data["cards"]
    # 简单结构校验：每张怪物必须有 id、name、hp、base_atk、base_def、active_skill、lore、battle_lines
    required_fields = ["id", "name", "hp", "base_atk", "base_def", "active_skill", "lore", "battle_lines"]
    missing_info = []
    for card in cards:
        cid = card.get("id", "<unknown>")
        for field in required_fields:
            if field not in card:
                missing_info.append((cid, field))
    if missing_info:
        details = ", ".join(f"{cid}:{field}" for cid, field in missing_info)
        raise ValueError(f"字段完整性校验失败，缺少字段: {details}")


def main():
    data = load_cards()
    update_battle_lines(data)
    insert_slime_paladin(data)
    validate_structure(data)
    save_cards(data)
    print("monster_cards.json 更新完成：补齐 battle_lines 并插入 mon_slime_paladin。")


if __name__ == "__main__":
    main()

