"""update_attitude -- domain logic for attitude updates.

Extracted from app/tools/attitude_tool.py.
No sqlalchemy / fastapi / redis imports allowed.

Accepts an AttitudeStore protocol and an optional cache callback.
"""
from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import Any, Callable, Awaitable

from kokoro_chat.storage.protocol import AttitudeStore

logger = logging.getLogger(__name__)


@dataclass
class AttitudeUpdateResult:
    """Result of an attitude update operation."""

    success: bool
    affection: int = 0
    trust: int = 0
    mood: str = "neutral"
    error: str = ""


async def update_attitude(
    store: AttitudeStore,
    user_id: str,
    character_id: str,
    affection_delta: int,
    trust_delta: int,
    mood: str,
    on_updated: Callable[[str, str, dict[str, Any]], Awaitable[None]] | None = None,
) -> AttitudeUpdateResult:
    """Update character attitude toward a user.

    Parameters
    ----------
    store : AttitudeStore
        Protocol-based attitude storage.
    user_id, character_id : str
        Identifiers for the user/character pair.
    affection_delta, trust_delta : int
        Score changes (clamped to keep totals within 0-100).
    mood : str
        Current mood label.
    on_updated : callable, optional
        Async callback invoked after successful save with
        ``(user_id, character_id, snapshot_dict)``.  Typically used
        to update a cache layer.
    """
    try:
        state = await store.get_or_create(user_id, character_id)

        new_affection = max(0, min(100, state.affection + int(affection_delta)))
        new_trust = max(0, min(100, state.trust + int(trust_delta)))

        await store.save(
            user_id=user_id,
            character_id=character_id,
            affection=new_affection,
            trust=new_trust,
            mood=mood,
            modifiers_json=state.modifiers_json or "[]",
        )

        snapshot = {
            "affection": new_affection,
            "trust": new_trust,
            "mood": mood,
        }

        if on_updated is not None:
            await on_updated(user_id, character_id, snapshot)

        logger.info(
            "Attitude updated for user=%s char=%s: affection=%d trust=%d mood=%s",
            user_id, character_id, new_affection, new_trust, mood,
        )
        return AttitudeUpdateResult(
            success=True,
            affection=new_affection,
            trust=new_trust,
            mood=mood,
        )

    except Exception as e:
        logger.error("update_attitude failed: %s", e, exc_info=True)
        return AttitudeUpdateResult(success=False, error=str(e))
