# retoor <retoor@molodetz.nl>

import logging
from typing import Annotated

from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse

from devplacepy.database import (
    REPORT_STATUSES,
    SYSTEM_ACTOR,
    get_table,
    get_users_by_uids,
)
from devplacepy.dependencies import json_or_form
from devplacepy.models import ModerationDecisionForm, ReportStatusForm
from devplacepy.responses import action_result, json_error, respond
from devplacepy.routers.admin._shared import deny_senior, is_senior_admin
from devplacepy.schemas import AdminModerationOut, AdminReportOut
from devplacepy.seo import base_seo_context, site_url, website_schema
from devplacepy.services.audit import record as audit
from devplacepy.services.moderation import enforcement, queue, sla
from devplacepy.utils import create_notification, not_found, require_admin

logger = logging.getLogger(__name__)
router = APIRouter()

QUEUE_URL = "/admin/moderation"

STATUS_TABS = [
    {"key": "open", "label": "Open"},
    {"key": "acknowledged", "label": "Acknowledged"},
    {"key": "actioned", "label": "Actioned"},
    {"key": "dismissed", "label": "Dismissed"},
]

SUBJECT_ACTIONS = ("warn", "suspend", "ban", "lift")

ENFORCEMENT_EVENTS = {
    "remove_content": "moderation.remove",
    "restore_content": "moderation.restore",
    "warn": "moderation.warn",
    "suspend": "moderation.suspend",
    "ban": "moderation.ban",
    "lift": "moderation.lift",
}

DECISION_MESSAGES = {
    "remove_content": "Your {target} was removed after a moderation review.",
    "restore_content": "Your {target} was restored after a moderation review.",
    "warn": "A moderator issued a warning about your {target}.",
    "suspend": "Your account is suspended following a moderation review.",
    "ban": "Your account has been closed following a moderation review.",
    "lift": "Your account restriction has been lifted.",
}


def _breadcrumbs(extra: list[dict] | None = None) -> list[dict]:
    trail = [
        {"name": "Home", "url": "/feed"},
        {"name": "Admin", "url": "/admin"},
        {"name": "Moderation", "url": QUEUE_URL},
    ]
    return trail + (extra or [])


def _available_actions(target_type: str) -> list[str]:
    actions = ["dismiss", "escalate"]
    if enforcement.can_remove(target_type):
        actions = ["remove_content", "restore_content"] + actions
    return actions + list(SUBJECT_ACTIONS)


def _subject(report: dict) -> dict | None:
    owner_uid = report.get("owner_uid") or ""
    if not owner_uid:
        return None
    return get_users_by_uids([owner_uid]).get(owner_uid)


def _action_view(rows: list[dict]) -> list[dict]:
    actors = get_users_by_uids([row.get("actor_uid") for row in rows if row.get("actor_uid")])
    view = []
    for row in rows:
        actor = actors.get(row.get("actor_uid"))
        view.append(
            {
                "uid": row["uid"],
                "report_uid": row.get("report_uid", ""),
                "action": row.get("action", ""),
                "actor_name": actor["username"] if actor else row.get("actor_uid", ""),
                "reason": row.get("reason", ""),
                "notes": row.get("notes", ""),
                "expires_at": row.get("expires_at", ""),
                "created_at": row.get("created_at", ""),
            }
        )
    return view


@router.get("/moderation", response_class=HTMLResponse)
async def admin_moderation(request: Request, status: str = "open", page: int = 1):
    admin = require_admin(request)
    if status not in REPORT_STATUSES:
        status = "open"
    reports, pagination = queue.list_reports(status=status, page=page)
    counts = queue.status_counts()
    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title="Moderation - Admin",
        description="Triage reported content and apply moderation decisions.",
        robots="noindex,nofollow",
        breadcrumbs=_breadcrumbs(),
        schemas=[website_schema(base)],
    )
    return respond(
        request,
        "admin_moderation.html",
        {
            **seo_ctx,
            "request": request,
            "user": admin,
            "reports": reports,
            "pagination": pagination,
            "status": status,
            "statuses": [
                {**tab, "count": counts.get(tab["key"], 0), "active": tab["key"] == status}
                for tab in STATUS_TABS
            ],
            "counts": counts,
            "sla": sla.snapshot(),
            "admin_section": "moderation",
        },
        model=AdminModerationOut,
    )


@router.get("/moderation/{uid}", response_class=HTMLResponse)
async def admin_report_detail(request: Request, uid: str):
    admin = require_admin(request)
    report = queue.get_report(uid)
    if not report:
        raise not_found("Report not found")
    view = queue.enrich_reports([report])[0]
    subject = _subject(report)
    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title=f"Report {uid} - Admin",
        description="One reported item and the decisions taken on it.",
        robots="noindex,nofollow",
        breadcrumbs=_breadcrumbs([{"name": "Report", "url": f"{QUEUE_URL}/{uid}"}]),
        schemas=[website_schema(base)],
    )
    return respond(
        request,
        "admin_report.html",
        {
            **seo_ctx,
            "request": request,
            "user": admin,
            "report": view,
            "actions": _action_view(queue.actions_for_report(uid)),
            "history": _action_view(
                queue.actions_for_subject(report.get("owner_uid", ""))
            ),
            "available_actions": _available_actions(report["target_type"]),
            "can_remove": enforcement.can_remove(report["target_type"]),
            "subject": subject,
            "sla": sla.snapshot(),
            "admin_section": "moderation",
        },
        model=AdminReportOut,
    )


@router.post("/moderation/{uid}/status")
async def admin_report_status(
    request: Request,
    uid: str,
    data: Annotated[ReportStatusForm, Depends(json_or_form(ReportStatusForm))],
):
    admin = require_admin(request)
    report = queue.get_report(uid)
    if not report:
        raise not_found("Report not found")
    updated = queue.set_status(uid, data.status, admin["uid"])
    if not updated:
        return json_error(400, "Report status could not be changed")
    logger.info(f"Admin {admin['username']} set report {uid} to {data.status}")
    audit.record(
        request,
        "report.status",
        user=admin,
        target_type=report["target_type"],
        target_uid=report["target_uid"],
        old_value=report.get("status"),
        new_value=data.status,
        metadata={"report_uid": uid},
        summary=f"{admin['username']} set report {uid} to {data.status}",
        links=[audit.target(report["target_type"], report["target_uid"])],
    )
    return action_result(request, f"{QUEUE_URL}/{uid}")


@router.post("/moderation/{uid}/decide")
async def admin_report_decide(
    request: Request,
    uid: str,
    data: Annotated[ModerationDecisionForm, Depends(json_or_form(ModerationDecisionForm))],
):
    admin = require_admin(request)
    report = queue.get_report(uid)
    if not report:
        raise not_found("Report not found")
    action = data.action
    if action not in _available_actions(report["target_type"]):
        return json_error(400, "That action does not apply to this target")
    subject = _subject(report)
    if action in SUBJECT_ACTIONS:
        if not subject:
            return json_error(400, "This report has no account to act on")
        if is_senior_admin(admin, subject):
            return deny_senior(
                request,
                admin,
                subject["uid"],
                subject,
                f"moderation.{action}",
                redirect_url=f"{QUEUE_URL}/{uid}",
            )
    if action == "escalate":
        queue.escalate(uid)
    else:
        outcome = "dismissed" if action == "dismiss" else "actioned"
        if not queue.claim_open(uid, outcome, admin["uid"]):
            return json_error(409, "This report was already resolved")
    expires_at = ""
    if action == "remove_content":
        enforcement.remove_content(
            request, admin, report["target_type"], report["target_uid"]
        )
    elif action == "restore_content":
        enforcement.restore_content(report["target_type"], report["target_uid"])
    elif action == "suspend":
        expires_at = enforcement.suspend_user(subject, data.duration_hours, data.reason)
    elif action == "ban":
        enforcement.ban_user(subject, data.reason)
    elif action == "lift":
        enforcement.lift_suspension(subject)
        enforcement.unban_user(subject)
    queue.record_action(
        report_uid=uid,
        actor_uid=admin["uid"],
        action=action,
        target_type=report["target_type"],
        target_uid=report["target_uid"],
        subject_uid=subject["uid"] if subject else "",
        reason=data.reason,
        notes=data.notes,
        expires_at=expires_at,
    )
    logger.info(f"Admin {admin['username']} applied {action} to report {uid}")
    metadata = {
        "report_uid": uid,
        "action": action,
        "reason": data.reason,
        "subject_uid": subject["uid"] if subject else "",
    }
    links = [audit.target(report["target_type"], report["target_uid"])]
    audit.record(
        request,
        "report.decide",
        user=admin,
        target_type=report["target_type"],
        target_uid=report["target_uid"],
        metadata=metadata,
        summary=f"{admin['username']} applied {action} on report {uid}",
        links=links,
    )
    enforcement_key = ENFORCEMENT_EVENTS.get(action)
    if enforcement_key:
        audit.record(
            request,
            enforcement_key,
            user=admin,
            target_type=report["target_type"],
            target_uid=report["target_uid"],
            metadata=metadata,
            summary=f"{admin['username']} applied {action} from report {uid}",
            links=links,
        )
    _notify_subject(subject, action, report, data.reason)
    if action != "escalate":
        _notify_reporter(report, action)
    return action_result(request, f"{QUEUE_URL}/{uid}")


def _notify_subject(subject: dict | None, action: str, report: dict, reason: str) -> None:
    template = DECISION_MESSAGES.get(action)
    if not subject or not template:
        return
    message = template.format(target=report["target_type"])
    if reason:
        message = f"{message} Reason: {reason}."
    enforcement.notify_subject(subject["uid"], message)


def _notify_reporter(report: dict, action: str) -> None:
    reporter_uid = report.get("reporter_uid") or ""
    if not reporter_uid or reporter_uid == SYSTEM_ACTOR:
        return
    if not get_table("users").find_one(uid=reporter_uid):
        return
    verb = "dismissed" if action == "dismiss" else "actioned"
    create_notification(
        reporter_uid,
        "moderation",
        f"Your report on a {report['target_type']} was {verb}.",
        reporter_uid,
        "/reports/mine",
    )
