# retoor <retoor@molodetz.nl>

from __future__ import annotations

from datetime import datetime, timezone

from devplacepy.database import get_table
from devplacepy.utils import generate_uid

FLAGS_TABLE = "workspace_flags"

SEVERITIES = ("info", "warn", "critical")
STATUSES = ("open", "acknowledged", "resolved", "dismissed")

KIND_CPU = "cpu_sustained"
KIND_EGRESS = "egress_spike"
KIND_REQUESTS = "request_rate"
KIND_ERRORS = "error_ratio"
KIND_DISK = "disk_growth"
KIND_TUNNEL_CHURN = "tunnel_churn"
KIND_MANUAL = "manual"


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


def open_flag(instance_uid: str, kind: str) -> dict | None:
    return get_table(FLAGS_TABLE).find_one(
        instance_uid=instance_uid, kind=kind, status="open", deleted_at=None
    )


def raise_flag(
    instance: dict,
    kind: str,
    severity: str = "warn",
    detail: str = "",
    metric_value: float = 0.0,
    threshold: float = 0.0,
) -> dict | None:
    if severity not in SEVERITIES:
        severity = "warn"
    instance_uid = instance.get("uid", "")
    if not instance_uid or not kind:
        return None
    table = get_table(FLAGS_TABLE)
    existing = open_flag(instance_uid, kind)
    if existing:
        table.update(
            {
                "uid": existing["uid"],
                "severity": severity,
                "detail": detail,
                "metric_value": float(metric_value),
                "threshold": float(threshold),
                "updated_at": _now(),
            },
            ["uid"],
        )
        return table.find_one(uid=existing["uid"])
    uid = generate_uid()
    table.insert(
        {
            "uid": uid,
            "instance_uid": instance_uid,
            "user_uid": instance.get("workspace_owner_uid", ""),
            "kind": kind,
            "severity": severity,
            "detail": detail,
            "metric_value": float(metric_value),
            "threshold": float(threshold),
            "status": "open",
            "resolved_by": "",
            "resolved_at": "",
            "created_at": _now(),
            "updated_at": _now(),
            "deleted_at": None,
            "deleted_by": None,
        }
    )
    return table.find_one(uid=uid)


def clear_flag(instance_uid: str, kind: str, resolved_by: str = "system") -> bool:
    existing = open_flag(instance_uid, kind)
    if not existing:
        return False
    get_table(FLAGS_TABLE).update(
        {
            "uid": existing["uid"],
            "status": "resolved",
            "resolved_by": resolved_by,
            "resolved_at": _now(),
            "updated_at": _now(),
        },
        ["uid"],
    )
    return True


def set_status(uid: str, status: str, actor_uid: str) -> bool:
    if status not in STATUSES:
        return False
    table = get_table(FLAGS_TABLE)
    row = table.find_one(uid=uid, deleted_at=None)
    if not row:
        return False
    changes = {"uid": uid, "status": status, "updated_at": _now()}
    if status in ("resolved", "dismissed"):
        changes["resolved_by"] = actor_uid
        changes["resolved_at"] = _now()
    table.update(changes, ["uid"])
    return True


def list_flags(
    instance_uid: str = "", user_uid: str = "", status: str = "open"
) -> list[dict]:
    filters: dict[str, object] = {"deleted_at": None}
    if instance_uid:
        filters["instance_uid"] = instance_uid
    if user_uid:
        filters["user_uid"] = user_uid
    if status:
        filters["status"] = status
    return list(get_table(FLAGS_TABLE).find(order_by=["-created_at"], **filters))


def has_critical(instance_uid: str) -> bool:
    for row in list_flags(instance_uid=instance_uid):
        if row.get("severity") == "critical":
            return True
    return False
