# #region ComplianceStageBase [C:5] [TYPE Module] [SEMANTICS pydantic, clean-release, stage, compliance, context]
# @BRIEF Define shared contracts and helpers for pluggable clean-release compliance stages.
# @LAYER Domain
# @RELATION DEPENDS_ON -> [CleanReleaseModels]
# @RELATION DEPENDS_ON -> [LoggerModule]
# @INVARIANT  Stage execution is deterministic for equal input context.
# @SIDE_EFFECT  None (deterministic execution)
# @DATA_CONTRACT  Context -> StageResult

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import UTC, datetime
from typing import Any, Protocol
from uuid import uuid4

from ....core.logger import belief_scope, logger
from ....models.clean_release import (
    CleanPolicySnapshot,
    ComplianceDecision,
    ComplianceRun,
    ComplianceStageRun,
    ComplianceViolation,
    DistributionManifest,
    ReleaseCandidate,
    SourceRegistrySnapshot,
)
from ..enums import ComplianceStageName, ViolationSeverity


# #region ComplianceStageContext [TYPE Class]
# @BRIEF Immutable input envelope passed to each compliance stage.
@dataclass(frozen=True)
class ComplianceStageContext:
    run: ComplianceRun
    candidate: ReleaseCandidate
    manifest: DistributionManifest
    policy: CleanPolicySnapshot
    registry: SourceRegistrySnapshot


# #endregion ComplianceStageContext


# #region StageExecutionResult [TYPE Class]
# @BRIEF Structured stage output containing decision, details and violations.
@dataclass
class StageExecutionResult:
    decision: ComplianceDecision
    details_json: dict[str, Any] = field(default_factory=dict)
    violations: list[ComplianceViolation] = field(default_factory=list)


# #endregion StageExecutionResult


# #region ComplianceStage [TYPE Class]
# @BRIEF Protocol for pluggable stage implementations.
class ComplianceStage(Protocol):
    stage_name: ComplianceStageName

    def execute(self, context: ComplianceStageContext) -> StageExecutionResult: ...


# #endregion ComplianceStage


# #region build_stage_run_record [TYPE Function]
# @BRIEF Build persisted stage run record from stage result.
# @PRE  run_id and stage_name are non-empty.
# @POST  Returns ComplianceStageRun with deterministic identifiers and timestamps.
def build_stage_run_record(
    *,
    run_id: str,
    stage_name: ComplianceStageName,
    result: StageExecutionResult,
    started_at: datetime | None = None,
    finished_at: datetime | None = None,
) -> ComplianceStageRun:
    with belief_scope("build_stage_run_record"):
        now = datetime.now(UTC)
        return ComplianceStageRun(
            id=f"stg-{uuid4()}",
            run_id=run_id,
            stage_name=stage_name.value,
            status="SUCCEEDED"
            if result.decision != ComplianceDecision.ERROR
            else "FAILED",
            started_at=started_at or now,
            finished_at=finished_at or now,
            decision=result.decision.value,
            details_json=result.details_json,
        )


# #endregion build_stage_run_record


# #region build_violation [TYPE Function]
# @BRIEF Construct a compliance violation with normalized defaults.
# @PRE  run_id, stage_name, code and message are non-empty.
# @POST  Returns immutable-style violation payload ready for persistence.
def build_violation(
    *,
    run_id: str,
    stage_name: ComplianceStageName,
    code: str,
    message: str,
    artifact_path: str | None = None,
    severity: ViolationSeverity = ViolationSeverity.MAJOR,
    evidence_json: dict[str, Any] | None = None,
    blocked_release: bool = True,
) -> ComplianceViolation:
    with belief_scope("build_violation"):
        logger.reflect(f"Building violation stage={stage_name.value} code={code}")
        return ComplianceViolation(
            id=f"viol-{uuid4()}",
            run_id=run_id,
            stage_name=stage_name.value,
            code=code,
            severity=severity.value,
            artifact_path=artifact_path,
            artifact_sha256=None,
            message=message,
            evidence_json={
                **(evidence_json or {}),
                "blocked_release": blocked_release,
            },
        )


# #endregion build_violation

# #endregion ComplianceStageBase
