from __future__ import annotations

import os
import re
from typing import Any


_IDENTITY_PATTERNS: tuple[str, ...] = (
    "кто ты",
    "кто вы",
    "ты кто",
    "вы кто",
    "как тебя зовут",
    "как вас зовут",
    "твое имя",
    "твоё имя",
    "ваше имя",
    "представься",
    "скажи кто ты",
    "скажи мне кто ты",
    "робот ты",
    "ты робот",
    "ты бот",
    "ты ии",
    "ты искусственный интеллект",
    "ты оператор",
    "вы оператор",
    "who are you",
    "what is your name",
    "сен кімсің",
    "сіз кімсіз",
    "атың кім",
    "атыңыз кім",
)


def _config_value(config: Any | None, name: str, default: str) -> str:
    if config is None:
        return default
    value = getattr(config, name, None)
    if value is None and isinstance(config, dict):
        value = config.get(name)
    normalized = str(value or "").strip()
    return normalized or default


def _agent_name(config: Any | None) -> str:
    return _config_value(config, "agent_name", "Айнур")


def _company_name(config: Any | None) -> str:
    return _config_value(config, "company_name", "DigiOps")


def _format_config_text(text: str, config: Any | None) -> str:
    return (
        str(text or "")
        .replace("{agent_name}", _agent_name(config))
        .replace("{company_name}", _company_name(config))
        .strip()
    )


def is_identity_request(text: str) -> bool:
    normalized = str(text or "").strip().lower().replace("ё", "е")
    if not normalized:
        return False
    normalized = re.sub(r"[^\w\sәіңғүұқөһ-]+", " ", normalized, flags=re.UNICODE)
    compact = " ".join(normalized.split())
    return any(pattern.replace("ё", "е") in compact for pattern in _IDENTITY_PATTERNS)


def customer_persona_mode() -> str:
    return str(os.getenv("AI_CUSTOMER_PERSONA_MODE", "operator_humanlike") or "operator_humanlike").strip().lower()


def disclosure_mode() -> str:
    return str(os.getenv("AI_DISCLOSURE_MODE", "hidden") or "hidden").strip().lower()


def voice_policy_mode() -> str:
    return str(os.getenv("AI_VOICE_POLICY_MODE", "llm_guarded") or "llm_guarded").strip().lower()


def disclosure_hidden() -> bool:
    return disclosure_mode() == "hidden"


def voice_disclosure_prefix(language: str) -> str:
    if disclosure_hidden():
        return ""
    if str(language or "").strip().lower() == "kz":
        return "Men kompaniya atynan jauap berip turmyn. "
    return "Отвечаю от имени линии поддержки компании. "


def identity_reply(language: str, config: Any | None = None) -> str:
    if str(language or "").strip().lower() == "kz":
        default = f"Мен {_agent_name(config)}мын, {_company_name(config)} байланыс орталығының операторымын. Қалай көмектесе аламын?"
        return _format_config_text(_config_value(config, "identity_reply_kz", default), config)
    default = f"Я {_agent_name(config)}, оператор контакт-центра {_company_name(config)}. Чем могу помочь?"
    return _format_config_text(_config_value(config, "identity_reply_ru", default), config)


def voice_greeting(language: str, config: Any | None = None) -> str:
    if str(language or "").strip().lower() == "kz":
        default = f"Сәлеметсіз бе. Мен {_agent_name(config)}мын. Қалай көмектесе аламын?"
        return _format_config_text(_config_value(config, "voice_greeting_kz", default), config)
    default = f"Здравствуйте. Я {_agent_name(config)}. Подскажите, пожалуйста, чем помочь. (тест деплоя)"
    return _format_config_text(_config_value(config, "voice_greeting_ru", default), config)


def voice_handoff_reply(language: str) -> str:
    if str(language or "").strip().lower() == "kz":
        return "Бір сәт, сізді операторға қосамын."
    return "Секунду, соединяю вас с оператором."


def text_resolution_reply(language: str) -> str:
    if str(language or "").strip().lower() == "kz":
        return "Жақсы, белгілеп қоямын. Қажет болса, осы жерден қайта жаза аласыз."
    return "Хорошо, отмечу это. Если понадобится, можно продолжить здесь."


def human_fallback_reply(language: str, *, is_greeting: bool = False) -> str:
    if str(language or "").strip().lower() == "kz":
        if is_greeting:
            return "Сәлеметсіз бе. Сұрағыңызды жазыңыз не айтыңыз, көмектесуге тырысамын."
        return "Түсіндім. Нақтырақ айтып жіберсеңіз, бірден жалғастырамын."
    if is_greeting:
        return "Здравствуйте. Напишите или коротко расскажите, чем помочь."
    return "Понял вас. Уточните, пожалуйста, детальнее, и я сразу продолжу."


def operator_system_prompt(*, language: str, channel_label: str, is_voice: bool, config: Any | None = None) -> str:
    preferred_language = "Kazakh" if str(language or "").strip().lower() == "kz" else "Russian"
    delivery_hint = (
        "The reply will be spoken aloud over a phone call, so keep it concise, natural, and easy to listen to. "
        "Prefer one or two short sentences and at most one clarifying question. "
        "The text-to-speech engine reads exactly what you write, digit by digit, with no number formatting of its own, "
        "so never output bare digits for phone numbers, hotline numbers, or dates — always spell them out in words "
        "the way a person would actually say them aloud in natural spoken Russian/Kazakh. "
        "Short hotline or service numbers (e.g. 1414, 109) must be spelled out the way people say them as a code, "
        "grouped and read naturally (\"1414\" as \"четырнадцать четырнадцать\", not \"тысяча четыреста четырнадцать\"). "
        "Calendar dates must use the correct spoken grammatical case (\"25 числа\" as \"двадцать пятого числа\", "
        "not \"двадцать пять число\"; \"14 марта\" as \"четырнадцатого марта\")."
        if is_voice
        else "The reply should read like a concise message from a live first-line operator."
    )
    default_base_prompt = (
        f"Ты {_agent_name(config)}, единый оператор контакт-центра {_company_name(config)} для звонков, "
        "Telegram и других каналов. Всегда сохраняй одну и ту же личность. Когда говоришь о себе, "
        "используй женский род. Не завершай диалог самостоятельно."
    )
    base_prompt = _format_config_text(_config_value(config, "base_system_prompt", default_base_prompt), config)
    identity_instruction = (
        f"If the customer asks who you are or what your name is, answer as {_agent_name(config)}. "
        f"For {preferred_language}, use this identity reply when appropriate: "
        f"{identity_reply(language, config)}"
    )
    return (
        f"{base_prompt}\n\n"
        f"You are a first-line company operator handling customer conversations in {channel_label}. "
        f"Reply in {preferred_language}. Speak naturally, warmly, and confidently like a human operator. "
        f"Your name is {_agent_name(config)} and you must not introduce yourself with any other name. "
        f"{identity_instruction} "
        "Do not mention a knowledge base, snippets, internal notes, policies, or hidden tools. "
        "Use the provided business context, conversation history, and KB snippets only as factual sources. "
        "Paraphrase them naturally instead of quoting them verbatim. "
        "Never invent order statuses, tariffs, discounts, deadlines, addresses, availability, approvals, or actions "
        "that are not supported by context. If the available facts are insufficient, ask one short clarifying question. "
        "If the customer explicitly asks for a live operator, if the request is sensitive, or if the case is blocked, "
        "set needs_handoff=true. "
        f"{delivery_hint} "
        "Return only a JSON object with keys: language, intent, reply_text, extracted_name, confidence, needs_handoff, "
        "handoff_reason, case_action, kb_refs. case_action must be one of none, close, escalate, keep_open."
    )
