# retoor <retoor@molodetz.nl>

from __future__ import annotations

import json
from datetime import datetime, timezone

from devplacepy.database import conditional_update_row, get_table
from devplacepy.utils import is_admin


class QuizError(Exception):
    pass


def _now() -> datetime:
    return datetime.now(timezone.utc)


def _iso(value: datetime | None = None) -> str:
    return (value or _now()).isoformat()


def _quizzes():
    return get_table("quizzes")


def _questions():
    return get_table("quiz_questions")


def _options():
    return get_table("quiz_options")


def _attempts():
    return get_table("quiz_attempts")


def _answers():
    return get_table("quiz_answers")


def born_live(fields: dict) -> dict:
    stamp = _iso()
    return {
        **fields,
        "created_at": fields.get("created_at") or stamp,
        "updated_at": stamp,
        "deleted_at": None,
        "deleted_by": None,
    }


def load_json(raw, fallback):
    if isinstance(raw, (list, dict)):
        return raw
    try:
        parsed = json.loads(raw or "")
    except (TypeError, ValueError):
        return fallback
    return parsed if isinstance(parsed, type(fallback)) else fallback


def dump_json(value) -> str:
    return json.dumps(value, ensure_ascii=False)


def get_quiz(quiz_uid: str) -> dict | None:
    if not quiz_uid:
        return None
    return _quizzes().find_one(uid=quiz_uid, deleted_at=None)


def is_quiz_owner(quiz: dict | None, user: dict | None) -> bool:
    return bool(quiz and user and quiz.get("user_uid") == user.get("uid"))


def can_view_quiz(quiz: dict | None, user: dict | None) -> bool:
    if not quiz:
        return False
    if quiz.get("status") == "published":
        return True
    return is_quiz_owner(quiz, user) or is_admin(user)


def guard_editable(quiz_uid: str) -> dict:
    rows = conditional_update_row(
        "quizzes",
        quiz_uid,
        "content_version = COALESCE(content_version, 0) + 1",
        "status = 'draft' AND deleted_at IS NULL",
        {},
    )
    if rows:
        return get_quiz(quiz_uid) or {}
    quiz = get_quiz(quiz_uid)
    if not quiz:
        raise QuizError("Quiz not found")
    raise QuizError("A published quiz can no longer be edited")


__all__ = [
    "QuizError",
    "born_live",
    "can_view_quiz",
    "conditional_update_row",
    "dump_json",
    "get_quiz",
    "guard_editable",
    "is_quiz_owner",
    "load_json",
    "_answers",
    "_attempts",
    "_iso",
    "_now",
    "_options",
    "_questions",
    "_quizzes",
]
