"""identidade.py — quem é o assistente e quem é a pessoa.

O assistente se chama "Primo" até a pessoa dar outro nome ("seu nome agora é
Luna", ou `primocode voz nome Luna`). O nome NÃO ativa nada: o modo voz só abre no clique. Fica em
~/.primocode/voz.json, junto com o nome da pessoa e as chaves de luz e som.

Personalidade: curta, natural, humor leve. Cumprimenta pela hora, lembra o nome
da pessoa, e varia a frase (nunca a mesma resposta robótica duas vezes seguidas).
"""
from __future__ import annotations

import json
import os
import random
import re
from pathlib import Path
from typing import Optional

PADRAO = {"nome": "Primo", "pessoa": "", "luz": True, "sons": True, "robo": "spline", "voz": "francisca", "tts": "edge"}


def arquivo() -> Path:
    return Path(os.environ.get("PRIMOCODE_VOZ_CONFIG") or (Path.home() / ".primocode" / "voz.json"))


def ler() -> dict:
    try:
        d = json.loads(arquivo().read_text("utf-8"))
        cfg = {**PADRAO, **{k: d[k] for k in PADRAO if k in d}}
        if cfg["robo"] not in ("spline", "expressive"):   # valor antigo ou torto: o padrão
            cfg["robo"] = PADRAO["robo"]
        return cfg
    except Exception:
        return dict(PADRAO)


def salvar(**campos) -> dict:
    cfg = {**ler(), **campos}
    a = arquivo()
    a.parent.mkdir(parents=True, exist_ok=True)
    a.write_text(json.dumps(cfg, ensure_ascii=False, indent=2), "utf-8")
    return cfg


def _nome_valido(x: str) -> Optional[str]:
    x = re.sub(r"[^\wÀ-ÿ \-]", "", x or "").strip()
    palavras = x.split()
    if not 1 <= len(palavras) <= 2 or len(x) > 20 or len(x) < 2:
        return None
    return " ".join(w[:1].upper() + w[1:] for w in palavras)


def aprender(texto: str) -> Optional[dict]:
    """"seu nome agora é Luna" / "pode me chamar de Joel" → o que gravar (ou None)."""
    t = " ".join(str(texto or "").split()).strip(" .!?,")
    m = re.search(r"(?:seu nome (?:agora )?é|vou te chamar de|(?:a partir de agora )?você se chama|te chamo de)\s+(.+)$", t, re.I)
    if m and _nome_valido(m.group(1)):
        return {"nome": _nome_valido(m.group(1))}
    m = re.search(r"(?:pode me chamar de|meu nome é|me chama de|eu sou o|eu sou a)\s+(.+)$", t, re.I)
    if m and _nome_valido(m.group(1)):
        return {"pessoa": _nome_valido(m.group(1))}
    return None


def periodo(hora: int) -> str:
    return "Bom dia" if 5 <= hora < 12 else "Boa tarde" if 12 <= hora < 18 else "Boa noite"


def saudacao(hora: int, pessoa: str = "", nome: str = "Primo", rnd: Optional[random.Random] = None) -> str:
    r = rnd or random
    p = f", {pessoa}" if pessoa else ""
    if hora < 5:
        opcoes = [f"Ainda de pé{p}? Tô aqui.", f"Madrugada, hein{p}. Bora, mas sem exagero."]
    else:
        opcoes = [f"{periodo(hora)}{p}! {nome} na área.", f"{periodo(hora)}{p}. Pode falar.",
                  f"{periodo(hora)}{p}, tô ouvindo."]
    return r.choice(opcoes)


FEITO = ["Feito.", "Pronto.", "Tá na mão.", "Resolvido."]
ERRO = ["Opa, deu ruim. Olha o painel.", "Travei aqui. O detalhe tá no painel."]
NAO_ENTENDI = ["Não peguei essa. Repete?", "Hã? Fala de novo."]


def variar(opcoes, ultimo: str = "", rnd: Optional[random.Random] = None) -> str:
    r = rnd or random
    cand = [o for o in opcoes if o != ultimo] or list(opcoes)
    return r.choice(cand)
