#!/usr/bin/env python3
"""Apply Styller extended outfits/mounts + Varkhal/Rodrik + portal catalog (host)."""
from __future__ import annotations

import re
from pathlib import Path

OTX = Path("/home/ubuntu/otx2_reseted")
HTML = Path("/home/ubuntu/www/html")

OUTFITS_XML = OTX / "data/XML/outfits.xml"
MOUNTS_XML = OTX / "data/XML/mounts.xml"
ADDON_LUA = OTX / "data/npc/scripts/addon_itens.lua"
MOUNT_QUEST = OTX / "data/lib/mount_quest.lua"
MOUNT_BENEFITS = OTX / "data/lib/mount_benefits.lua"
DOC_MD = OTX / "doc.md"
COMMUNITY = HTML / "portal/api/community-lib.php"
MOUNTS_PHP = HTML / "portal/api/mounts.php"
MOUNTS_PAGE = HTML / "portal/src/app/mounts/page.tsx"

MARK_OUTFITS = "\t<outfit id=\"116\" premium=\"no\" default=\"0\" access=\"5\">"
OUTFITS_BLOCK = """\t<!-- BEGIN CHANGE: Styller extended outfits 129-131 2026-09-01 -->
\t<outfit id="129" premium="yes" default="1">
\t\t<list gender="1" lookType="2900" name="Styller Knight" speed="22">
\t\t<stats maxHealth="550"/>
\t\t<stats maxMana="450"/>
\t\t<skills shielding="8"/>
\t\t<skills sword="7"/>
\t\t<absorb percentPhysical="3"/>
\t</list>
\t\t<list gender="0" lookType="2899" name="Styller Knight" speed="22">
\t\t<stats maxHealth="550"/>
\t\t<stats maxMana="450"/>
\t\t<skills shielding="8"/>
\t\t<skills sword="7"/>
\t\t<absorb percentPhysical="3"/>
\t</list>
\t</outfit>
\t<outfit id="130" premium="yes" default="1">
\t\t<list gender="1" lookType="2904" name="Styller Royal" speed="22">
\t\t<stats maxHealth="550"/>
\t\t<stats maxMana="450"/>
\t\t<skills shielding="8"/>
\t\t<skills sword="7"/>
\t\t<absorb percentPhysical="3"/>
\t</list>
\t\t<list gender="0" lookType="2903" name="Styller Royal" speed="22">
\t\t<stats maxHealth="550"/>
\t\t<stats maxMana="450"/>
\t\t<skills shielding="8"/>
\t\t<skills sword="7"/>
\t\t<absorb percentPhysical="3"/>
\t</list>
\t</outfit>
\t<outfit id="131" premium="no" default="0" access="2">
\t\t<list gender="0-3" lookType="2892" name="Captain"/>
\t</outfit>
\t<!-- END CHANGE -->
"""

MOUNTS_BLOCK = """\t<!-- BEGIN CHANGE: Styller extended mounts 240-246 2026-09-01 -->
\t<mount id="240" clientid="2902" name="Rooster" speed="25" premium="yes" />
\t<mount id="241" clientid="2898" name="Anivia" speed="25" premium="yes" />
\t<mount id="242" clientid="2894" name="Styller Strider" speed="25" premium="yes" />
\t<mount id="243" clientid="2515" name="Ladybug" speed="25" premium="yes" />
\t<mount id="244" clientid="2518" name="Forest Runner" speed="25" premium="yes" />
\t<mount id="245" clientid="2688" name="River Spirit" speed="25" premium="yes" />
\t<mount id="246" clientid="2872" name="Beaver" speed="25" premium="yes" />
\t<!-- END CHANGE -->
"""

ADDON_BLOCK = """
-- BEGIN CHANGE: Styller extended outfits 129-130 (Varkhal) 2026-09-01
addVarkhalAddon({'styller knight outfit'}, {premium = true, cost = 120000000000, items = {{12709,20}, {9955,12}, {12731,8}, {6500,1000}, {5943,140}, {2171,20}, {45108,4}, {45109,3}}, outfit_female = 2899, outfit_male = 2900, addon = 0, storageID = 50249})
addVarkhalAddon({'first styller royal addon'}, {premium = true, cost = 120000000000, items = {{12709,20}, {9955,12}, {12731,8}, {6500,1000}, {5943,140}, {2171,20}, {45109,4}, {45115,3}}, outfit_female = 2903, outfit_male = 2904, addon = 1, storageID = 50251})
addVarkhalAddon({'second styller royal addon'}, {premium = true, cost = 180000000000, items = {{12709,30}, {9955,18}, {12731,12}, {6500,1500}, {5943,180}, {2171,28}, {45115,5}, {38111,4}}, outfit_female = 2903, outfit_male = 2904, addon = 2, storageID = 50252})
-- END CHANGE
"""

BOSSES_BLOCK = """
\t[240] = "Magma Tyrant",
\t[241] = "Draptor Nemesis",
\t[242] = "Lionheart Devastator",
\t[243] = "Beastlord Champion",
\t[244] = "Magma Tyrant",
\t[245] = "Draptor Nemesis",
\t[246] = "Lionheart Devastator",
"""

OFFERS_BLOCK = """
\t{
\t\tkeyword = "rooster",
\t\tmountId = 240,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 84500000,
\t\titems = { {24734, 7}, {26689, 7}, {29950, 7}, {23008, 7}, {23017, 7}, {45109, 5}, {45113, 5}, {45115, 5}, {37534, 5} },
\t\tpremiumCoins = 61,
\t\tpremdaysCost = 41,
\t\teventCoins = 6160,
\t\tneedsArena = true,
\t},
\t{
\t\tkeyword = "anivia",
\t\tmountId = 241,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 85000000,
\t\titems = { {26689, 7}, {29950, 7}, {23008, 7}, {23017, 7}, {23790, 7}, {45113, 5}, {45115, 5}, {37534, 5}, {38111, 5} },
\t\tpremiumCoins = 61,
\t\tpremdaysCost = 41,
\t\teventCoins = 6180,
\t\tneedsArena = true,
\t},
\t{
\t\tkeyword = "styller strider",
\t\tmountId = 242,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 85500000,
\t\titems = { {29950, 7}, {23008, 7}, {23017, 7}, {23790, 7}, {24734, 7}, {45115, 5}, {37534, 5}, {38111, 5}, {38800, 5} },
\t\tpremiumCoins = 62,
\t\tpremdaysCost = 41,
\t\teventCoins = 6200,
\t\tneedsArena = true,
\t},
\t{
\t\tkeyword = "ladybug",
\t\tmountId = 243,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 86000000,
\t\titems = { {23008, 7}, {23017, 7}, {23790, 7}, {24734, 7}, {26689, 7}, {37534, 5}, {38111, 5}, {38800, 5}, {40815, 5} },
\t\tpremiumCoins = 62,
\t\tpremdaysCost = 41,
\t\teventCoins = 6220,
\t\tneedsArena = true,
\t},
\t{
\t\tkeyword = "forest runner",
\t\tmountId = 244,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 86500000,
\t\titems = { {23017, 7}, {23790, 7}, {24734, 7}, {26689, 7}, {29950, 7}, {38111, 5}, {38800, 5}, {40815, 5}, {45108, 5} },
\t\tpremiumCoins = 63,
\t\tpremdaysCost = 41,
\t\teventCoins = 6240,
\t\tneedsArena = true,
\t},
\t{
\t\tkeyword = "river spirit",
\t\tmountId = 245,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 87000000,
\t\titems = { {23790, 7}, {24734, 7}, {26689, 7}, {29950, 7}, {23008, 7}, {38800, 5}, {40815, 5}, {45108, 5}, {45109, 5} },
\t\tpremiumCoins = 63,
\t\tpremdaysCost = 41,
\t\teventCoins = 6260,
\t\tneedsArena = true,
\t},
\t{
\t\tkeyword = "beaver",
\t\tmountId = 246,
\t\ttier = "S",
\t\tpremiumRequired = true,
\t\tgold = 87500000,
\t\titems = { {24734, 7}, {26689, 7}, {29950, 7}, {23008, 7}, {23017, 7}, {40815, 5}, {45108, 5}, {45109, 5}, {45113, 5} },
\t\tpremiumCoins = 64,
\t\tpremdaysCost = 41,
\t\teventCoins = 6280,
\t\tneedsArena = true,
\t},
"""

CLIENT_MAP = """
\t[2902] = 240, -- Rooster
\t[2898] = 241, -- Anivia
\t[2894] = 242, -- Styller Strider
\t[2515] = 243, -- Ladybug
\t[2518] = 244, -- Forest Runner
\t[2688] = 245, -- River Spirit
\t[2872] = 246, -- Beaver
"""

CATALOG_BLOCK = """
        // BEGIN CHANGE: Styller extended outfits 129-130 2026-09-01
        array('level' => 715, 'outfit' => 'Styller Knight', 'outfitKey' => 'styller knight', 'images' => array(2900, 2899), 'lookMale' => 2900, 'lookFemale' => 2899, 'bonus' => '+22 Speed, +550 Health, +450 Mana, +8 Shield, +7 Sword, +3% Physical Absorb', 'premium' => true, 'requiresExtended' => true, 'useOutfitPreview' => true),
        array('level' => 720, 'outfit' => 'Styller Royal', 'outfitKey' => 'styller royal', 'images' => array(2904, 2903), 'lookMale' => 2904, 'lookFemale' => 2903, 'bonus' => '+22 Speed, +550 Health, +450 Mana, +8 Shield, +7 Sword, +3% Physical Absorb', 'premium' => true, 'requiresExtended' => true, 'useOutfitPreview' => true),
        // END CHANGE
"""


def insert_before_once(text: str, marker: str, block: str, label: str) -> str:
    if block.strip() in text or "Styller extended outfits 129-131" in text and label == "outfits":
        print(f"SKIP {label} (already patched)")
        return text
    if marker not in text:
        raise SystemExit(f"marker not found for {label}")
    return text.replace(marker, block + marker, 1)


def insert_before_end_mounts(text: str) -> str:
    marker = "\t<!-- END CHANGE -->\n</mounts>"
    if "Styller extended mounts 240-246" in text:
        print("SKIP mounts.xml (already patched)")
        return text
    if marker not in text:
        marker = "</mounts>"
    return text.replace(marker, MOUNTS_BLOCK + marker, 1)


def patch_addon_lua(text: str) -> str:
    marker = "keywordHandler:addKeyword({'addons'}"
    if "Styller extended outfits 129-130" in text:
        print("SKIP addon_itens.lua (already patched)")
        return text
    return text.replace(marker, ADDON_BLOCK + "\n" + marker, 1)


def patch_mount_quest(text: str) -> str:
    if "[246] = " in text:
        print("SKIP mount_quest.lua bosses (already patched)")
    else:
        text = text.replace("\t[239] = \"Magma Tyrant\",", "\t[239] = \"Magma Tyrant\"," + BOSSES_BLOCK, 1)
    if 'keyword = "beaver"' in text:
        print("SKIP mount_quest.lua offers (already patched)")
        return text
    return text.replace("\t-- END CHANGE\n}", OFFERS_BLOCK + "\t-- END CHANGE\n}", 1)


def patch_mount_benefits(text: str) -> str:
    if "[2902] = 240" in text:
        print("SKIP mount_benefits.lua (already patched)")
        return text
    return text.replace("\t[1778] = 239, -- Bumblebee", "\t[1778] = 239, -- Bumblebee" + CLIENT_MAP, 1)


def patch_community(text: str) -> str:
    marker = "        // END CHANGE: extended outfits ids 25-115\n    );"
    if "Styller extended outfits 129-130" in text:
        print("SKIP community-lib.php (already patched)")
        return text
    return text.replace(marker, CATALOG_BLOCK + marker, 1)


def patch_mounts_php(text: str) -> str:
    text = text.replace("'S' => array(132, 239),", "'S' => array(132, 246),")
    text = text.replace("S=132-239", "S=132-246")
    return text


def patch_mounts_page(text: str) -> str:
    return text.replace("idsTo: 239,", "idsTo: 246,")


def patch_doc(text: str) -> str:
    line = "| **50249-50252** | Varkhal Styller Knight / Styller Royal addons (outfits 129-130) |\n"
    if "50249-50252" in text:
        print("SKIP doc.md (already patched)")
        return text
    marker = "| **50047-50230** | Varkhal first/second addons for outfits ids 24-115 (generated) |"
    if marker not in text:
        return text
    return text.replace(marker, marker + "\n" + line.rstrip(), 1)


def main() -> None:
    outfits = OUTFITS_XML.read_text(encoding="latin-1", errors="replace")
    outfits = insert_before_once(outfits, MARK_OUTFITS, OUTFITS_BLOCK, "outfits")
    OUTFITS_XML.write_text(outfits, encoding="latin-1")

    mounts = MOUNTS_XML.read_text(encoding="utf-8")
    mounts = insert_before_end_mounts(mounts)
    MOUNTS_XML.write_text(mounts, encoding="utf-8")

    addon = ADDON_LUA.read_text(encoding="latin-1", errors="replace")
    addon = patch_addon_lua(addon)
    ADDON_LUA.write_text(addon, encoding="latin-1")

    mq = MOUNT_QUEST.read_text(encoding="latin-1", errors="replace")
    mq = patch_mount_quest(mq)
    MOUNT_QUEST.write_text(mq, encoding="latin-1")

    mb = MOUNT_BENEFITS.read_text(encoding="latin-1", errors="replace")
    mb = patch_mount_benefits(mb)
    MOUNT_BENEFITS.write_text(mb, encoding="latin-1")

    if DOC_MD.is_file():
        doc = DOC_MD.read_text(encoding="utf-8", errors="replace")
        doc = patch_doc(doc)
        DOC_MD.write_text(doc, encoding="utf-8")

    comm = COMMUNITY.read_text(encoding="utf-8")
    comm = patch_community(comm)
    COMMUNITY.write_text(comm, encoding="utf-8")

    mp = MOUNTS_PHP.read_text(encoding="utf-8")
    mp = patch_mounts_php(mp)
    MOUNTS_PHP.write_text(mp, encoding="utf-8")

    page = MOUNTS_PAGE.read_text(encoding="utf-8")
    page = patch_mounts_page(page)
    MOUNTS_PAGE.write_text(page, encoding="utf-8")

    print("PATCH_OK")


if __name__ == "__main__":
    main()
