"""Data models for auto-remediation feature."""

from __future__ import annotations

from datetime import datetime  # noqa: TC003 - needed at runtime by Pydantic
from typing import Any, Literal

import orjson
from pydantic import BaseModel, ConfigDict, Field


class DetectionRule(BaseModel):
    """Server-defined detection rule."""

    model_config = ConfigDict(frozen=True)

    id: str
    version: str
    name: str
    description: str
    type: Literal["command", "http", "process", "log_pattern"]
    check: dict[str, Any]  # type-specific config
    interval: float = 60.0
    failure_threshold: int = 1
    enabled: bool = True


class PlaybookStep(BaseModel):
    """Single step in a remediation playbook."""

    model_config = ConfigDict(frozen=True)

    name: str
    command: str
    timeout: float = 60.0
    continue_on_error: bool = False


class Playbook(BaseModel):
    """Server-defined remediation playbook."""

    model_config = ConfigDict(frozen=True)

    id: str
    version: str
    name: str
    description: str
    rule_id: str
    steps: list[PlaybookStep]
    max_retries: int = 3
    verify_after: bool = True
    cooldown: float = 300.0


class PlaybookBundle(BaseModel):
    """Signed bundle of rules and playbooks from server."""

    version: str
    timestamp: datetime
    nonce: str  # UUID to prevent replay
    rules: list[DetectionRule]
    playbooks: list[Playbook]
    signature: str  # Base64-encoded ECDSA signature
    signature_algorithm: str = "ecdsa-sha256"
    key_id: str

    def get_signature_data(self) -> bytes:
        """Get canonical data for signature verification."""
        data = {
            "version": self.version,
            "timestamp": self.timestamp.isoformat(),
            "nonce": self.nonce,
            "rules": [r.model_dump() for r in self.rules],
            "playbooks": [p.model_dump() for p in self.playbooks],
        }
        return orjson.dumps(data, option=orjson.OPT_SORT_KEYS)


class StepResult(BaseModel):
    """Result of a single playbook step."""

    step_name: str
    command: str
    exit_code: int
    stdout: str
    stderr: str
    duration_ms: float
    success: bool


class RemediationResult(BaseModel):
    """Result of a remediation attempt."""

    rule_id: str
    playbook_id: str
    triggered_at: datetime
    completed_at: datetime
    success: bool
    steps_executed: list[StepResult]
    verified: bool
    verification_passed: bool | None = None
    error: str | None = None
    dry_run: bool = False


class DetectionResult(BaseModel):
    """Result of running a detection check."""

    rule_id: str
    rule_name: str
    check_type: str
    passed: bool
    message: str | None = None
    details: dict[str, Any] = Field(default_factory=dict)
    checked_at: datetime
    duration_ms: float
    consecutive_failures: int = 0


class RuleState(BaseModel):
    """Runtime state for a detection rule."""

    rule_id: str
    consecutive_failures: int = 0
    last_check_time: datetime | None = None
    last_remediation_time: datetime | None = None
    remediation_count: int = 0
    in_cooldown: bool = False
