# retoor <retoor@molodetz.nl>

from __future__ import annotations

from sqlalchemy.exc import IntegrityError

from devplacepy.database import get_table
from devplacepy.utils import generate_uid

from .. import economy
from .common import GameError, _iso, _now, _update_farm, conditional_update_farm
from .farm import ensure_farm


def _cosmetics():
    return get_table("game_cosmetics")


def owned_cosmetic_keys(user_uid: str) -> set[str]:
    return {row["cosmetic_key"] for row in _cosmetics().find(user_uid=user_uid)}


def buy_cosmetic(user: dict, key: str) -> dict:
    cosmetic = economy.cosmetic_for(key)
    if not cosmetic:
        raise GameError("Unknown cosmetic.")
    farm = ensure_farm(user["uid"])
    now = _iso(_now())
    row_uid = generate_uid()
    try:
        _cosmetics().insert(
            {
                "uid": row_uid,
                "user_uid": user["uid"],
                "cosmetic_key": key,
                "purchased_at": now,
                "created_at": now,
            }
        )
    except IntegrityError:
        raise GameError("You already own that cosmetic.")
    rows = conditional_update_farm(
        farm["uid"],
        set_clause="coins = coins - :cost",
        where_clause="coins >= :cost",
        params={"cost": cosmetic.cost_coins},
    )
    if rows == 0:
        _cosmetics().delete(uid=row_uid)
        raise GameError("Not enough coins for that cosmetic.")
    return {"key": key, "spent": cosmetic.cost_coins}


def equip_title(user: dict, key: str) -> dict:
    cosmetic = economy.cosmetic_for(key)
    if not cosmetic or cosmetic.kind != "title":
        raise GameError("Unknown title.")
    if key not in owned_cosmetic_keys(user["uid"]):
        raise GameError("You do not own that title.")
    farm = ensure_farm(user["uid"])
    _update_farm(farm["uid"], {"active_title": key})
    return {"active_title": key}
