"""Tests for drift Pydantic models."""

from __future__ import annotations

import pytest
from backend.drift.models import (
    DriftAlertPayload,
    DriftConfigureRequest,
    DriftConfigureResponse,
    DriftFinding,
    DriftSetupInstructions,
    NormalizedDriftEvent,
)
from pydantic import ValidationError


class TestDriftModels:
    """Drift Pydantic model validation tests."""

    def test_drift_configure_request_all_none(self) -> None:
        req = DriftConfigureRequest()
        assert req.drift_mode is None
        assert req.drift_alerts is None
        assert req.state_source is None
        assert req.frameworks is None
        assert req.alert_email is None
        assert req.alert_threshold is None
        assert req.alert_webhook is None
        assert req.tfc_token is None

    @pytest.mark.parametrize("threshold", [0, 51, -1, 100])
    def test_drift_configure_request_threshold_bounds(self, threshold: int) -> None:
        with pytest.raises(ValidationError):
            DriftConfigureRequest(alert_threshold=threshold)

    @pytest.mark.parametrize("threshold", [1, 25, 50])
    def test_drift_configure_request_threshold_valid(self, threshold: int) -> None:
        req = DriftConfigureRequest(alert_threshold=threshold)
        assert req.alert_threshold == threshold

    def test_normalized_event_valid(self) -> None:
        event = NormalizedDriftEvent(
            cloud="gcp",
            cloud_account_id="my-project",
            resource_type="google_compute_instance",
            resource_id="//compute.googleapis.com/projects/my-proj/zones/us-central1-a/instances/vm1",
            change_type="create",
            event_timestamp="2026-01-01T00:00:00Z",
            raw_event={"test": True},
        )
        assert event.cloud == "gcp"
        assert event.change_type == "create"

    def test_drift_alert_payload_serialization(self) -> None:
        payload = DriftAlertPayload(
            project_label="prod",
            cloud="aws",
            old_score=85.0,
            new_score=78.0,
            score_delta=-7.0,
            top_findings=[
                DriftFinding(
                    control_id="CKV_AWS_1",
                    framework="cis_aws",
                    resource_address="aws_s3_bucket.main",
                    severity="high",
                )
            ],
            dashboard_url="https://dashboard.complyform.dev/projects/test",
            timestamp="2026-01-01T00:00:00Z",
        )
        data = payload.model_dump(mode="json")
        assert data["event"] == "drift_alert"
        assert data["score_delta"] == -7.0
        assert len(data["top_findings"]) == 1

    def test_drift_finding_severity_literal(self) -> None:
        for sev in ("critical", "high", "medium", "low"):
            f = DriftFinding(
                control_id="C1",
                framework="soc2",
                resource_address="res.foo",
                severity=sev,  # type: ignore[arg-type]
            )
            assert f.severity == sev

        with pytest.raises(ValidationError):
            DriftFinding(
                control_id="C1",
                framework="soc2",
                resource_address="res.foo",
                severity="unknown",  # type: ignore[arg-type]
            )

    def test_drift_configure_response_with_instructions(self) -> None:
        resp = DriftConfigureResponse(
            project_id="proj-1",
            drift_mode="event_driven",
            drift_alerts=True,
            setup_instructions=DriftSetupInstructions(
                cloud="gcp",
                webhook_url="https://api.complyform.dev/v1/drift/event",
                terraform_module_url="https://complyform.dev/docs/drift-setup/gcp/",
                variables={"project_id": "my-proj"},
                quickstart="1. Download\n2. Configure\n3. Apply",
            ),
            webhook_secret="cf_drift_abc123",
        )
        assert resp.setup_instructions is not None
        assert resp.webhook_secret == "cf_drift_abc123"

    def test_drift_configure_response_without_instructions(self) -> None:
        resp = DriftConfigureResponse(
            project_id="proj-1",
            drift_mode="scheduled",
            drift_alerts=True,
        )
        assert resp.setup_instructions is None
        assert resp.webhook_secret is None
