# retoor <retoor@molodetz.nl>

from __future__ import annotations

from datetime import datetime, timedelta, timezone

from devplacepy.database import (
    _now_iso,
    get_table,
    restore_event,
    soft_delete,
)
from devplacepy.utils import clear_user_cache, create_notification


NOTICE_URL = "/docs/content-moderation.html"

REMOVABLE_TABLES: dict[str, str] = {
    "post": "posts",
    "gist": "gists",
    "project": "projects",
    "quiz": "quizzes",
    "news": "news",
}

SUBJECT_ONLY_TARGETS: frozenset[str] = frozenset(
    {"message", "user", "workspace", "poll", "devii_output"}
)


def notify_subject(user_uid: str, message: str) -> None:
    if not user_uid or not message:
        return
    create_notification(user_uid, "moderation", message, user_uid, NOTICE_URL)


def can_remove(target_type: str) -> bool:
    if target_type in REMOVABLE_TABLES:
        return True
    return target_type in ("comment", "attachment", "project_file")


def remove_content(request, admin: dict, target_type: str, target_uid: str) -> bool:
    if target_type in REMOVABLE_TABLES:
        from devplacepy.content import delete_content_item

        table_name = REMOVABLE_TABLES[target_type]
        delete_content_item(
            request,
            table_name,
            target_type,
            admin,
            target_uid,
            f"/{table_name}",
        )
        return True
    if target_type == "comment":
        from devplacepy.content import delete_comment_record

        comment = get_table("comments").find_one(uid=target_uid, deleted_at=None)
        if not comment:
            return False
        delete_comment_record(request, admin, comment)
        return True
    if target_type == "attachment":
        from devplacepy.attachments import soft_delete_attachment

        return bool(soft_delete_attachment(target_uid, admin["uid"]))
    if target_type == "project_file":
        node = get_table("project_files").find_one(uid=target_uid, deleted_at=None)
        if not node:
            return False
        soft_delete("project_files", admin["uid"], uid=target_uid)
        return True
    return False


def restore_content(target_type: str, target_uid: str) -> bool:
    table_name = REMOVABLE_TABLES.get(target_type)
    if target_type == "comment":
        table_name = "comments"
    elif target_type == "attachment":
        table_name = "attachments"
    elif target_type == "project_file":
        table_name = "project_files"
    if not table_name:
        return False
    row = get_table(table_name).find_one(uid=target_uid)
    if not row or not row.get("deleted_at"):
        return False
    restore_event(row["deleted_at"])
    return True


def suspend_user(subject: dict, hours: int, reason: str) -> str:
    until = (datetime.now(timezone.utc) + timedelta(hours=max(1, hours))).isoformat()
    get_table("users").update(
        {"uid": subject["uid"], "suspended_until": until, "suspension_reason": reason},
        ["uid"],
    )
    clear_user_cache(subject["uid"])
    return until


def lift_suspension(subject: dict) -> None:
    get_table("users").update(
        {"uid": subject["uid"], "suspended_until": "", "suspension_reason": ""},
        ["uid"],
    )
    clear_user_cache(subject["uid"])


def ban_user(subject: dict, reason: str) -> None:
    get_table("users").update(
        {
            "uid": subject["uid"],
            "is_active": False,
            "suspension_reason": reason,
            "suspended_until": "",
        },
        ["uid"],
    )
    revoke_sessions(subject["uid"])
    clear_user_cache(subject["uid"])


def unban_user(subject: dict) -> None:
    get_table("users").update(
        {"uid": subject["uid"], "is_active": True, "suspension_reason": ""}, ["uid"]
    )
    clear_user_cache(subject["uid"])


def revoke_sessions(user_uid: str) -> int:
    stamp = _now_iso()
    revoked = soft_delete("sessions", user_uid, stamp=stamp, user_uid=user_uid)
    revoked += soft_delete("access_tokens", user_uid, stamp=stamp, user_uid=user_uid)
    revoked += soft_delete("devrant_tokens", user_uid, stamp=stamp, user_uid=user_uid)
    return revoked
