from __future__ import annotations

import hashlib
import json
import uuid
from datetime import datetime, timezone
from sqlite3 import Connection
from typing import Any

ACTIVE_STATUSES = {"active", "resolved", "muted"}


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


def alert_fingerprint(evidence: dict[str, Any] | None = None, *, explicit: str | None = None) -> str:
    if explicit:
        payload = explicit
    else:
        payload = json.dumps(evidence or {}, sort_keys=True, ensure_ascii=False, default=str)
    return hashlib.sha256(payload.encode("utf-8")).hexdigest()[:32]


def build_dedup_key(*, rule_id: str | None, entity_type: str | None, entity_id: str | None, priority: str, fingerprint: str) -> str:
    payload = "|".join([rule_id or "", entity_type or "", entity_id or "", priority, fingerprint])
    return hashlib.sha256(payload.encode("utf-8")).hexdigest()[:40]


def create_alert(
    conn: Connection,
    *,
    priority: str,
    category: str,
    message: str,
    entity_type: str | None = None,
    entity_id: str | None = None,
    rule_id: str | None = None,
    evidence: dict[str, Any] | None = None,
    fingerprint: str | None = None,
) -> str:
    now = utc_now()
    fp = alert_fingerprint(evidence, explicit=fingerprint)
    dedup_key = build_dedup_key(rule_id=rule_id, entity_type=entity_type, entity_id=entity_id, priority=priority, fingerprint=fp)
    existing = conn.execute(
        "SELECT alert_id, status, occurrence_count FROM alerts WHERE dedup_key=? AND status IN ('active','resolved','muted') ORDER BY created_at DESC LIMIT 1",
        (dedup_key,),
    ).fetchone()
    evidence_json = json.dumps(evidence or {}, sort_keys=True, ensure_ascii=False, default=str)
    if existing:
        conn.execute(
            "UPDATE alerts SET last_seen_at=?, occurrence_count=COALESCE(occurrence_count,1)+1, evidence_json=? WHERE alert_id=?",
            (now, evidence_json, existing["alert_id"]),
        )
        return existing["alert_id"]
    alert_id = str(uuid.uuid4())
    conn.execute(
        """
        INSERT INTO alerts(
            alert_id, priority, category, entity_type, entity_id, rule_id, message,
            evidence_json, status, created_at, last_seen_at, occurrence_count, fingerprint, dedup_key
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?, 1, ?, ?)
        """,
        (alert_id, priority, category, entity_type, entity_id, rule_id, message, evidence_json, now, now, fp, dedup_key),
    )
    return alert_id


def resolve_alert(conn: Connection, alert_id: str, *, note: str | None = None) -> None:
    conn.execute("UPDATE alerts SET status='resolved', resolved_at=? WHERE alert_id=?", (utc_now(), alert_id))
    conn.commit()


def mute_alert(conn: Connection, alert_id: str, *, muted_until: str | None = None) -> None:
    conn.execute("UPDATE alerts SET status='muted', muted_until=? WHERE alert_id=?", (muted_until, alert_id))
    conn.commit()
