"""Minimal owner-only Telegram entry point for nutrition operations."""

from __future__ import annotations

import hashlib
from collections.abc import Mapping

from gateway.platforms.nutrition_coaching import IncomingAddress
from gateway.platforms.nutrition_operator_projection import operator_runtime_state

_ROOT_ACTIONS = (
    ("승인 대기", "approvals"),
    ("조정 제안", "adaptive"),
    ("고객 검색", "search"),
)


def _customers(coordinator: object) -> tuple[object, ...]:
    registry = getattr(coordinator, "registry", None) or getattr(
        coordinator,
        "_registry",
        None,
    )
    return tuple(getattr(registry, "customers", ()) or ())


def _spec(customer: object) -> object:
    return getattr(customer, "spec", customer)


def _customer_key(customer: object) -> str:
    return str(getattr(_spec(customer), "customer_key", "") or "").strip()


def _customer_token(customer: object) -> str:
    return hashlib.sha256(_customer_key(customer).encode("utf-8")).hexdigest()[:16]


def _detail_callback(customer: object) -> str:
    return f"noc1:detail:{_customer_token(customer)}"


def operator_queue(coordinator: object) -> Mapping[str, object]:
    pending = [
        customer
        for customer in _customers(coordinator)
        if getattr(_spec(customer), "enabled", False) is not True
    ]
    if not pending:
        return {
            "status": "empty",
            "text": "승인 대기 고객이 없습니다.",
            "buttons": [],
        }
    return {
        "status": "queue",
        "text": f"승인 대기 {len(pending)}명",
        "buttons": [
            {
                "label": str(
                    getattr(
                        _spec(customer),
                        "display_name",
                        _customer_key(customer),
                    )
                )[:80],
                "callback_data": _detail_callback(customer),
            }
            for customer in pending
        ],
    }


def customer_directory(coordinator: object) -> Mapping[str, object]:
    customers = _customers(coordinator)
    if not customers:
        return {
            "status": "empty",
            "text": "등록된 고객이 없습니다.",
            "buttons": [],
        }
    return {
        "status": "directory",
        "text": f"고객 {len(customers)}명",
        "buttons": [
            {
                "label": str(
                    getattr(
                        _spec(customer),
                        "display_name",
                        _customer_key(customer),
                    )
                )[:80],
                "callback_data": _detail_callback(customer),
            }
            for customer in customers
        ],
    }


def customer_detail(
    coordinator: object,
    callback_data: str,
) -> Mapping[str, object]:
    prefix = "noc1:detail:"
    if not callback_data.startswith(prefix):
        return {"status": "rejected", "text": "고객 정보를 찾을 수 없습니다."}
    token = callback_data.removeprefix(prefix)
    matches = [
        customer
        for customer in _customers(coordinator)
        if _customer_token(customer) == token
    ]
    if len(matches) != 1:
        return {"status": "rejected", "text": "고객 정보를 찾을 수 없습니다."}
    customer = _spec(matches[0])
    enabled = getattr(customer, "enabled", False) is True
    paused = getattr(customer, "paused", False) is True
    runtime_state = operator_runtime_state(
        coordinator,
        _customer_key(customer),
    )
    status = runtime_state.status_override or (
        "일시중지" if paused else ("진행 중" if enabled else "승인 대기")
    )
    consent = getattr(customer, "ai_processing_consent", None)
    consent_text = (
        str(getattr(consent, "notice_version", "") or "동의 완료")
        if getattr(consent, "granted", False) is True
        else "미동의"
    )
    schedule = getattr(customer, "schedule", None)
    daily_time = str(getattr(schedule, "daily_time", "") or "미설정")
    plan = getattr(customer, "plan", None)
    calories = getattr(plan, "calories_kcal", None)
    protein = getattr(plan, "protein_g", None)
    if calories is None or protein is None:
        weeks = tuple(getattr(plan, "weeks", ()) or ())
        current = weeks[0] if weeks else None
        calories = getattr(current, "calories_kcal", None)
        protein = getattr(current, "protein_g", None)
    plan_text = (
        f"{calories} kcal / P{protein}"
        if calories is not None and protein is not None
        else "확인 필요"
    )
    name = str(getattr(customer, "display_name", _customer_key(customer))).strip()
    return {
        "status": "detail",
        "text": (
            f"{name}\n"
            f"상태: {status}\n"
            f"동의: {consent_text}\n"
            f"아침 체크인: 평일 {daily_time}\n"
            f"현재 계획: {plan_text}\n"
            f"오늘 체크인: {runtime_state.checkin_state}\n"
            f"조정 제안: {runtime_state.proposal_state}"
        ),
        "buttons": [],
    }


def handle_action(
    coordinator: object,
    adaptive_service: object,
    *,
    address: IncomingAddress,
    owner_address: IncomingAddress | None,
    callback_data: str,
    message_id: object = "",
    chat_id: object = "",
    topic_id: object = "0",
) -> Mapping[str, object]:
    if owner_address is None or address.key != owner_address.key:
        return {
            "status": "rejected",
            "text": "이 메뉴를 사용할 권한이 없습니다.",
        }
    if callback_data == "noc1:approvals":
        return operator_queue(coordinator)
    if callback_data == "noc1:search":
        return customer_directory(coordinator)
    if callback_data.startswith("noc1:detail:"):
        return customer_detail(coordinator, callback_data)
    if callback_data == "noc1:adaptive":
        accepts = getattr(adaptive_service, "accepts", None)
        if callable(accepts) and accepts(address) is not True:
            return {
                "status": "route",
                "text": (
                    "조정 제안의 Preview·Confirm·Cancel은 기존 내부 검토방에서 "
                    "진행해 주세요."
                ),
            }
        opener = getattr(adaptive_service, "open_menu", None)
        if not callable(opener):
            return {
                "status": "rejected",
                "text": "조정 제안을 확인할 수 없습니다.",
            }
        result = opener(
            address,
            message_id=message_id,
            chat_id=chat_id,
            topic_id=topic_id,
        )
        return (
            result
            if isinstance(result, Mapping)
            else {
                "status": "rejected",
                "text": "조정 제안을 확인할 수 없습니다.",
            }
        )
    return {
        "status": "rejected",
        "text": "사용할 수 없는 운영 메뉴입니다.",
    }


def root_menu(
    address: IncomingAddress,
    *,
    owner_address: IncomingAddress | None,
) -> Mapping[str, object]:
    if owner_address is None or address.key != owner_address.key:
        return {
            "status": "rejected",
            "text": "이 메뉴를 사용할 권한이 없습니다.",
        }
    return {
        "status": "menu",
        "text": "영양 코칭 운영",
        "buttons": [
            {
                "label": label,
                "callback_data": f"noc1:{action}",
            }
            for label, action in _ROOT_ACTIONS
        ],
    }
