"""
Hard Pattern Detection — Bắt các mẫu hỏi CỨNG đòi hỏi tham chiếu.

Các pattern phổ biến:
  • "rẻ hơn", "giá rẻ hơn"         → so sánh giá
  • "đắt hơn", "cao hơn"           → so sánh giá
  • "tương tự", "giống như"         → lấy đặc điểm SP tham chiếu
  • "như cái trước", "cái kia"      → refer đến SP đã nói
  • "còn size...", "size còn không" → check size variant
  • "còn màu...", "màu gì còn"     → check color variant
  • "còn hàng không"               → check stock
"""

import re
from typing import TypedDict, Optional, Any
from dataclasses import dataclass


@dataclass
class PatternMatch:
    """Kết quả pattern detection."""
    pattern_type: str          # "cheaper_than", "similar_to", "check_size", ...
    reference_sku: Optional[str] = None
    reference_product_line: Optional[str] = None
    reference_price: Optional[float] = None
    reference_color: Optional[str] = None
    reference_size: Optional[str] = None

    # Target criteria (nếu có)
    target_price_max: Optional[float] = None
    target_price_min: Optional[float] = None
    target_size: Optional[str] = None
    target_color: Optional[str] = None

    confidence: float = 0.0   # 0.0 - 1.0
    raw_match: str = ""       # Văn bản khớp


class HardPatternDetector:
    """Detect và trích xuất reference từ query user."""

    # ═══════════════════════════════════════════════════════════════
    # PATTERN REGEXES
    # ═══════════════════════════════════════════════════════════════

    # 1. GIÁ RẺ HƠN
    CHEAPER_PATTERNS = [
        r"(?:rẻ|giá)\s+(?:hơn|thấp hơn|xuống hơn)",
        r"có\s+(?:cái)?\s+(?:nào)?\s+(?:rẻ|giá)\s+(?:hơn|thấp hơn)",
        r"tìm\s+(?:cái)?\s+(?:rẻ|giá)\s+(?:hơn|thấp hơn)",
        r"(?:rẻ|giá)\s+(?:hơn|thấp hơn)\s+(?:cái|chiếc)?",
        r"có.*rẻ.*hơn",
    ]

    # 2. GIÁ ĐẮT HƠN
    EXPENSIVE_PATTERNS = [
        r"(?:đắt|giá)\s+(?:hơn|cao hơn)",
        r"có\s+(?:cái)?\s+(?:nào)?\s+(?:đắt|giá)\s+(?:hơn|cao hơn)",
        r"(?:đắt|giá)\s+(?:hơn|cao hơn)\s+(?:cái|chiếc)?",
        r"có.*đắt.*hơn",
    ]

    # 3. TƯƠNG TỰ / GIỐNG NHƯ
    SIMILAR_PATTERNS = [
        r"(?:giống|tương tự|như|cùng)\s+(?:như|với)?\s+(?:cái|chiếc)?\s*(?:đó|trước|ban\s*nãy|cạnh|là)?",
        r"còn\s+(?:cái)?\s+(?:nào|còn)?\s+(?:tương tự|giống)\s+(?:như|với)?",
        r"(?:có|tìm)\s+(?:cái)?\s+(?:nào|còn)?\s+(?:giống|tương tự)",
        r"giống\s+(?:như)?\s+(?:cái)?(?:đó|trước|kia)",
    ]

    # 4. CHECK SIZE (còn size?, size còn không, có size X không)
    SIZE_CHECK_PATTERNS = [
        r"(?:còn|có)\s+size\s+([A-Z0-9]+)",
        r"size\s+([A-Z0-9]+)\s+(?:còn|có)",
        r"(?:còn|có)\s+(?:size\s+)?([A-Z0-9]+)\s+(?:không|ko|kh)",
    ]

    # 5. CHECK MÀU (còn màu?, màu gì còn, có màu X không)
    COLOR_CHECK_PATTERNS = [
        r"(?:còn|có)\s+(?:màu\s+)?(\w+)\s+(?:còn|không|ko)",
        r"màu\s+(\w+)\s+(?:còn|có)",
        r"(?:màu\s+)?(\w+)\s+(?:còn|có)\s+(?:không|ko)",
    ]

    # 6. CHECK TỒN KHO (còn hàng không, còn ko, có hàng ko)
    STOCK_CHECK_PATTERNS = [
        r"(?:còn|có)\s+(?:hàng|kho)\s+(?:không|ko|kh)",
        r"(?:hàng|kho)\s+(?:còn|có)\s+(?:không|ko|kh)",
    ]

    # 7. REFERENCE SKU (nhắc trực tiếp mã: 8TP25A002, 5TS25S021-SR079)
    SKU_PATTERN = r"\b([A-Z0-9]{4,}-[A-Z0-9]{3,}(?:-[A-Z0-9]{3,})?)\b"

    # 8. REFERENCE BY POSITION (cái trước, cái kia, cái đầu tiên)
    POSITION_REFERENCE = {
        "trước": 0,      # SP trước đó (index -1)
        "đầu": 0,        # SP đầu tiên trong list
        "đầu tiên": 0,
        "kia": -1,       # SP cuối/cuối cùng (gần nhất)
        "cuối": -1,
        "cuối cùng": -1,
        "sau": -1,
    }

    def detect(self, query: str, context_products: list[dict[str, Any]] = None) -> PatternMatch:
        """
        Detect pattern trong query user.

        Args:
            query: Câu hỏi của user (raw text)
            context_products: List sản phẩm đã được giới thiệu trong conversation
                             [{"sku": "...", "product_line_vn": "...", "sale_price": ...}, ...]

        Returns:
            PatternMatch với đầy đủ thông tin pattern.
        """
        query_lower = query.lower().strip()
        match = PatternMatch(pattern_type="unknown")

        # 1. Detect CHEAPER THAN
        if self._match_any_pattern(query_lower, self.CHEAPER_PATTERNS):
            match.pattern_type = "cheaper_than"
            match.confidence = 0.9
            match = self._extract_reference_info(query, context_products, match)
            if match.reference_price:
                match.target_price_max = match.reference_price * 0.95  # Rẻ hơn 5%

        # 2. Detect EXPENSIVE THAN
        elif self._match_any_pattern(query_lower, self.EXPENSIVE_PATTERNS):
            match.pattern_type = "more_expensive_than"
            match.confidence = 0.9
            match = self._extract_reference_info(query, context_products, match)
            if match.reference_price:
                match.target_price_min = match.reference_price * 1.05  # Đắt hơn 5%

        # 3. Detect SIMILAR TO
        elif self._match_any_pattern(query_lower, self.SIMILAR_PATTERNS):
            match.pattern_type = "similar_to"
            match.confidence = 0.8
            match = self._extract_reference_info(query, context_products, match)

        # 4. Detect SIZE CHECK
        elif size_match := re.search(r"(?:còn|có)\s+size\s+([A-Z0-9]+)", query_lower):
            match.pattern_type = "check_size"
            match.confidence = 0.95
            match.target_size = size_match.group(1).upper()
            match = self._extract_reference_info(query, context_products, match)

        # 5. Detect COLOR CHECK
        elif color_match := re.search(r"(?:màu\s+)?(\w+)\s+(?:còn|có)", query_lower):
            # Filter out common stop words
            color = color_match.group(1)
            if color not in ["có", "còn", "ko", "không", "màu"]:
                match.pattern_type = "check_color"
                match.confidence = 0.9
                match.target_color = color
                match = self._extract_reference_info(query, context_products, match)

        # 6. Detect STOCK CHECK
        elif self._match_any_pattern(query_lower, self.STOCK_CHECK_PATTERNS):
            match.pattern_type = "check_stock"
            match.confidence = 0.9
            match = self._extract_reference_info(query, context_products, match)

        # 7. Detect direct SKU reference
        elif sku_match := re.search(self.SKU_PATTERN, query):
            match.pattern_type = "direct_sku"
            match.confidence = 1.0
            match.reference_sku = sku_match.group(1)

        return match

    def _match_any_pattern(self, text: str, patterns: list[str]) -> bool:
        """Check nếu text match bất kỳ pattern nào."""
        return any(re.search(p, text) for p in patterns)

    def _extract_reference_info(self, query: str, context_products: list[dict[str, Any]],
                               current_match: PatternMatch) -> PatternMatch:
        """
        Trích xuất thông tin reference SP từ context.

        Logic:
        1. Nếu query có SKU cụ thể → tìm trực tiếp
        2. Nếu query có tên product_line ("áo polo kia") → filter context
        3. Nếu query có từ vị trí ("cái trước", "cái kia") → lấy theo index
        4. Default: lấy SP gần nhất (cuối context)
        """
        if not context_products:
            return current_match

        query_lower = query.lower()

        # --- Case 1: Direct SKU trong query ---
        sku_match = re.search(self.SKU_PATTERN, query)
        if sku_match:
            sku = sku_match.group(1)
            for p in context_products:
                if p.get("sku") == sku or p.get("magento_ref_code") == sku:
                    self._populate_match_from_product(p, current_match)
                    return current_match

        # --- Case 2: Reference by position ---
        for pos_word, idx_offset in self.POSITION_REFERENCE.items():
            if pos_word in query_lower:
                idx = idx_offset if idx_offset >= 0 else len(context_products) + idx_offset
                if 0 <= idx < len(context_products):
                    self._populate_match_from_product(context_products[idx], current_match)
                    return current_match

        # --- Case 3: Reference by product_line ---
        # Từ khóa product_line phổ biến
        product_keywords = [
            "áo phông", "áo polo", "áo sơ mi", "áo khoác", "áo len",
            "quần jean", "quần khaki", "quần âu", "quần soóc", "váy", "chân váy",
            "bộ", "đồ lót", "quần lót", "áo dài", "blazer", "cardigan"
        ]
        for kw in product_keywords:
            if kw in query_lower:
                # Tìm SP trong context có product_line chứa kw
                for p in reversed(context_products):  # Ưu tiên SP gần nhất
                    if kw in p.get("product_line_vn", "").lower():
                        self._populate_match_from_product(p, current_match)
                        return current_match

        # --- Case 4: Default → SP gần nhất (last in context) ---
        if context_products:
            self._populate_match_from_product(context_products[-1], current_match)

        return current_match

    def _populate_match_from_product(self, product: dict[str, Any], match: PatternMatch) -> None:
        """Fill match info từ product dict."""
        match.reference_sku = product.get("sku") or product.get("magento_ref_code") or product.get("internal_ref_code")
        match.reference_product_line = product.get("product_line_vn") or product.get("product_line")
        match.reference_price = float(product.get("sale_price") or product.get("price") or 0)
        match.reference_color = product.get("master_color") or product.get("color")
        match.reference_size = None  # Size thường không có trong product summary
