from __future__ import annotations

import asyncio
import json
from collections.abc import Callable
from typing import cast

from gateway.platforms.nutrition_onboarding_reconciliation import (
    NutritionOnboardingReconciliation,
    ReconciliationUnavailable,
    parse_reconciliation_json,
)


def _configured_client() -> tuple[object | None, str | None]:
    from agent.auxiliary_client import get_text_auxiliary_client

    return cast(
        tuple[object | None, str | None],
        get_text_auxiliary_client(
            "nutrition_onboarding_reconciliation"
        ),
    )


class NutritionOnboardingReconciler:
    def __init__(
        self,
        client_factory: (
            Callable[[], tuple[object | None, str | None]] | None
        ) = None,
    ) -> None:
        self._client_factory = client_factory or _configured_client

    async def reconcile(
        self,
        answers: dict[str, object],
        *,
        consent_granted: bool,
    ) -> NutritionOnboardingReconciliation:
        if not consent_granted:
            raise ReconciliationUnavailable(
                "AI processing consent is required"
            )
        client, model = self._client_factory()
        if client is None or not model:
            raise ReconciliationUnavailable(
                "configured reconciliation model is unavailable"
            )
        prompt = json.dumps(
            answers,
            ensure_ascii=False,
            sort_keys=True,
            separators=(",", ":"),
        )

        def invoke() -> object:
            chat = getattr(client, "chat")
            completions = getattr(chat, "completions")
            create = getattr(completions, "create")
            return create(
                model=model,
                messages=[
                    {
                        "role": "system",
                        "content": (
                            "Return one plain JSON object with exactly: "
                            "summary_ko, facts_ko, ambiguities_ko, "
                            "contradictions_ko, safety_observations_ko, "
                            "clarifications. Clarifications are objects with "
                            "exactly field, kind, question_ko. Field must be "
                            "one input key; kind is ambiguity or "
                            "contradiction. Use one unique field per item. "
                            "All list fields contain Korean strings. "
                            "Never decide readiness, approval, activation, "
                            "delivery, diagnosis, or treatment."
                        ),
                    },
                    {
                        "role": "user",
                        "content": prompt,
                    },
                ],
                temperature=0,
                max_tokens=1200,
                timeout=120,
            )

        try:
            response = await asyncio.to_thread(invoke)
            choices = getattr(response, "choices")
            message = getattr(choices[0], "message")
            raw = getattr(message, "content")
        except (AttributeError, IndexError, TypeError) as exc:
            raise ReconciliationUnavailable(
                "reconciliation provider response is incomplete"
            ) from exc
        except Exception as exc:
            raise ReconciliationUnavailable(
                f"reconciliation provider failed: {type(exc).__name__}"
            ) from exc
        if not isinstance(raw, str):
            raise ReconciliationUnavailable(
                "reconciliation provider returned no text"
            )
        return parse_reconciliation_json(raw)
