# #region Test.CleanRelease.DTO [C:2] [TYPE Module] [SEMANTICS test,clean-release,dto,schema]
# @BRIEF Tests for clean release DTO models — construction, serialization, defaults, field types.
# @RELATION BINDS_TO -> [clean_release_dto]

from datetime import datetime
import pytest

from src.services.clean_release.dto import (
    ArtifactDTO,
    CandidateDTO,
    CandidateOverviewDTO,
    ComplianceRunDTO,
    ManifestDTO,
    ReportDTO,
)
from src.services.clean_release.enums import CandidateStatus, ComplianceDecision, RunStatus


class TestCandidateDTO:
    """CandidateDTO — construction and field validation."""

    # #region test_candidate_dto_basic [C:2] [TYPE Function]
    def test_candidate_dto_basic(self):
        """Basic CandidateDTO constructed with required fields."""
        now = datetime.now()
        dto = CandidateDTO(
            id="cand-1", version="1.0.0", source_snapshot_ref="git:sha",
            build_id="build-1", created_at=now, created_by="tester",
            status=CandidateStatus.DRAFT,
        )
        assert dto.id == "cand-1"
        assert dto.version == "1.0.0"
        assert dto.build_id == "build-1"
        assert dto.status == CandidateStatus.DRAFT
    # #endregion test_candidate_dto_basic

    # #region test_candidate_dto_default_build_id [C:2] [TYPE Function]
    def test_candidate_dto_default_build_id(self):
        """build_id defaults to None."""
        now = datetime.now()
        dto = CandidateDTO(
            id="cand-1", version="1.0.0", source_snapshot_ref="git:sha",
            created_at=now, created_by="tester", status=CandidateStatus.PREPARED,
        )
        assert dto.build_id is None
    # #endregion test_candidate_dto_default_build_id


class TestArtifactDTO:
    """ArtifactDTO — field defaults and construction."""

    # #region test_artifact_dto_basic [C:2] [TYPE Function]
    def test_artifact_dto_basic(self):
        """Basic ArtifactDTO constructed."""
        dto = ArtifactDTO(
            id="art-1", candidate_id="cand-1", path="bin/app",
            sha256="abc123", size=42,
        )
        assert dto.id == "art-1"
        assert dto.size == 42
        assert dto.detected_category is None
        assert dto.metadata == {}
    # #endregion test_artifact_dto_basic

    # #region test_artifact_dto_with_all_fields [C:2] [TYPE Function]
    def test_artifact_dto_with_all_fields(self):
        """All optional fields populated."""
        dto = ArtifactDTO(
            id="art-1", candidate_id="cand-1", path="bin/app",
            sha256="abc", size=42, detected_category="binary",
            declared_category="executable", source_uri="https://src",
            source_host="internal.local", metadata={"key": "val"},
        )
        assert dto.detected_category == "binary"
        assert dto.source_host == "internal.local"
        assert dto.metadata == {"key": "val"}
    # #endregion test_artifact_dto_with_all_fields


class TestManifestDTO:
    """ManifestDTO — construction."""

    # #region test_manifest_dto_basic [C:2] [TYPE Function]
    def test_manifest_dto_basic(self):
        """ManifestDTO constructed with all fields."""
        now = datetime.now()
        dto = ManifestDTO(
            id="man-1", candidate_id="cand-1", manifest_version=1,
            manifest_digest="digest", artifacts_digest="adigest",
            created_at=now, created_by="tester",
            source_snapshot_ref="ref", content_json={"items": []},
        )
        assert dto.manifest_version == 1
        assert dto.content_json == {"items": []}
    # #endregion test_manifest_dto_basic


class TestComplianceRunDTO:
    """ComplianceRunDTO — status tracking DTO."""

    # #region test_compliance_run_dto [C:2] [TYPE Function]
    def test_compliance_run_dto(self):
        """ComplianceRunDTO with minimal fields."""
        dto = ComplianceRunDTO(
            run_id="run-1", candidate_id="cand-1", status=RunStatus.RUNNING,
        )
        assert dto.run_id == "run-1"
        assert dto.status == RunStatus.RUNNING
        assert dto.final_status is None
        assert dto.report_id is None
    # #endregion test_compliance_run_dto

    # #region test_compliance_run_dto_full [C:2] [TYPE Function]
    def test_compliance_run_dto_full(self):
        """ComplianceRunDTO with all optional fields."""
        dto = ComplianceRunDTO(
            run_id="run-1", candidate_id="cand-1", status=RunStatus.SUCCEEDED,
            final_status=ComplianceDecision.PASSED, report_id="CCR-1", task_id="task-1",
        )
        assert dto.final_status == ComplianceDecision.PASSED
        assert dto.task_id == "task-1"
    # #endregion test_compliance_run_dto_full


class TestReportDTO:
    """ReportDTO — compact report view."""

    # #region test_report_dto [C:2] [TYPE Function]
    def test_report_dto(self):
        """ReportDTO constructed."""
        now = datetime.now()
        dto = ReportDTO(
            report_id="CCR-1", candidate_id="cand-1",
            final_status=ComplianceDecision.PASSED, policy_version="1.0",
            manifest_digest="digest", violation_count=0, generated_at=now,
        )
        assert dto.report_id == "CCR-1"
        assert dto.violation_count == 0
        assert dto.final_status == ComplianceDecision.PASSED
    # #endregion test_report_dto


class TestCandidateOverviewDTO:
    """CandidateOverviewDTO — read model for candidate overview."""

    # #region test_candidate_overview_dto_basic [C:2] [TYPE Function]
    def test_candidate_overview_dto_basic(self):
        """CandidateOverviewDTO with only required fields."""
        dto = CandidateOverviewDTO(
            candidate_id="cand-1", version="1.0.0",
            source_snapshot_ref="ref", status=CandidateStatus.DRAFT,
        )
        assert dto.candidate_id == "cand-1"
        assert dto.latest_manifest_id is None
        assert dto.latest_approval_decision is None
    # #endregion test_candidate_overview_dto_basic

    # #region test_candidate_overview_dto_full [C:2] [TYPE Function]
    def test_candidate_overview_dto_full(self):
        """CandidateOverviewDTO with all optional fields."""
        dto = CandidateOverviewDTO(
            candidate_id="cand-1", version="1.0.0",
            source_snapshot_ref="ref", status=CandidateStatus.APPROVED,
            latest_manifest_id="man-1", latest_manifest_digest="digest",
            latest_run_id="run-1", latest_run_status=RunStatus.SUCCEEDED,
            latest_report_id="CCR-1", latest_report_final_status=ComplianceDecision.PASSED,
            latest_policy_snapshot_id="policy-1", latest_policy_version="1.0",
            latest_registry_snapshot_id="reg-1", latest_registry_version="1.0",
            latest_approval_decision="APPROVED",
            latest_publication_id="pub-1", latest_publication_status="ACTIVE",
        )
        assert dto.latest_manifest_id == "man-1"
        assert dto.latest_approval_decision == "APPROVED"
        assert dto.latest_publication_status == "ACTIVE"
        assert dto.latest_run_status == RunStatus.SUCCEEDED
    # #endregion test_candidate_overview_dto_full
