"""Phase 13: Operational Alerts — AlertRule and AlertInstance models."""

import enum
import uuid
from datetime import datetime

from sqlalchemy import (
    Boolean, Column, DateTime, ForeignKey,
    Index, Integer, String, Text,
)
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import relationship

from app.database import Base


# ── Enumerations ──────────────────────────────────────────────────────────────

class AlertSeverity(str, enum.Enum):
    critical = "critical"
    high     = "high"
    medium   = "medium"
    low      = "low"
    info     = "info"


class AlertStatus(str, enum.Enum):
    open         = "open"
    acknowledged = "acknowledged"
    resolved     = "resolved"
    dismissed    = "dismissed"


class AlertRuleType(str, enum.Enum):
    high_risk           = "high_risk"           # risk_score >= threshold
    stale_technique     = "stale_technique"     # not validated in N days
    coverage_regression = "coverage_regression" # coverage_pct dropped
    low_coverage        = "low_coverage"        # coverage below min
    expiry_wave         = "expiry_wave"         # many pending queue items
    new_technique       = "new_technique"       # new MITRE techniques added
    orphan_spike        = "orphan_spike"        # many unowned techniques
    custom              = "custom"              # future extension placeholder


# ── AlertRule ─────────────────────────────────────────────────────────────────

class AlertRule(Base):
    """
    Defines a condition that, when satisfied, fires an AlertInstance.

    System rules (is_system=True) are seeded at startup and cannot be deleted.
    Custom rules (is_system=False) can be created by admins.
    """

    __tablename__ = "alert_rules"

    id          = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    name        = Column(String(300), nullable=False)
    description = Column(Text, nullable=True)
    rule_type   = Column(String(50),  nullable=False)
    severity    = Column(String(20),  nullable=False, default=AlertSeverity.medium.value)
    is_enabled  = Column(Boolean,     nullable=False, default=True)
    is_system   = Column(Boolean,     nullable=False, default=False)  # seeded, not deletable

    # Rule-specific thresholds/config (varies by rule_type)
    config = Column(JSONB, nullable=False, default={})

    # Delivery
    notify_in_app  = Column(Boolean, nullable=False, default=True)
    notify_webhook = Column(Boolean, nullable=False, default=False)
    webhook_id     = Column(
        UUID(as_uuid=True),
        ForeignKey("webhook_configs.id", ondelete="SET NULL"),
        nullable=True,
    )

    # Cooldown — don't re-fire within N hours of last firing
    cooldown_hours = Column(Integer, nullable=False, default=24)

    # Meta
    created_by    = Column(
        UUID(as_uuid=True),
        ForeignKey("users.id", ondelete="SET NULL"),
        nullable=True,
    )
    created_at    = Column(DateTime, default=datetime.utcnow)
    last_fired_at = Column(DateTime, nullable=True)

    creator  = relationship("User",          foreign_keys=[created_by])
    instances = relationship("AlertInstance", back_populates="rule",
                             cascade="all, delete-orphan")

    __table_args__ = (
        Index("ix_alert_rules_type",      "rule_type"),
        Index("ix_alert_rules_enabled",   "is_enabled"),
    )


# ── AlertInstance ─────────────────────────────────────────────────────────────

class AlertInstance(Base):
    """
    A single firing of an AlertRule.

    Transitions: open → acknowledged → resolved
                 open → dismissed
    """

    __tablename__ = "alert_instances"

    id        = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    rule_id   = Column(
        UUID(as_uuid=True),
        ForeignKey("alert_rules.id", ondelete="SET NULL"),
        nullable=True,
    )
    # Denormalised fields kept for history even after rule deletion
    rule_name = Column(String(300), nullable=False)
    rule_type = Column(String(50),  nullable=False)
    severity  = Column(String(20),  nullable=False)

    title   = Column(String(500), nullable=False)
    message = Column(Text,        nullable=False)
    details = Column(JSONB,       nullable=True)   # structured context

    status          = Column(String(20),  nullable=False, default=AlertStatus.open.value)
    acknowledged_by = Column(
        UUID(as_uuid=True),
        ForeignKey("users.id", ondelete="SET NULL"),
        nullable=True,
    )
    acknowledged_at = Column(DateTime, nullable=True)
    resolved_at     = Column(DateTime, nullable=True)
    created_at      = Column(DateTime, default=datetime.utcnow)

    rule             = relationship("AlertRule",    back_populates="instances")
    acknowledger     = relationship("User",         foreign_keys=[acknowledged_by])

    __table_args__ = (
        Index("ix_alert_instances_rule_id",   "rule_id"),
        Index("ix_alert_instances_status",    "status"),
        Index("ix_alert_instances_severity",  "severity"),
        Index("ix_alert_instances_created",   "created_at"),
    )
