# retoor <retoor@molodetz.nl>

from .core import TTLCache, bump_cache_version, datetime, db, get_table, sync_local_cache, timezone
from .soft_delete import soft_delete


CUSTOMIZATION_GLOBAL_SCOPE = "global"


CUSTOMIZATION_LANGS = ("css", "js")


_customizations_cache = TTLCache(ttl=300, max_size=100)


def _customization_key(owner_kind: str, owner_id: str, page_type: str) -> str:
    return f"{owner_kind}\x1f{owner_id}\x1f{page_type}"


CUSTOMIZATION_PREF_COLUMNS = {
    "global": "cust_disable_global",
    "pagetype": "cust_disable_pagetype",
}


def get_customization_prefs(owner_kind: str, owner_id: str) -> dict:
    if owner_kind != "user" or "users" not in db.tables:
        return {"disable_global": False, "disable_pagetype": False}
    user = db["users"].find_one(uid=owner_id)
    if user is None:
        return {"disable_global": False, "disable_pagetype": False}
    return {
        "disable_global": bool(user.get("cust_disable_global", 0)),
        "disable_pagetype": bool(user.get("cust_disable_pagetype", 0)),
    }


def set_customization_pref(owner_id: str, category: str, disabled: bool) -> None:
    column = CUSTOMIZATION_PREF_COLUMNS.get(category)
    if column is None:
        raise ValueError(f"Unknown customization category: {category}")
    from devplacepy.utils import clear_user_cache

    get_table("users").update(
        {"uid": owner_id, column: 1 if disabled else 0}, ["uid"]
    )
    clear_user_cache(owner_id)
    bump_cache_version("customizations")


def get_custom_overrides(owner_kind: str, owner_id: str, page_type: str) -> dict:
    sync_local_cache("customizations", _customizations_cache)
    key = _customization_key(owner_kind, owner_id, page_type)
    cached = _customizations_cache.get(key)
    if cached is not None:
        return cached
    result = {"css": "", "js": ""}
    if "user_customizations" in db.tables:
        prefs = get_customization_prefs(owner_kind, owner_id)
        scopes = (CUSTOMIZATION_GLOBAL_SCOPE, page_type)
        rows = db["user_customizations"].find(
            owner_kind=owner_kind,
            owner_id=owner_id,
            enabled=1,
            deleted_at=None,
        )
        pieces: dict[str, dict[str, str]] = {lang: {} for lang in CUSTOMIZATION_LANGS}
        for row in rows:
            lang = row.get("lang")
            scope = row.get("scope")
            if lang not in pieces or scope not in scopes:
                continue
            if scope == CUSTOMIZATION_GLOBAL_SCOPE and prefs["disable_global"]:
                continue
            if scope != CUSTOMIZATION_GLOBAL_SCOPE and prefs["disable_pagetype"]:
                continue
            pieces[lang][scope] = row.get("code") or ""
        for lang in CUSTOMIZATION_LANGS:
            ordered = [pieces[lang][scope] for scope in scopes if scope in pieces[lang]]
            result[lang] = "\n".join(part for part in ordered if part.strip())
    _customizations_cache.set(key, result)
    return result


def get_custom_override(
    owner_kind: str, owner_id: str, scope: str, lang: str
) -> dict | None:
    if "user_customizations" not in db.tables:
        return None
    return db["user_customizations"].find_one(
        owner_kind=owner_kind,
        owner_id=owner_id,
        scope=scope,
        lang=lang,
        deleted_at=None,
    )


def list_custom_overrides(owner_kind: str, owner_id: str) -> list:
    if "user_customizations" not in db.tables:
        return []
    return list(
        db["user_customizations"].find(
            owner_kind=owner_kind, owner_id=owner_id, deleted_at=None
        )
    )


def set_custom_override(
    owner_kind: str, owner_id: str, scope: str, lang: str, code: str
) -> dict:
    from devplacepy.utils import generate_uid

    table = get_table("user_customizations")
    now = datetime.now(timezone.utc).isoformat()
    existing = table.find_one(
        owner_kind=owner_kind, owner_id=owner_id, scope=scope, lang=lang
    )
    if existing:
        record = {
            "id": existing["id"],
            "code": code,
            "enabled": 1,
            "updated_at": now,
            "deleted_at": None,
            "deleted_by": None,
        }
        table.update(record, ["id"])
        result = {**existing, **record}
    else:
        result = {
            "uid": generate_uid(),
            "owner_kind": owner_kind,
            "owner_id": owner_id,
            "scope": scope,
            "lang": lang,
            "code": code,
            "enabled": 1,
            "created_at": now,
            "updated_at": now,
            "deleted_at": None,
            "deleted_by": None,
        }
        table.insert(result)
    bump_cache_version("customizations")
    return result


def delete_custom_override(
    owner_kind: str,
    owner_id: str,
    scope: str | None = None,
    lang: str | None = None,
    deleted_by: str | None = None,
) -> int:
    if "user_customizations" not in db.tables:
        return 0
    criteria: dict = {"owner_kind": owner_kind, "owner_id": owner_id}
    if scope is not None:
        criteria["scope"] = scope
    if lang is not None:
        criteria["lang"] = lang
    count = soft_delete(
        "user_customizations", deleted_by or f"{owner_kind}:{owner_id}", **criteria
    )
    bump_cache_version("customizations")
    return int(count)
