"""Detect content-generation goals: HTML landing, web post, articles, documents (0.2.2.44)."""

from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Literal

from .explicit_text_extractor import extract_explicit_post_text
from .website_resolver import extract_target_site, extract_url_from_prompt, is_web_post_with_site, prompt_specifies_site
from iuve_connect_agents.shared.url_normalizer import extract_normalized_url_from_text

ContentType = Literal[
    "html_landing",
    "social_post",
    "article",
    "email",
    "document",
    "ad_text",
    "product_description",
]

_HTML_LANDING_TOKENS = (
    "лендинг",
    "landing",
    "html",
    "страниц",
    "page",
    "веб-страниц",
    "web page",
    "сайт в html",
)
_CREATE_TOKENS = (
    "создай",
    "создать",
    "create ",
    "make ",
    "сделай",
    "напиши",
    "написать",
    "write ",
    "помести",
    "положи",
    "сформир",
    "формируй",
)
_FORM_DOCUMENT_TOKENS = (
    "сформир",
    "формируй",
    "создай документ",
    "create document",
)
_MD_FILE_RE = re.compile(r"\b([A-Za-z0-9_.-]+\.md)\b", re.IGNORECASE)
_POST_TOKENS = (
    "пост",
    "post",
    "опублик",
    "publish",
    "черновик",
    "draft",
)
_ARTICLE_TOKENS = ("стать", "article")
_EMAIL_TOKENS = ("письм", "email", "e-mail")
_AD_TOKENS = ("реклам", "ad text", "объявлен")
_PRODUCT_TOKENS = ("описан", "product description", "товар")
_FOLDER_NAME_RE = re.compile(
    r"(?:папк[уаеи]|folder)\s+(?:с\s+именем\s+|named\s+)?([A-Za-zА-Яа-яЁё0-9_-]+)",
    re.IGNORECASE,
)
_FOLDER_CREATE_RE = re.compile(
    r"\b(?:создай|создать|create)\s+папк[уаеи]\s+([A-Za-zА-Яа-яЁё][A-Za-zА-Яа-яЁё0-9_-]*)",
    re.IGNORECASE,
)
_TOPIC_ABOUT_RE = re.compile(
    r"(?:о|об|про|about)\s+([^,.;]+)",
    re.IGNORECASE,
)
_TOPIC_ENGLISH_RE = re.compile(
    r"\b(?:на\s+английск\w*|in\s+english|english\s+language)\b",
    re.IGNORECASE,
)
_TOPIC_SERVICE_RE = re.compile(
    r"(?:"
    r"(?:о|об|про|about)\s+(?:сервисе\s+|service\s+)?([^,.;]+?)"
    r"(?:\s+(?:www\.|https?://)|$)"
    r"|"
    r"(?:пост|post)\s+(?:на\s+английск\w*\s+)?(?:о|об|про|about)\s+([^,.;]+)"
    r")",
    re.IGNORECASE,
)
_LITERAL_WRITE_COLON_RE = re.compile(
    r"(?:напиш\w*|write)\s*[:—–-]\s*"
    r"(?:[«\"']([^»\"']+)[»\"']|([^,;]+?))"
    r"(?:\s+и\s+(?:потом|нажми)|\s+потом\s+|\s+нажми\s+|$)",
    re.IGNORECASE,
)
_LITERAL_WRITE_SHORT_RE = re.compile(
    r"(?:напиш\w*|write)\s+"
    r"(?:[«\"']([^»\"']+)[»\"']|([^,;.]{1,80}))"
    r"(?:\s+и\s+(?:потом|нажми)|\s+потом\s+|\s+нажми\s+|$)",
    re.IGNORECASE,
)
_QUOTED_TEXT_RE = re.compile(r"[«\"']([^»\"']{1,240})[»\"']")
_PATH_CONTAMINATION_RE = re.compile(
    r"(?:/home/[^\s,»\"']+|шага:\s*[^\s,.»\"']+|IuVeWorkspace/[^\s,»\"']+)",
    re.IGNORECASE,
)
_EXPLICIT_PUBLISH_RE = re.compile(
    r"(?:"
    r"нажми\s+(?:кнопку\s+)?опубликовать|"
    r"нажми\s+опубликовать|"
    r"и\s+(?:потом\s+)?нажми\s+(?:кнопку\s+)?опубликовать|"
    r"и\s+опубликовать|"
    r"\bопубликуй\b|"
    r"\bpublish\b|"
    r"\bsend\b|"
    r"\bsubmit\b|"
    r"click\s+(?:the\s+)?publish|"
    r"press\s+publish|"
    r"publish\s+button"
    r")",
    re.IGNORECASE,
)
_HTML_FILE_RE = re.compile(r"\bindex\.html\b", re.IGNORECASE)


@dataclass(frozen=True)
class ContentCreationIntent:
    content_type: ContentType
    topic: str
    folder_name: str = ""
    target_url: str = ""
    output_filename: str = "index.html"
    stop_before_publish: bool = True


def _has_create_verb(lower: str) -> bool:
    return any(token in lower for token in _CREATE_TOKENS)


def extract_landing_folder_name(text: str) -> str:
    raw = str(text or "").strip()
    for pattern in (_FOLDER_CREATE_RE, _FOLDER_NAME_RE):
        match = pattern.search(raw)
        if match:
            name = str(match.group(1) or "").strip()
            if name and name.lower() not in {"на", "в", "in", "the"}:
                return name
    lower = raw.lower()
    if "сайт" in lower and ("папк" in lower or "folder" in lower):
        return "сайт"
    return "сайт"


def sanitize_content_topic(text: str) -> str:
    """Strip workspace path / stale follow-up contamination from topic strings."""
    cleaned = _PATH_CONTAMINATION_RE.sub("", str(text or "")).strip(" .,:;—–-»\"'")
    cleaned = re.sub(r"\s+", " ", cleaned).strip()
    if cleaned.lower().startswith("шага:"):
        cleaned = cleaned.split(":", 1)[-1].strip()
    if _PATH_CONTAMINATION_RE.search(cleaned) or cleaned.lower() in {"сайт", "site", "шага"}:
        return ""
    return cleaned


def extract_literal_post_text(text: str) -> str:
    """Extract verbatim post body — delegates to explicit_text_extractor (0.2.2.48)."""
    explicit = extract_explicit_post_text(text)
    if explicit:
        return explicit

    raw = str(text or "").strip()
    if not raw:
        return ""

    def _accept(candidate: str) -> str:
        cleaned = sanitize_content_topic(str(candidate or "").strip(" .,:;—–-"))
        if not cleaned:
            return ""
        if re.search(r"\b(?:пост|post|стать|article)\b", cleaned, re.IGNORECASE):
            return ""
        return cleaned

    colon_match = _LITERAL_WRITE_COLON_RE.search(raw)
    if colon_match:
        accepted = _accept(str(colon_match.group(1) or colon_match.group(2) or ""))
        if accepted:
            return accepted

    short_match = _LITERAL_WRITE_SHORT_RE.search(raw)
    if short_match:
        accepted = _accept(str(short_match.group(1) or short_match.group(2) or ""))
        if accepted and len(accepted) <= 80:
            return accepted

    quoted = _QUOTED_TEXT_RE.search(raw)
    if quoted and any(token in raw.lower() for token in ("напиш", "write", "пост", "post")):
        accepted = _accept(str(quoted.group(1) or ""))
        if accepted:
            return accepted
    return ""


def is_short_literal_content(text: str) -> bool:
    """True when post body should skip LLM expansion."""
    literal = str(text or "").strip()
    return bool(literal) and len(literal) <= 240


def user_requests_explicit_publish(text: str) -> bool:
    """Detect explicit user instruction to click Publish."""
    raw = str(text or "")
    if not raw.strip():
        return False
    if re.search(r"\b(?:не\s+опублик|без\s+опублик|don't\s+publish|draft\s+only)\b", raw, re.IGNORECASE):
        return False
    return bool(_EXPLICIT_PUBLISH_RE.search(raw))


def extract_content_topic(text: str, *, default: str = "услуги") -> str:
    raw = str(text or "").strip()
    literal = extract_literal_post_text(raw)
    if literal:
        return literal
    match = _TOPIC_ABOUT_RE.search(raw)
    if match:
        topic = sanitize_content_topic(str(match.group(1) or ""))
        if topic and len(topic) > 2 and not _PATH_CONTAMINATION_RE.search(topic):
            return topic
    lower = raw.lower()
    if "аналитик" in lower:
        return "услуги аналитики"
    if "iuve" in lower:
        return "Iuve AI service"
    return sanitize_content_topic(default) or default


def extract_web_post_generation_topic(text: str) -> str:
    """Prompt-first topic for generate_content web posts (not stale goal memory)."""
    raw = str(text or "").strip()
    if not raw:
        return ""

    literal = extract_literal_post_text(raw)
    if literal:
        return literal

    topic = ""
    match = _TOPIC_SERVICE_RE.search(raw)
    if match:
        topic = sanitize_content_topic(str(match.group(1) or match.group(2) or ""))
    if not topic:
        match = _TOPIC_ABOUT_RE.search(raw)
        if match:
            topic = sanitize_content_topic(str(match.group(1) or ""))
    if not topic and "iuve" in raw.lower():
        topic = "Iuve AI service"

    parts: list[str] = []
    if topic:
        parts.append(topic)
    if _TOPIC_ENGLISH_RE.search(raw):
        parts.append("in English")
    url = extract_normalized_url_from_text(raw)
    if url:
        parts.append(url)
    combined = sanitize_content_topic(" ".join(parts).strip())
    if combined:
        return combined
    return extract_content_topic(raw, default="новость")


def infer_content_type(text: str) -> ContentType:
    lower = str(text or "").strip().lower()
    if any(token in lower for token in _HTML_LANDING_TOKENS):
        return "html_landing"
    if any(token in lower for token in _EMAIL_TOKENS):
        return "email"
    if any(token in lower for token in _AD_TOKENS):
        return "ad_text"
    if any(token in lower for token in _PRODUCT_TOKENS):
        return "product_description"
    if any(token in lower for token in _ARTICLE_TOKENS):
        return "article"
    if any(token in lower for token in _POST_TOKENS):
        return "social_post"
    return "document"


def is_html_landing_intent(text: str) -> bool:
    lower = str(text or "").strip().lower()
    if not lower or not _has_create_verb(lower):
        return False
    has_html = any(token in lower for token in _HTML_LANDING_TOKENS)
    has_folder = "папк" in lower or "folder" in lower or "сайт" in lower
    if has_html and has_folder:
        return True
    if has_html and ("помест" in lower or "полож" in lower or "код" in lower):
        return True
    if _HTML_FILE_RE.search(lower) and has_folder:
        return True
    return False


def is_web_post_intent(text: str, *, memory_site: str = "") -> bool:
    lower = str(text or "").strip().lower()
    if not lower:
        return False
    try:
        from .compound_intent_resolver import should_defer_web_post_intent

        if should_defer_web_post_intent(text):
            return False
    except ImportError:
        pass
    try:
        from .local_notepad_intent import is_local_notepad_intent

        if is_local_notepad_intent(text):
            return False
    except ImportError:
        pass
    if extract_explicit_post_text(text):
        site = extract_target_site(text, memory_site=memory_site)
        if site:
            return True
    if is_web_post_with_site(text, memory_site=memory_site):
        return True
    url = extract_url_from_prompt(text) or extract_normalized_url_from_text(text)
    if not url:
        return False
    has_post = any(token in lower for token in _POST_TOKENS)
    has_create = _has_create_verb(lower) or "напиш" in lower
    if has_post and has_create:
        return True
    if has_post and ("сайт" in lower or "site" in lower or "где" in lower):
        return True
    return False


def is_generate_only_intent(text: str) -> bool:
    """Generate text/content without file or browser steps."""
    lower = str(text or "").strip().lower()
    if not lower:
        return False
    if is_html_landing_intent(text) or is_web_post_intent(text):
        return False
    if extract_url_from_prompt(text) or prompt_specifies_site(text):
        return False
    has_write = any(token in lower for token in ("напиш", "write", "сгенерир", "generate", "составь"))
    has_type = any(
        token in lower
        for token in (*_ARTICLE_TOKENS, *_EMAIL_TOKENS, *_AD_TOKENS, *_PRODUCT_TOKENS, "текст", "content")
    )
    return has_write and has_type


def extract_markdown_filename(text: str, *, default: str = "document.md") -> str:
    match = _MD_FILE_RE.search(str(text or ""))
    if match:
        return str(match.group(1) or "").strip() or default
    return default


def is_document_generation_intent(text: str) -> bool:
    """Generate a workspace document (.md etc.) — not vision/screen capture."""
    raw = str(text or "").strip()
    if not raw:
        return False
    if is_html_landing_intent(raw) or is_web_post_intent(raw):
        return False
    lower = raw.lower()
    has_md = bool(_MD_FILE_RE.search(raw))
    has_form = any(token in lower for token in _FORM_DOCUMENT_TOKENS)
    has_create_doc = "создай документ" in lower or "create document" in lower
    if has_create_doc:
        return True
    if has_md and (has_form or _has_create_verb(lower)):
        return True
    if has_form and ("документ" in lower or "document" in lower or has_md):
        return True
    return False


def detect_content_creation_intent(text: str) -> ContentCreationIntent | None:
    raw = str(text or "").strip()
    if not raw:
        return None
    if is_document_generation_intent(raw):
        filename = extract_markdown_filename(raw)
        topic = extract_content_topic(raw, default=filename.replace(".md", "").replace("_", " "))
        return ContentCreationIntent(
            content_type="document",
            topic=topic,
            output_filename=filename,
        )
    if is_html_landing_intent(raw):
        folder = extract_landing_folder_name(raw)
        topic = extract_content_topic(raw, default="услуги аналитики")
        filename = "index.html"
        if _HTML_FILE_RE.search(raw):
            filename = "index.html"
        return ContentCreationIntent(
            content_type="html_landing",
            topic=topic,
            folder_name=folder,
            output_filename=filename,
        )
    if is_web_post_intent(raw):
        site = extract_target_site(raw)
        url = site.url if site else (extract_url_from_prompt(raw) or "")
        topic = extract_content_topic(raw, default="новость")
        stop = "опублик" not in raw.lower() or "не опублик" in raw.lower()
        return ContentCreationIntent(
            content_type="social_post",
            topic=topic,
            target_url=url,
            stop_before_publish=stop,
        )
    if is_generate_only_intent(raw):
        return ContentCreationIntent(
            content_type=infer_content_type(raw),
            topic=extract_content_topic(raw),
        )
    return None
