import hashlib
import html
import json
import math
import re
from pathlib import Path

import pandas as pd

MODULE_ID = "tomo-de-magia-od2"
INPUT = Path("/Volumes/rMacMiniM4/organizar/Downloads/foundry-tomo de magia.xlsx")
OUTPUT = Path(__file__).resolve().parents[1] / "data" / "spells.json"


def clean(value):
    if value is None:
        return ""
    if isinstance(value, float) and math.isnan(value):
        return ""
    text = str(value).strip()
    if text.endswith(".0") and text[:-2].isdigit():
        return text[:-2]
    return text


def split_list(value):
    text = clean(value)
    if not text:
        return []
    return [part.strip() for part in re.split(r"[,/]", text) if part.strip()]


def split_top_level(value):
    text = clean(value)
    if not text:
        return []

    parts = []
    current = []
    depth = 0
    for char in text:
        if char == "(":
            depth += 1
        elif char == ")":
            depth = max(0, depth - 1)

        if char in {",", "/"} and depth == 0:
            part = "".join(current).strip()
            if part:
                parts.append(part)
            current = []
        else:
            current.append(char)

    part = "".join(current).strip()
    if part:
        parts.append(part)
    return parts


def split_spheres(value):
    spheres = []
    for part in split_top_level(value):
        normalized = re.sub(r"\s+", " ", part).strip()
        elemental = re.fullmatch(r"Elementa[lr]\s*\(([^)]+)\)", normalized, flags=re.IGNORECASE)
        if elemental:
            for element in [piece.strip() for piece in elemental.group(1).split(",") if piece.strip()]:
                spheres.append(f"Elemental({element})")
            continue
        if normalized.lower() == "elementar":
            normalized = "Elemental"
        spheres.append(normalized)
    return spheres


def slugify(value):
    import unicodedata

    value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
    value = re.sub(r"[^a-zA-Z0-9]+", "-", value).strip("-").lower()
    return value or "magia"


def foundry_id(seed):
    alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    number = int(hashlib.sha256(seed.encode("utf-8")).hexdigest(), 16)
    chars = []
    for _ in range(16):
        number, idx = divmod(number, len(alphabet))
        chars.append(alphabet[idx])
    return "".join(chars)


def paragraphize(text):
    text = clean(text)
    if not text:
        return ""
    if "<" in text and ">" in text:
        return text
    paragraphs = [p.strip() for p in re.split(r"\n\s*\n", text) if p.strip()]
    return "\n".join(f"<p>{html.escape(p)}</p>" for p in paragraphs)


def meta_html(meta):
    lines = []
    if meta["escolas"]:
        lines.append(f"<p><strong>Escola:</strong> {html.escape(', '.join(meta['escolas']))}</p>")
    if meta["esferas"]:
        lines.append(f"<p><strong>Esfera:</strong> {html.escape(', '.join(meta['esferas']))}</p>")
    if meta.get("missao"):
        lines.append("<p><strong>Tipo:</strong> Magia de missão</p>")
    if meta.get("cooperativa"):
        lines.append("<p><strong>Tipo:</strong> Magia cooperativa</p>")
    for label, key in [
        ("Fonte", "fonte"),
        ("Pagina", "pagina"),
        ("Elemental", "elemental"),
        ("Selvagem", "selvagem"),
        ("Dark Sun", "darkSun"),
    ]:
        if meta.get(key):
            lines.append(f"<p><strong>{label}:</strong> {html.escape(meta[key])}</p>")
    if not lines:
        return ""
    return '<section class="tomo-de-magia-meta">' + "".join(lines) + "</section>"


def row_to_item(row, tradition, index):
    name = clean(row.get("Magia"))
    source_circle = clean(row.get("Círculo"))
    is_mission = tradition == "divine" and source_circle.lower() == "missão"
    circle = "1" if is_mission else source_circle
    is_cooperative = tradition == "divine" and name.endswith("*")
    meta = {
        "tradicao": tradition,
        "circulo": circle,
        "circuloOriginal": source_circle,
        "missao": is_mission,
        "cooperativa": is_cooperative,
        "fonte": clean(row.get("Fonte")),
        "escolas": split_list(row.get("Escola")),
        "esferas": split_spheres(row.get("Esfera")),
        "pagina": clean(row.get("Página")),
        "elemental": clean(row.get("Elemental")),
        "selvagem": clean(row.get("Selvagem")),
        "darkSun": clean(row.get("Dark Sun")),
        "indice": clean(row.get("Índice")),
    }
    item_id = foundry_id(f"{tradition}:{index}:{name}:{circle}")
    reverse = bool(clean(row.get("Reversível")))
    system = {
        "odo_id": f"tomo-{tradition}-{slugify(name)}",
        "school": tradition,
        "circle": circle,
        "arcane": circle if tradition == "arcane" else "null",
        "divine": circle if tradition == "divine" else "null",
        "necromancer": "null",
        "illusionist": "null",
        "reverse": reverse,
        "range": clean(row.get("Alcance")),
        "duration": clean(row.get("Duração")),
        "jp": clean(row.get("JP")) or "nenhuma",
        "description": meta_html(meta) + paragraphize(row.get("texto")),
    }
    return {
        "_id": item_id,
        "name": name,
        "type": "spell",
        "img": f"modules/{MODULE_ID}/assets/icons/spell-circle-{circle}.svg",
        "system": system,
        "effects": [],
        "flags": {
            MODULE_ID: meta
        },
        "ownership": {"default": 2},
        "sort": index * 1000,
    }


def valid_spell_row(row):
    circle = clean(row.get("Círculo"))
    return bool(clean(row.get("Magia")) and (circle.isdigit() or circle.lower() == "missão"))


def build():
    arcane = pd.read_excel(INPUT, sheet_name="arcana")
    divine = pd.read_excel(INPUT, sheet_name="divina")
    data = {
        "moduleId": MODULE_ID,
        "source": INPUT.name,
        "arcane": [
            row_to_item(row, "arcane", i)
            for i, row in arcane.iterrows()
            if valid_spell_row(row)
        ],
        "divine": [
            row_to_item(row, "divine", i)
            for i, row in divine.iterrows()
            if valid_spell_row(row)
        ],
    }
    OUTPUT.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
    print(f"Wrote {OUTPUT}")
    print(f"Arcane: {len(data['arcane'])}; Divine: {len(data['divine'])}")


if __name__ == "__main__":
    build()
