# retoor <retoor@molodetz.nl>

import logging

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

from devplacepy.database import db, get_admin_uids, get_int_setting, get_users_by_uids
from devplacepy.responses import action_result, respond
from devplacepy.schemas import AdminDeviiTasksOut
from devplacepy.seo import base_seo_context, site_url, website_schema
from devplacepy.services.audit import record as audit
from devplacepy.services.devii import config as devii_config
from devplacepy.services.devii.tasks import limits
from devplacepy.services.devii.tasks.guards import DEFAULT_MAX_PER_OWNER
from devplacepy.services.devii.tasks.schedule import now_utc
from devplacepy.services.devii.tasks.store import TABLE, TaskStore
from devplacepy.utils import not_found, require_admin

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

STATES = ("active", "inactive", "all")


def _schedule_text(row: dict) -> str:
    kind = row.get("kind") or ""
    if kind == "interval":
        return f"every {row.get('every_seconds')}s"
    if kind == "cron":
        return f"cron {row.get('cron')}"
    return f"once {row.get('run_at') or ''}".strip()


def _rows(state: str) -> list[dict]:
    if TABLE not in db.tables:
        return []
    criteria: dict = {"deleted_at": None}
    if state == "active":
        criteria["enabled"] = True
    elif state == "inactive":
        criteria["enabled"] = False
    rows = list(db[TABLE].find(**criteria))
    rows.sort(key=lambda row: int(row.get("run_count") or 0), reverse=True)
    return rows


def _quotas(owner_uids: set[str]) -> dict[str, dict]:
    reference = now_utc()
    quotas = {}
    for owner_uid in owner_uids:
        runs = limits.run_quota(db, "user", owner_uid, reference)
        creations = limits.create_quota(db, "user", owner_uid, reference)
        quotas[owner_uid] = {
            "runs_used": runs.used,
            "runs_limit": runs.limit,
            "creates_used": creations.used,
            "creates_limit": creations.limit,
        }
    return quotas


def _items(rows: list[dict]) -> list[dict]:
    owners = get_users_by_uids([row.get("owner_id") for row in rows if row.get("owner_id")])
    admins = get_admin_uids()
    quotas = _quotas({str(row.get("owner_id") or "") for row in rows if row.get("owner_id")})
    items = []
    for row in rows:
        owner_uid = row.get("owner_id") or ""
        owner = owners.get(owner_uid)
        items.append(
            {
                "uid": row.get("uid"),
                "label": row.get("label") or row.get("uid"),
                "owner_uid": owner_uid,
                "owner": owner["username"] if owner else owner_uid,
                "owner_is_admin": owner_uid in admins,
                "quota": quotas.get(owner_uid, {}),
                "schedule": _schedule_text(row),
                "status": row.get("status") or "",
                "enabled": bool(row.get("enabled")),
                "run_count": int(row.get("run_count") or 0),
                "max_runs": row.get("max_runs"),
                "failure_count": int(row.get("failure_count") or 0),
                "next_run_at": row.get("next_run_at"),
                "expires_at": row.get("expires_at"),
                "last_error": row.get("last_error"),
            }
        )
    return items


def _require_task(uid: str) -> dict:
    row = db[TABLE].find_one(uid=uid, deleted_at=None) if TABLE in db.tables else None
    if row is None:
        raise not_found("Unknown task")
    return row


@router.get("/devii-tasks", response_class=HTMLResponse)
async def admin_devii_tasks(request: Request, state: str = "active"):
    admin = require_admin(request)
    if state not in STATES:
        state = "active"
    rows = _rows(state)
    items = _items(rows)
    bounds = {
        "max_concurrent": get_int_setting(
            devii_config.FIELD_TASK_MAX_CONCURRENT,
            devii_config.DEFAULT_TASK_MAX_CONCURRENT,
        ),
        "max_per_owner": get_int_setting(
            devii_config.FIELD_TASK_MAX_PER_OWNER, DEFAULT_MAX_PER_OWNER
        ),
        "max_failures": get_int_setting(
            devii_config.FIELD_TASK_MAX_FAILURES,
            devii_config.DEFAULT_TASK_MAX_FAILURES,
        ),
        "idle_days": get_int_setting(
            devii_config.FIELD_TASK_IDLE_DAYS, devii_config.DEFAULT_TASK_IDLE_DAYS
        ),
        "member_create_24h": limits.create_limit(False),
        "member_runs_24h": limits.run_limit(False),
        "admin_create_24h": limits.create_limit(True),
        "admin_runs_24h": limits.run_limit(True),
    }
    tabs = [
        {"key": key, "label": key.capitalize(), "active": key == state}
        for key in STATES
    ]
    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title="Devii tasks - Admin",
        description="Every scheduled Devii task, its owner, and its bounds.",
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Admin", "url": "/admin"},
            {"name": "Devii tasks", "url": "/admin/devii-tasks"},
        ],
        schemas=[website_schema(base)],
        robots="noindex,nofollow",
    )
    return respond(
        request,
        "admin_devii_tasks.html",
        {
            **seo_ctx,
            "request": request,
            "user": admin,
            "items": items,
            "state": state,
            "tabs": tabs,
            "limits": bounds,
            "admin_section": "devii-tasks",
        },
        model=AdminDeviiTasksOut,
    )


@router.post("/devii-tasks/{uid}/disable")
async def admin_devii_task_disable(request: Request, uid: str):
    admin = require_admin(request)
    row = _require_task(uid)
    store = TaskStore(db, str(row.get("owner_kind") or "user"), str(row.get("owner_id") or ""))
    store.update(
        uid,
        {
            "enabled": False,
            "status": "disabled",
            "next_run_at": None,
            "last_error": f"disabled by {admin['username']}",
        },
    )
    logger.info(f"Admin {admin['username']} disabled Devii task {uid}")
    audit.record(
        request,
        "admin.devii_task.disable",
        user=admin,
        target_type="task",
        target_uid=uid,
        target_label=row.get("label"),
        metadata={"owner_id": row.get("owner_id"), "run_count": row.get("run_count")},
        summary=f"{admin['username']} disabled Devii task {uid}",
    )
    return action_result(request, "/admin/devii-tasks")


@router.post("/devii-tasks/{uid}/delete")
async def admin_devii_task_delete(request: Request, uid: str):
    admin = require_admin(request)
    row = _require_task(uid)
    store = TaskStore(db, str(row.get("owner_kind") or "user"), str(row.get("owner_id") or ""))
    store.delete(uid)
    logger.info(f"Admin {admin['username']} deleted Devii task {uid}")
    audit.record(
        request,
        "admin.devii_task.delete",
        user=admin,
        target_type="task",
        target_uid=uid,
        target_label=row.get("label"),
        metadata={"owner_id": row.get("owner_id"), "run_count": row.get("run_count")},
        summary=f"{admin['username']} deleted Devii task {uid}",
    )
    return action_result(request, "/admin/devii-tasks")
