from __future__ import annotations

import json
from typing import Any

from sqlalchemy import select

from services.shared.core import utc_now_iso
from services.shared.models import (
    VoiceNameCollectionConfig,
    VoiceNameCollectionConfigOut,
    VoiceNameCollectionLanguageTexts,
    VoiceNameCollectionTextsConfig,
)
from services.shared.sql_models import VoiceNameCollectionSettingsRow


VOICE_NAME_COLLECTION_SETTINGS_KEY = "global"


def voice_name_collection_default_config() -> VoiceNameCollectionConfig:
    return VoiceNameCollectionConfig(
        enabled=True,
        texts=VoiceNameCollectionTextsConfig(
            ru=VoiceNameCollectionLanguageTexts(
                start_prompt="Здравствуйте. Назовите, пожалуйста, ваше имя.",
                personalized_greeting_template=(
                    "Здравствуйте, {name}. Коротко расскажите, пожалуйста, чем помочь."
                ),
                confirmation_greeting_template=(
                    "Если я правильно расслышал, вас зовут {name}? И чем помочь?"
                ),
                inline_followup_prompt="И ещё подскажите, как мне к вам обращаться?",
            ),
            kz=VoiceNameCollectionLanguageTexts(
                start_prompt="Сәлеметсіз бе. Атыңызды атайсыз ба?",
                personalized_greeting_template=(
                    "Сәлеметсіз бе, {name}. Қысқаша айтыңызшы, не көмектесу керек."
                ),
                confirmation_greeting_template=(
                    "Егер дұрыс естісем, атыңыз {name}? Қалай көмектесемін?"
                ),
                inline_followup_prompt="Тағы бір нақтыласам, сізге қалай қараймын?",
            ),
        ),
    )


def _settings_row(session) -> VoiceNameCollectionSettingsRow | None:
    return session.execute(
        select(VoiceNameCollectionSettingsRow).where(
            VoiceNameCollectionSettingsRow.settings_key == VOICE_NAME_COLLECTION_SETTINGS_KEY
        )
    ).scalar_one_or_none()


def _normalize_config_payload(raw: Any) -> VoiceNameCollectionConfig:
    if isinstance(raw, VoiceNameCollectionConfig):
        return raw
    if not isinstance(raw, dict):
        raise ValueError("Voice name collection config payload must be an object")
    return VoiceNameCollectionConfig.model_validate(raw)


def load_voice_name_collection_config(session) -> VoiceNameCollectionConfigOut:
    default_config = voice_name_collection_default_config()
    row = _settings_row(session)
    if row is None:
        return VoiceNameCollectionConfigOut(config=default_config, updated_at=None, source="defaults")
    try:
        parsed = json.loads(row.config_json or "{}")
        config = _normalize_config_payload(parsed)
        return VoiceNameCollectionConfigOut(config=config, updated_at=row.updated_at, source="database")
    except Exception:
        return VoiceNameCollectionConfigOut(config=default_config, updated_at=row.updated_at, source="defaults")


def load_effective_voice_name_collection_config(session) -> VoiceNameCollectionConfig:
    return load_voice_name_collection_config(session).config


def save_voice_name_collection_config(
    session,
    config_payload: VoiceNameCollectionConfig | dict[str, Any],
) -> VoiceNameCollectionConfigOut:
    config = _normalize_config_payload(config_payload)
    row = _settings_row(session)
    now = utc_now_iso()
    if row is None:
        row = VoiceNameCollectionSettingsRow(
            settings_key=VOICE_NAME_COLLECTION_SETTINGS_KEY,
            config_json="{}",
            updated_at=now,
        )
        session.add(row)
    row.config_json = json.dumps(config.model_dump(), ensure_ascii=False)
    row.updated_at = now
    session.commit()
    session.refresh(row)
    return VoiceNameCollectionConfigOut(config=config, updated_at=row.updated_at, source="database")


def voice_name_collection_texts(
    config: VoiceNameCollectionConfig,
    language: str,
) -> VoiceNameCollectionLanguageTexts:
    if str(language or "").strip().lower() == "kz":
        return config.texts.kz
    return config.texts.ru


def voice_name_collection_start_prompt(config: VoiceNameCollectionConfig, language: str) -> str:
    return voice_name_collection_texts(config, language).start_prompt


def voice_name_collection_personalized_greeting(
    config: VoiceNameCollectionConfig,
    language: str,
    name: str,
) -> str:
    return voice_name_collection_texts(config, language).personalized_greeting_template.format(name=name)


def voice_name_collection_confirmation_greeting(
    config: VoiceNameCollectionConfig,
    language: str,
    name: str,
) -> str:
    return voice_name_collection_texts(config, language).confirmation_greeting_template.format(name=name)


def voice_name_collection_inline_followup(config: VoiceNameCollectionConfig, language: str) -> str:
    return voice_name_collection_texts(config, language).inline_followup_prompt


def voice_name_collection_followup_markers(
    config: VoiceNameCollectionConfig,
    language: str,
) -> tuple[str, ...]:
    texts = voice_name_collection_texts(config, language)
    markers = [texts.inline_followup_prompt]
    for template in (texts.confirmation_greeting_template, texts.personalized_greeting_template):
        for chunk in str(template or "").split("{name}"):
            normalized = chunk.strip(" ,.!?;:-")
            if len(normalized) >= 5:
                markers.append(normalized)
    markers.extend(
        [
            "как мне к вам обращаться",
            "как к вам обращаться",
            "вас зовут",
            "atyngyz",
            "qalai qaratamyn",
        ]
    )
    unique_markers: list[str] = []
    seen: set[str] = set()
    for marker in markers:
        key = marker.strip()
        if not key or key in seen:
            continue
        seen.add(key)
        unique_markers.append(key)
    return tuple(unique_markers)
