# [DEF:backend.src.services.clean_release.stages:Module]
# @TIER: STANDARD
# @SEMANTICS: clean-release, compliance, stages, state-machine
# @PURPOSE: Define compliance stage order and helper functions for deterministic run-state evaluation.
# @LAYER: Domain
# @RELATION: DEPENDS_ON -> backend.src.models.clean_release
# @INVARIANT: Stage order remains deterministic for all compliance runs.

from __future__ import annotations

from typing import Dict, Iterable, List

from ...models.clean_release import CheckFinalStatus, CheckStageName, CheckStageResult, CheckStageStatus

MANDATORY_STAGE_ORDER: List[CheckStageName] = [
    CheckStageName.DATA_PURITY,
    CheckStageName.INTERNAL_SOURCES_ONLY,
    CheckStageName.NO_EXTERNAL_ENDPOINTS,
    CheckStageName.MANIFEST_CONSISTENCY,
]


# [DEF:stage_result_map:Function]
# @PURPOSE: Convert stage result list to dictionary by stage name.
# @PRE: stage_results may be empty or contain unique stage names.
# @POST: Returns stage->status dictionary for downstream evaluation.
def stage_result_map(stage_results: Iterable[CheckStageResult]) -> Dict[CheckStageName, CheckStageStatus]:
    return {result.stage: result.status for result in stage_results}
# [/DEF:stage_result_map:Function]


# [DEF:missing_mandatory_stages:Function]
# @PURPOSE: Identify mandatory stages that are absent from run results.
# @PRE: stage_status_map contains zero or more known stage statuses.
# @POST: Returns ordered list of missing mandatory stages.
def missing_mandatory_stages(stage_status_map: Dict[CheckStageName, CheckStageStatus]) -> List[CheckStageName]:
    return [stage for stage in MANDATORY_STAGE_ORDER if stage not in stage_status_map]
# [/DEF:missing_mandatory_stages:Function]


# [DEF:derive_final_status:Function]
# @PURPOSE: Derive final run status from stage results with deterministic blocking behavior.
# @PRE: Stage statuses correspond to compliance checks.
# @POST: Returns one of COMPLIANT/BLOCKED/FAILED according to mandatory stage outcomes.
def derive_final_status(stage_results: Iterable[CheckStageResult]) -> CheckFinalStatus:
    status_map = stage_result_map(stage_results)
    missing = missing_mandatory_stages(status_map)
    if missing:
        return CheckFinalStatus.FAILED

    for stage in MANDATORY_STAGE_ORDER:
        if status_map.get(stage) == CheckStageStatus.FAIL:
            return CheckFinalStatus.BLOCKED
        if status_map.get(stage) == CheckStageStatus.SKIPPED:
            return CheckFinalStatus.FAILED

    return CheckFinalStatus.COMPLIANT
# [/DEF:derive_final_status:Function]
# [/DEF:backend.src.services.clean_release.stages:Module]