"""The GODVERSE modules — canonical naming per GODVERSE.md (the brand bible; lanes name to match it).

StoreGod is the BASE store-management app (vanilla: inventory, POS, store ops, universal identify+value over the
BaseGod brain — any goods). Each MODULE (RecordGod, ToolGod, VaultGod…) is a specialist ADD-ON unlocked on top,
deepening the store for one shopper-world. A store unlocks the modules for what it sells — MULTIPLE at once
(a pawnbroker enables records + tools + jewellery). Enabled via `STOREGOD_MODULES` (csv); the key's scope/features
on the DealGod side gate access + billing. Branding: one module → that BrandGod; many/none → "StoreGod".

Umbrella by shopper-world + data source (GODVERSE.md §naming): media (TMDb video), tech (electronics),
vault (graded collectibles = comics+cards+collectible toys), kid (family/kids resale). Cross-cutting FEATURES
(scangod/meltgod/stagegod/comps/lore/history) are capabilities, NOT modules — they ride on a key's `features`.
"""
import os
from dataclasses import dataclass

BASE_BRAND = "StoreGod"
BASE_FEATURES = ("identify", "value", "inventory", "pos", "supply")


@dataclass(frozen=True)
class Module:
    key: str                 # STOREGOD_MODULES token
    brand: str               # BrandGod name shown when this is the only module unlocked
    domains: tuple           # the DealGod scope domain(s) it unlocks (umbrellas carry several)
    condition_vocab: str     # grading vocab
    adds: tuple              # specialist features layered onto the base
    threed: bool


# Roster per GODVERSE.md. domains use DG1's published scope vocab
# (apparel·books·comics·computing·games·instruments·jewellery·music·phones·photo·tcg·tools·toys·video).
MODULES = {
    "records":   Module("records",   "RecordGod", ("music",),                       "goldmine", ("lore", "discogs_intake", "wishlist", "heal"), True),
    "media":     Module("media",     "MediaGod",  ("video",),                       "disc",     ("lore",),          False),
    "books":     Module("books",     "BookGod",   ("books",),                       "generic",  ("lore",),          False),
    "tech":      Module("tech",      "TechGod",   ("computing", "phones", "photo"), "grade",    ("comps", "lore"),  False),
    "tools":     Module("tools",     "ToolGod",   ("tools",),                       "tested",   ("lore",),          False),
    "play":      Module("play",      "PlayGod",   ("instruments",),                 "gear",     ("lore",),          True),
    "games":     Module("games",     "GameGod",   ("games",),                       "CIB",      ("comps", "lore"),  False),
    "jewellery": Module("jewellery", "JewelGod",  ("jewellery",),                   "hallmark", ("melt",),          False),
    "vault":     Module("vault",     "VaultGod",  ("comics", "tcg", "toys"),        "graded",   ("lore", "comps"),  False),
    "kids":      Module("kids",      "KidGod",    ("toys", "apparel"),              "generic",  ("comps",),         False),
    "kicks":     Module("kicks",     "KicksGod",  ("apparel",),                     "grade",    ("comps",),         False),
    "drip":      Module("drip",      "DripGod",   ("apparel",),                     "generic",  ("comps",),         False),
}

# legacy STOREGOD_PACK / module aliases → canonical key (back-compat for running containers + folded gods)
ALIASES = {"store": None, "": None, "instruments": "play", "computing": "tech", "phones": "tech",
           "comics": "vault", "cards": "vault", "tcg": "vault", "toys": "vault", "jewel": "jewellery"}


def _resolve(token: str):
    token = ALIASES.get(token, token)
    return MODULES.get(token) if token else None


def active_modules() -> list:
    """The unlocked modules. STOREGOD_MODULES (csv) preferred; falls back to legacy single STOREGOD_PACK
    ('store'/'' = vanilla base, no module). Unknown/folded tokens resolve via ALIASES."""
    env = os.getenv("STOREGOD_MODULES")
    tokens = ([t.strip() for t in env.split(",")] if env is not None
              else [os.getenv("STOREGOD_PACK", "records")])
    out, seen = [], set()
    for t in tokens:
        m = _resolve(t.strip())
        if m and m.key not in seen:
            out.append(m)
            seen.add(m.key)
    return out


def brand() -> str:
    m = active_modules()
    return m[0].brand if len(m) == 1 else BASE_BRAND


def active_scope() -> list:
    m = active_modules()
    if not m:
        return ["*"]                                       # no module = StoreGod base = every domain
    return sorted({d for mod in m for d in mod.domains})   # union of all unlocked modules' domains


def features() -> set:
    f = set(BASE_FEATURES)
    for m in active_modules():
        f |= set(m.adds)
    return f


def has_module(key: str) -> bool:
    mod = _resolve(key)
    return bool(mod) and any(m.key == mod.key for m in active_modules())


def has_feature(feat: str) -> bool:
    return feat in features()


def threed() -> bool:
    return any(m.threed for m in active_modules())


def info() -> dict:
    return {"brand": brand(), "base": BASE_BRAND, "modules": [m.key for m in active_modules()],
            "scope": active_scope(), "features": sorted(features()), "threed": threed()}


def _selfcheck():
    assert "identify" in features() and "value" in features()        # base always on
    os.environ["STOREGOD_MODULES"] = "records,tools"
    assert has_module("records") and has_module("tools")
    assert brand() == "StoreGod" and set(active_scope()) == {"music", "tools"}
    os.environ["STOREGOD_MODULES"] = "records"
    assert brand() == "RecordGod" and "discogs_intake" in features()
    os.environ["STOREGOD_MODULES"] = "vault"                          # umbrella → multi-domain
    assert brand() == "VaultGod" and set(active_scope()) == {"comics", "tcg", "toys"}
    os.environ["STOREGOD_MODULES"] = "comics"                         # folded alias → vault
    assert has_module("vault")
    os.environ["STOREGOD_MODULES"] = ""
    assert brand() == "StoreGod" and active_scope() == ["*"]
    del os.environ["STOREGOD_MODULES"]
    print("ok")


if __name__ == "__main__":
    _selfcheck()
