"""
farm_state.py — v4 Farm State Layer.

Сесійний оперативний контекст господарства.
Ізольований від doc_mode, memory_manager, crewai.

Публічні функції:
  detect_farm_state_updates(text) -> dict
  update_farm_state(session, updates, now_ts) -> None
  build_farm_state_prefix(session) -> str
"""
from __future__ import annotations

import re
import time

# ── Культури ──────────────────────────────────────────────────────────────────
_CROP_RE = re.compile(
    r"\b(кукурудз[аиіує]|кукурудзою|кукурудзі"
    r"|пшениц[яіює]|пшениця"
    r"|соняшник[аиуів]?|соняшник"
    r"|ріпак[аиуів]?|ріпак"
    r"|со[яіює]|соя"
    r"|ячмінь|ячмен[юі]"
    r"|горох[аиуів]?|горох"
    r"|буряк[аиуів]?|буряк"
    r"|картопл[яіі]|картопля"
    r"|льон[аиуів]?|льон)\b",
    re.IGNORECASE | re.UNICODE,
)

# Нормалізація до канонічної форми
_CROP_CANONICAL: dict[str, str] = {
    # кукурудза (всі відмінки)
    "кукурудза": "кукурудза", "кукурудзи": "кукурудза",
    "кукурудзі": "кукурудза", "кукурудзу": "кукурудза",
    "кукурудзою": "кукурудза", "кукурудзє": "кукурудза",
    # пшениця
    "пшениця": "пшениця", "пшениці": "пшениця",
    "пшеницею": "пшениця", "пшеницю": "пшениця", "пшеницю": "пшениця",
    # соняшник
    "соняшник": "соняшник", "соняшника": "соняшник",
    "соняшнику": "соняшник", "соняшників": "соняшник",
    # ріпак
    "ріпак": "ріпак", "ріпака": "ріпак", "ріпаку": "ріпак", "ріпаків": "ріпак",
    # соя
    "соя": "соя", "сої": "соя", "сою": "соя", "соєю": "соя",
    # ячмінь
    "ячмінь": "ячмінь", "ячменю": "ячмінь", "ячмені": "ячмінь",
    # горох
    "горох": "горох", "гороху": "горох", "гороха": "горох", "горохів": "горох",
    # буряк
    "буряк": "буряк", "буряка": "буряк", "буряку": "буряк", "буряків": "буряк",
    # картопля
    "картопля": "картопля", "картоплі": "картопля",
    # льон
    "льон": "льон", "льону": "льон", "льона": "льон", "льонів": "льон",
}

# ── Стадії росту ──────────────────────────────────────────────────────────────
# Спочатку шукаємо числові коди (vN, rN, BBCH) — вони точніші.
# Потім словесні фази. "стадія" — артикль, ігноруємо.
_STAGE_NUMERIC_RE = re.compile(
    r"\b(v\d{1,2}|vt|r\d|bbch\s*\d+|\d+-\d+\s+листк[иів]?)\b",
    re.IGNORECASE | re.UNICODE,
)
_STAGE_WORD_RE = re.compile(
    r"\b(сходи|кущення|викидання\s+волоті|цвітіння|наливання\s+зерна"
    r"|дозрівання|збирання|посів|кінець\s+вегетації)\b",
    re.IGNORECASE | re.UNICODE,
)
# Єдиний RE для API-сумісності (використовуємо numeric першим)
_STAGE_RE = _STAGE_NUMERIC_RE  # backward compat alias

# ── Проблеми / симптоми ───────────────────────────────────────────────────────
_ISSUE_RE = re.compile(
    r"\b(жовтизна|жовтіння|хлороз|некроз|плям[иа]|плями"
    r"|дефіцит\s+\w+|нестача\s+\w+"
    r"|шкідник[иів]?|хвороб[аи]|гриб[иок]|гниль"
    r"|бур['']?ян[иів]?|бур['']яни"
    r"|попелиц[яі]|тля|кліщ[іи]|трипс[иів]?"
    r"|фузаріоз|іржа|борошниста\s+роса|септоріоз)\b",
    re.IGNORECASE | re.UNICODE,
)

# ── Ризики ────────────────────────────────────────────────────────────────────
_RISK_RE = re.compile(
    r"\b(посуха|посухи|засух[аи]"
    r"|заморозок|заморозки|приморозок"
    r"|спека|перегрів"
    r"|надлишок\s+вологи|затоплення|підтоплення"
    r"|град|вітер|буря"
    r"|брак\s+опадів|немає\s+дощу)\b",
    re.IGNORECASE | re.UNICODE,
)

# Максимальний TTL farm_state в сесії (30 хв — синхронізовано з SESSION_TTL)
FARM_STATE_TTL = 1800.0


def detect_farm_state_updates(text: str) -> dict:
    """
    Rule-based витяг оновлень farm_state з тексту.

    Повертає тільки знайдені поля:
      current_crop: str
      growth_stage: str
      recent_issue: str
      risk_flags: list[str]

    Fail-safe: будь-яка помилка → {}.
    """
    try:
        t = text.strip()
        updates: dict = {}

        crop_m = _CROP_RE.search(t)
        if crop_m:
            raw = crop_m.group(0).lower()
            updates["current_crop"] = _CROP_CANONICAL.get(raw, raw)

        # Числовий код (V6, R2, BBCH30) пріоритетніший за словесну фазу
        stage_m = _STAGE_NUMERIC_RE.search(t) or _STAGE_WORD_RE.search(t)
        if stage_m:
            updates["growth_stage"] = stage_m.group(0).strip().upper()

        issue_m = _ISSUE_RE.search(t)
        if issue_m:
            updates["recent_issue"] = issue_m.group(0).strip().lower()

        risk_matches = _RISK_RE.findall(t)
        if risk_matches:
            updates["risk_flags"] = [r.lower() for r in risk_matches]

        return updates
    except Exception:
        return {}


def update_farm_state(session: dict, updates: dict, now_ts: float | None = None) -> None:
    """
    Оновлює session["farm_state"] знайденими полями.
    Створює dict якщо відсутній.
    Встановлює last_update_ts.
    Fail-safe: не кидає назовні.
    """
    try:
        if not updates:
            return
        now = now_ts if now_ts is not None else time.time()
        fs: dict = session.get("farm_state") or {}

        if "current_crop" in updates:
            fs["current_crop"] = updates["current_crop"]

        if "growth_stage" in updates:
            fs["growth_stage"] = updates["growth_stage"]

        if "recent_issue" in updates:
            fs["recent_issue"] = updates["recent_issue"]

        if "risk_flags" in updates:
            existing_risks: list = fs.get("risk_flags") or []
            new_risks = updates["risk_flags"]
            # merge + dedup, max 5
            merged = list(dict.fromkeys(existing_risks + new_risks))[:5]
            fs["risk_flags"] = merged

        fs["last_update_ts"] = now
        session["farm_state"] = fs
    except Exception:
        pass


def build_farm_state_prefix(session: dict, now_ts: float | None = None) -> str:
    """
    Повертає короткий структурований префікс якщо є farm_state.
    Максимум 5 рядків.
    Порожній рядок якщо нема current_crop або state протух.
    Fail-safe: будь-яка помилка → "".
    """
    try:
        fs: dict = session.get("farm_state") or {}
        if not fs.get("current_crop"):
            return ""

        # TTL check
        last_ts = float(fs.get("last_update_ts") or 0.0)
        now = now_ts if now_ts is not None else time.time()
        if (now - last_ts) > FARM_STATE_TTL:
            return ""

        lines = ["[Контекст господарства]"]
        lines.append(f"Культура: {fs['current_crop']}")

        if fs.get("growth_stage"):
            lines.append(f"Стадія: {fs['growth_stage']}")

        if fs.get("recent_issue"):
            lines.append(f"Проблема: {fs['recent_issue']}")

        risks = fs.get("risk_flags") or []
        if risks:
            lines.append(f"Ризики: {', '.join(risks[:3])}")

        return "\n".join(lines)
    except Exception:
        return ""
