"""Redacted workflow-session persistence helpers."""

from __future__ import annotations

from pathlib import Path
from typing import cast

from checkin_cli.nutrition_onboarding_authority import validate_authority, validate_route
from checkin_cli.nutrition_onboarding_contract import (
    MessageEvidence,
    OnboardingAuthority,
    OnboardingStatus,
    canonical_digest,
    questionnaire_screens,
)
from checkin_cli.nutrition_onboarding_fs import atomic_write_private_json, read_private_json
from checkin_cli.nutrition_onboarding_models import OnboardingState


def session_cursor(document: dict[str, object]) -> int:
    cursor = document.get("cursor")
    if not isinstance(cursor, int):
        raise ValueError("invalid onboarding cursor")
    return cursor


def build_status(
    *,
    customer_key: str,
    document: dict[str, object],
) -> OnboardingStatus:
    cursor = session_cursor(document)
    state = OnboardingState(str(document["state"]))
    raw_answers = document.get("answers")
    if raw_answers is None:
        answers: dict[str, object] = {}
    elif not isinstance(raw_answers, dict):
        raise ValueError("invalid onboarding answers")
    else:
        typed_answers = cast(dict[str, object], raw_answers)
        answers = {
            field: value
            for field, value in typed_answers.items()
        }
    raw_version = document.get("questionnaire_version")
    questionnaire_version = raw_version if isinstance(raw_version, str) else None
    screens = questionnaire_screens(questionnaire_version, answers)
    collecting = state is OnboardingState.COLLECTING and cursor < len(screens)
    help_field_value = document.get("input_help_field")
    help_field = (
        help_field_value
        if state is OnboardingState.INPUT_HELP
        and isinstance(help_field_value, str)
        else None
    )
    current_field = (
        help_field
        if help_field is not None
        else screens[cursor]
        if cursor < len(screens)
        else None
    )
    if current_field is None and state is OnboardingState.CUSTOMER_ATTESTATION:
        reconciliation = document.get("reconciliation")
        issues = (
            cast(dict[str, object], reconciliation).get("issues")
            if isinstance(reconciliation, dict)
            else None
        )
        first_issue = (
            cast(dict[str, object], issues[0])
            if isinstance(issues, list)
            and issues
            and isinstance(issues[0], dict)
            else None
        )
        issue_field = first_issue.get("field") if first_issue else None
        current_field = issue_field if isinstance(issue_field, str) else None
    failures_value = document.get("answer_failures")
    failures = (
        cast(dict[str, object], failures_value)
        if isinstance(failures_value, dict)
        else {}
    )
    failure_count_value = failures.get(current_field) if current_field else None
    answer_failure_count = (
        failure_count_value
        if type(failure_count_value) is int and failure_count_value >= 0
        else 0
    )
    raw_baseline_digest = document.get("baseline_digest")
    baseline_digest = (
        raw_baseline_digest
        if isinstance(raw_baseline_digest, str)
        else None
    )
    return OnboardingStatus(
        customer_key=customer_key,
        state=state,
        answer_count=cursor,
        next_field=screens[cursor] if collecting else None,
        questionnaire_version=questionnaire_version,
        question_number=min(cursor + 1, len(screens)),
        question_total=len(screens),
        previous_cursor=cursor - 1 if cursor > 0 else None,
        baseline_digest=baseline_digest,
        owner_reviewed=bool(document.get("owner_reviewed")),
        help_field=help_field,
        answer_failure_count=answer_failure_count,
    )


def load_mutable_session(
    *,
    session_path: Path,
    customer_key: str,
    authority: OnboardingAuthority,
    evidence: MessageEvidence,
    role: str,
) -> dict[str, object]:
    validate_authority(authority, customer_key=customer_key)
    validate_route(authority, evidence, role=role)
    document = read_private_json(session_path)
    expected = canonical_digest(authority.model_dump(mode="json"))
    if document.get("authority_digest") != expected:
        raise ValueError("onboarding authority is stale")
    consumed = document.get("consumed_updates")
    if not isinstance(consumed, list) or evidence.update_id in consumed:
        raise ValueError("duplicate onboarding update")
    return document


def save_session(
    *,
    session_path: Path,
    document: dict[str, object],
    evidence: MessageEvidence,
) -> None:
    consumed = document["consumed_updates"]
    if not isinstance(consumed, list):
        raise ValueError("invalid consumed updates")
    consumed.append(evidence.update_id)
    atomic_write_private_json(session_path, document)
