# retoor <retoor@molodetz.nl>

from __future__ import annotations

from devplacepy.utils import generate_uid

from .. import economy
from .common import _iso, _iso_week, _lvl, _now, _quests, _today, conditional_update_row
from .farm import get_farm


WEEKLY_SLOT_INDEX = 3


def _income_scale(farm: dict) -> float:
    return economy.social_reward_scale(
        _lvl(farm, "prestige"), _lvl(farm, "legacy_multiplier")
    )


def ensure_quests(farm: dict, day: str) -> None:
    if _quests().find_one(farm_uid=farm["uid"], day=day, scope="daily"):
        return
    now = _iso(_now())
    for index, quest in enumerate(
        economy.daily_quests(farm["user_uid"], day, _income_scale(farm))
    ):
        _quests().insert(
            {
                "uid": generate_uid(),
                "farm_uid": farm["uid"],
                "user_uid": farm["user_uid"],
                "day": day,
                "scope": "daily",
                "slot_index": index,
                "kind": quest["kind"],
                "label": quest["label"],
                "goal": quest["goal"],
                "progress": 0,
                "reward_coins": quest["reward_coins"],
                "reward_xp": quest["reward_xp"],
                "reward_stars": 0,
                "claimed": 0,
                "created_at": now,
                "updated_at": now,
            }
        )


def ensure_weekly_contract(farm: dict, iso_week: str) -> None:
    if not _lvl(farm, "mastery_contracts"):
        return
    if _quests().find_one(farm_uid=farm["uid"], day=iso_week, scope="weekly"):
        return
    now = _iso(_now())
    contract = economy.weekly_contract(farm["user_uid"], iso_week, _income_scale(farm))
    _quests().insert(
        {
            "uid": generate_uid(),
            "farm_uid": farm["uid"],
            "user_uid": farm["user_uid"],
            "day": iso_week,
            "scope": "weekly",
            "slot_index": WEEKLY_SLOT_INDEX,
            "kind": contract["kind"],
            "label": contract["label"],
            "goal": contract["goal"],
            "progress": 0,
            "reward_coins": 0,
            "reward_xp": contract["reward_xp"],
            "reward_stars": contract["reward_stars"],
            "claimed": 0,
            "created_at": now,
            "updated_at": now,
        }
    )


def advance_quests(user_uid: str, kind: str, amount: int) -> None:
    if amount <= 0:
        return
    try:
        farm = get_farm(user_uid)
        if not farm:
            return
        now = _now()
        day = _today()
        ensure_quests(farm, day)
        iso_week = _iso_week(now)
        ensure_weekly_contract(farm, iso_week)
        rows = list(_quests().find(farm_uid=farm["uid"], day=day, kind=kind, scope="daily"))
        rows += list(
            _quests().find(farm_uid=farm["uid"], day=iso_week, kind=kind, scope="weekly")
        )
        for row in rows:
            if row.get("claimed"):
                continue
            conditional_update_row(
                "game_quests",
                row["uid"],
                "progress = MIN(COALESCE(goal, 0), COALESCE(progress, 0) + :amount)",
                "COALESCE(claimed, 0) = 0",
                {"amount": amount},
            )
    except Exception:
        return
