"""Durable answer-failure handoff for nutrition onboarding."""

from __future__ import annotations

from pathlib import Path
from typing import cast

from checkin_cli.nutrition_onboarding_contract import (
    MessageEvidence,
    OnboardingAuthority,
    OnboardingStatus,
    questionnaire_screens,
)
from checkin_cli.nutrition_onboarding_models import OnboardingState
from checkin_cli.nutrition_onboarding_reconciliation import load_reconciliation
from checkin_cli.nutrition_onboarding_session import (
    build_status,
    load_mutable_session,
    save_session,
    session_cursor,
)


def increment_answer_failure(
    document: dict[str, object],
    *,
    field: str,
    return_state: OnboardingState,
    force_handoff: bool = False,
) -> int:
    """Increment one field and bind a handoff without consuming an update."""
    raw_failures = document.get("answer_failures")
    failures = (
        cast(dict[str, object], raw_failures)
        if isinstance(raw_failures, dict)
        else {}
    )
    current = failures.get(field)
    count = current + 1 if type(current) is int and current >= 0 else 1
    failures[field] = count
    document["answer_failures"] = failures
    if force_handoff or count >= 2:
        document.update(
            state=OnboardingState.INPUT_HELP.value,
            input_help_field=field,
            input_help_return_state=return_state.value,
        )
    return count


class NutritionOnboardingInputHelpMixin:
    """Pause one unresolved answer until an owner reopens the same question."""

    _input_help_customer_key: str
    _input_help_session_path: Path

    def __init__(
        self,
        *,
        input_help_customer_key: str,
        input_help_session_path: Path,
    ) -> None:
        self._input_help_customer_key = input_help_customer_key
        self._input_help_session_path = input_help_session_path

    def _validate_storage(self) -> None:
        raise NotImplementedError

    def _validate_current_authority(
        self,
        authority: OnboardingAuthority,
    ) -> None:
        _ = authority
        raise NotImplementedError

    def record_answer_failure(
        self,
        *,
        field: str,
        authority: OnboardingAuthority,
        evidence: MessageEvidence,
        force_handoff: bool = False,
    ) -> OnboardingStatus:
        """Persist one rejected answer and pause for owner help when needed."""
        self._validate_storage()
        self._validate_current_authority(authority)
        document = load_mutable_session(
            session_path=self._input_help_session_path,
            customer_key=self._input_help_customer_key,
            authority=authority,
            evidence=evidence,
            role="customer",
        )
        state = OnboardingState(str(document["state"]))
        if state is OnboardingState.COLLECTING:
            cursor = session_cursor(document)
            raw_answers = document.get("answers")
            answers = (
                cast(dict[str, object], raw_answers)
                if isinstance(raw_answers, dict)
                else {}
            )
            raw_version = document.get("questionnaire_version")
            version = raw_version if isinstance(raw_version, str) else None
            screens = questionnaire_screens(version, answers)
            if cursor >= len(screens) or screens[cursor] != field:
                raise ValueError("answer failure field is not current")
        elif state is OnboardingState.CUSTOMER_ATTESTATION:
            reconciliation = load_reconciliation(
                document.get("reconciliation")
            )
            issues = reconciliation.get("issues")
            first_issue = (
                cast(dict[str, object], issues[0])
                if isinstance(issues, list)
                and issues
                and isinstance(issues[0], dict)
                else None
            )
            if first_issue is None or first_issue.get("field") != field:
                raise ValueError(
                    "answer failure clarification is not current"
                )
        else:
            raise ValueError("answer failure is not available")
        _ = increment_answer_failure(
            document,
            field=field,
            return_state=state,
            force_handoff=force_handoff,
        )
        save_session(
            session_path=self._input_help_session_path,
            document=document,
            evidence=evidence,
        )
        return build_status(
            customer_key=self._input_help_customer_key,
            document=document,
        )

    def resume_input_help(
        self,
        *,
        authority: OnboardingAuthority,
        evidence: MessageEvidence,
    ) -> OnboardingStatus:
        """Resume the exact question after an owner-assisted handoff."""
        self._validate_storage()
        self._validate_current_authority(authority)
        document = load_mutable_session(
            session_path=self._input_help_session_path,
            customer_key=self._input_help_customer_key,
            authority=authority,
            evidence=evidence,
            role="owner",
        )
        if document.get("state") != OnboardingState.INPUT_HELP.value:
            raise ValueError("input help is not available")
        field = document.get("input_help_field")
        return_state = document.get("input_help_return_state")
        if not isinstance(field, str) or return_state not in {
            OnboardingState.COLLECTING.value,
            OnboardingState.CUSTOMER_ATTESTATION.value,
        }:
            raise ValueError("input help binding is invalid")
        failures = document.get("answer_failures")
        if isinstance(failures, dict):
            cast(dict[str, object], failures)[field] = 0
        document["state"] = return_state
        _ = document.pop("input_help_field", None)
        _ = document.pop("input_help_return_state", None)
        save_session(
            session_path=self._input_help_session_path,
            document=document,
            evidence=evidence,
        )
        return build_status(
            customer_key=self._input_help_customer_key,
            document=document,
        )
