"""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)
    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")),
    )


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)
