# retoor <retoor@molodetz.nl>

from __future__ import annotations

from devplacepy.database.moderation import (
    CONSENT_KINDS,
    MODERATION_ACTIONS as DECISION_KINDS,
    REPORT_REASONS,
    REPORT_STATUSES,
    REPORTABLE_TARGETS,
)

from ..spec import Action
from ._shared import body, confirm, path, query


TARGET_KEYS = ", ".join(REPORTABLE_TARGETS)
REASON_KEYS = ", ".join(REPORT_REASONS)
STATUS_KEYS = ", ".join(REPORT_STATUSES)
DECISION_KEYS = ", ".join(DECISION_KINDS)
CONSENT_KEYS = ", ".join(CONSENT_KINDS)
CONSENT_CHOICES = "; ".join(
    f"{kind} ({label})" for kind, label in CONSENT_KINDS.items()
)


MODERATION_ACTIONS: tuple[Action, ...] = (
    Action(
        name="report_reasons",
        method="GET",
        path="/reports/reasons",
        summary="List the reasons a piece of content can be reported under",
        requires_auth=False,
    ),
    Action(
        name="report_content",
        method="POST",
        path="/reports/{target_type}/{target_uid}",
        summary="Report content that breaks the community guidelines",
        description=(
            "Files a report a moderator reviews within the published response window. "
            "Use report_reasons to pick a valid reason key first."
        ),
        params=(
            path("target_type", f"Type of content being reported: {TARGET_KEYS}."),
            path("target_uid", "Uid of the reported item."),
            body("reason", f"Reason key: {REASON_KEYS}.", required=True),
            body("detail", "What the moderator should know, up to 2000 characters."),
        ),
    ),
    Action(
        name="list_my_reports",
        method="GET",
        path="/reports/mine",
        summary="List the reports you filed and their outcome",
        params=(
            query("status", f"Filter by status: {STATUS_KEYS}."),
            query("page", "Page number, 25 per page."),
        ),
    ),
    Action(
        name="list_reports",
        method="GET",
        path="/admin/moderation",
        summary="List the moderation queue, oldest open report first",
        requires_admin=True,
        params=(
            query("status", f"Filter by status: {STATUS_KEYS}."),
            query("page", "Page number, 25 per page."),
        ),
    ),
    Action(
        name="get_report",
        method="GET",
        path="/admin/moderation/{uid}",
        summary="Read one report, its decisions and the author's moderation history",
        requires_admin=True,
        params=(path("uid", "Report uid."),),
    ),
    Action(
        name="set_report_status",
        method="POST",
        path="/admin/moderation/{uid}/status",
        summary="Move a report through the triage state machine",
        requires_admin=True,
        params=(
            path("uid", "Report uid."),
            body("status", f"New status: {STATUS_KEYS}.", required=True),
        ),
    ),
    Action(
        name="decide_report",
        method="POST",
        path="/admin/moderation/{uid}/decide",
        summary="Apply a moderation decision to a report",
        description=(
            "Removes or restores content, warns, suspends, bans, lifts, dismisses or "
            "escalates. The decision is recorded and the affected user is told why. "
            "Show the moderator the exact report and decision, get explicit "
            "confirmation, then call again with confirm=true."
        ),
        requires_admin=True,
        params=(
            path("uid", "Report uid."),
            body("action", f"Decision to apply: {DECISION_KEYS}.", required=True),
            body("reason", "Reason shown to the affected user."),
            body("notes", "Internal notes, never shown to the user."),
            body("duration_hours", "Suspension length in hours.", type="integer"),
            confirm(),
        ),
    ),
    Action(
        name="suspend_user",
        method="POST",
        path="/admin/users/{uid}/suspend",
        summary="Suspend an account for a fixed period with a stated reason",
        description=(
            "A suspended account can still read, see why, and delete itself, but "
            "cannot post. Show the moderator the exact account, get explicit "
            "confirmation, then call again with confirm=true."
        ),
        requires_admin=True,
        params=(
            path("uid", "User uid to suspend."),
            body("reason", "Reason shown to the user."),
            body("duration_hours", "Suspension length in hours.", type="integer"),
            confirm(),
        ),
    ),
    Action(
        name="lift_suspension",
        method="POST",
        path="/admin/users/{uid}/lift",
        summary="Lift a suspension or ban and restore the account",
        requires_admin=True,
        params=(path("uid", "User uid to restore."),),
    ),
    Action(
        name="accept_terms",
        method="POST",
        path="/auth/accept-terms",
        summary="Accept the current version of the Terms of Service",
        description=(
            "Records acceptance of the version in force and of the privacy policy. "
            "Show the user the terms first."
        ),
    ),
    Action(
        name="list_consents",
        method="GET",
        path="/profile/{username}",
        summary="List the consents on an account and whether each is granted",
        description=(
            "Only the account holder and an administrator see the consents; for anyone "
            "else the list comes back empty."
        ),
        params=(
            path("username", "Your own username, or an account you administer."),
            query("tab", "Profile tab (use privacy for this action)."),
        ),
    ),
    Action(
        name="set_consent",
        method="POST",
        path="/profile/{username}/consent",
        summary="Grant or withdraw one consent on your own account",
        description=(
            f"Kinds: {CONSENT_CHOICES}. Withdrawal takes effect immediately. Only the "
            "account holder can change a consent, administrators included."
        ),
        params=(
            path("username", "Your own username."),
            body("kind", f"Consent kind to change: {CONSENT_KEYS}.", required=True),
            body("granted", "1 to grant, 0 to withdraw.", required=True),
        ),
    ),
    Action(
        name="set_mature_content",
        method="POST",
        path="/profile/{username}/mature-content",
        summary="Turn the mature-content reveal on or off for your own account",
        params=(
            path("username", "Your own username."),
            body("mature_opt_in", "1 to show mature content, 0 to hide it.", required=True),
        ),
    ),
    Action(
        name="view_account_deletion",
        method="GET",
        path="/profile/{username}/delete",
        summary="Read what account deletion removes, what it retains and the grace window",
        description=(
            "Returns the removed list, the retained list and the grace window in hours. "
            "Read it and show it to the user before calling delete_my_account. Only the "
            "account holder may read it."
        ),
        params=(path("username", "Your own username."),),
    ),
    Action(
        name="delete_my_account",
        method="POST",
        path="/profile/{username}/delete",
        summary="Permanently delete your own account and personal data",
        description=(
            "Only the account holder can do this, and only with their password. "
            "Sessions are revoked, the profile is anonymised at once, and the content "
            "is purged after the published grace window. Show the user exactly what "
            "will be removed, get explicit confirmation, then call again with "
            "confirm=true."
        ),
        params=(
            path("username", "Your own username."),
            body("password", "Your account password.", required=True),
            confirm(),
        ),
    ),
    Action(
        name="list_published_workspaces",
        method="GET",
        path="/workspaces/index",
        summary="List every workspace published to the public ingress, with its link",
        requires_auth=False,
        params=(query("page", "Page number, 50 per page."),),
    ),
    Action(
        name="ban_user",
        method="POST",
        path="/admin/users/{uid}/ban",
        summary="Permanently close an account with a stated reason",
        description=(
            "Disables the account, revokes every session and token, and tells the "
            "user why. Show the moderator the exact account, get explicit "
            "confirmation, then call again with confirm=true."
        ),
        requires_admin=True,
        params=(
            path("uid", "User uid to ban."),
            body("reason", "Reason shown to the user."),
            confirm(),
        ),
    ),
)
