import json
import sqlite3
import subprocess
import sys
from pathlib import Path

sys.stdout.reconfigure(encoding='utf-8')

project_root = Path.cwd()
sys.path.insert(0, str(project_root))

# 1. Load Python catalog
import server.world.map_style_catalog as py_cat
from server.world.map_style_service import MapStyleService

py_styles = py_cat.MAP_STYLES_BY_ID
print(f"Loaded {len(py_styles)} styles from Python catalog.")

# 2. Load DB
service = MapStyleService()
db_styles = {s.style_id: s for s in service.list_styles()}
print(f"Loaded {len(db_styles)} styles from SQLite DB.")

# 3. Load Client JS catalog via Node
js_script = """
import catalog from './client/webapp/js/data/map_style_catalog.js';

const tilePalettes = {};
for (let b = 1; b <= 30; b++) {
    tilePalettes[b] = {};
    for (let t = 0; t < 20; t++) {
        tilePalettes[b][t] = catalog.getTilePalette(b, t);
    }
}

const payload = {
    map_styles: catalog.MAP_STYLES,
    code_to_style: catalog.BIOME_CODE_TO_STYLE_ID,
    legacy_map: catalog.LEGACY_BIOME_MAP,
    tile_palettes: tilePalettes
};
console.log(JSON.stringify(payload));
"""

proc = subprocess.run(
    ["node", "--input-type=module", "-e", js_script],
    cwd=str(project_root),
    capture_output=True,
    text=True,
    encoding="utf-8",
    check=True
)
lines = [l.strip() for l in proc.stdout.splitlines() if l.strip().startswith("{")]
js_data = json.loads(lines[-1])
js_styles = js_data["map_styles"]
print(f"Loaded {len(js_styles)} styles from JS catalog via Node.")

# Verification checks
assert set(py_styles.keys()) == set(db_styles.keys()) == set(js_styles.keys()), "Style ID sets mismatch!"
print("Style ID sets MATCH across all 3 catalogs (30 styles).")

# Attribute-by-attribute check
for s_id in sorted(py_styles.keys()):
    p = py_styles[s_id]
    d = db_styles[s_id]
    j = js_styles[s_id]

    # biome_code
    assert p.biome_code == d.biome_code == j["biome_code"], f"biome_code mismatch for {s_id}: {p.biome_code}, {d.biome_code}, {j['biome_code']}"
    # names
    assert p.name_vi == d.name_vi == j["name_vi"], f"name_vi mismatch for {s_id}"
    assert p.name_en == d.name_en == j["name_en"], f"name_en mismatch for {s_id}"
    # theme
    assert p.theme_category == d.theme_category == j["theme_category"], f"theme_category mismatch for {s_id}"
    # legacy_alias
    assert p.legacy_alias == d.legacy_alias == j["legacy_alias"], f"legacy_alias mismatch for {s_id}"
    # palette
    for col in ["floor", "wall", "path", "liquid", "ambient"]:
        pval = getattr(p.palette, col)
        dval = getattr(d.palette, col)
        jval = j["palette"][col]
        assert pval == dval == jval, f"Palette {col} mismatch for {s_id}: py={pval}, db={dval}, js={jval}"

    # lighting fog density
    assert abs(p.lighting.fog_density - d.lighting.fog_density) < 1e-4, f"Fog density mismatch py/db for {s_id}"
    assert abs(p.lighting.fog_density - j["lighting"]["fog_density"]) < 1e-4, f"Fog density mismatch py/js for {s_id}"

    # hazard
    assert p.hazard.dps == d.hazard.dps == j["hazard"]["dps"], f"Hazard DPS mismatch for {s_id}"
    assert abs(p.hazard.slow_factor - d.hazard.slow_factor) < 1e-4, f"Hazard slow factor mismatch for {s_id}"

    # props count
    py_props = py_cat.get_props_for_style(s_id)
    db_props = service.get_props_for_style(s_id)
    js_props = j["props"]
    assert len(py_props) == len(db_props) == len(js_props) >= 3, f"Props count mismatch for {s_id}"

    for pp, dp, jp in zip(py_props, db_props, js_props):
        assert pp.prop_id == dp.prop_id == jp["prop_id"], f"Prop ID mismatch in {s_id}"
        assert pp.placement_rule == dp.placement_rule == jp["placement_rule"], f"Prop rule mismatch in {s_id}"
        assert abs(pp.spawn_weight - dp.spawn_weight) < 1e-4, f"Prop weight mismatch py/db in {s_id}"
        assert abs(pp.spawn_weight - jp["spawn_weight"]) < 1e-4, f"Prop weight mismatch py/js in {s_id}"

print("All 30 styles passed 100% attribute parity checks across Python, DB, and JS!")

# Check getTilePalette consistency
# In client, getTilePalette(biomeCode, tileCode) returns base, side, stroke, elev, floor, wall, path, liquid, ambient
for b_code in range(1, 31):
    s = py_cat.get_map_style_by_code(b_code)
    for t_code in range(20):
        tpal = js_data["tile_palettes"][str(b_code)][str(t_code)]
        assert tpal["floor"] == s.palette.floor
        assert tpal["wall"] == s.palette.wall
        assert tpal["path"] == s.palette.path
        assert tpal["liquid"] == s.palette.liquid
        assert tpal["ambient"] == s.palette.ambient

print("getTilePalette returned valid palettes matching style for all 30 biomes x 20 tiles (600 combinations)!")

# Backward compatibility lookup verification
legacy_names = [
    ("BLEACHED_BONE_CANYON", 1),
    ("SAVAGE_MANGROVE_SWAMP", 2),
    ("CRIMSON_BLOOD_FOREST", 3),
    ("OUTCAST_MINE_SHAFTS", 4),
    ("CORRUPTED_FIEND_RUINS", 5),
]

for legacy_name, expected_code in legacy_names:
    py_by_legacy = py_cat.get_style(legacy_name)
    assert py_by_legacy is not None, f"py get_style({legacy_name}) is None"
    assert py_by_legacy.biome_code == expected_code, f"py {legacy_name} code != {expected_code}"

    db_by_legacy = service.get_style(legacy_name)
    assert db_by_legacy is not None, f"db get_style({legacy_name}) is None"
    assert db_by_legacy.biome_code == expected_code, f"db {legacy_name} code != {expected_code}"

print("Backward compatibility biomes 1-5 legacy lookup verified across Python and DB!")
