"""Parser for plain text notes."""

import re
from typing import List
from ..models import FailureRecord

_ERROR_PATTERNS = re.compile(
    r"\b(AttributeError|NameError|TypeError|ValueError|ImportError|"
    r"ModuleNotFoundError|TimeoutError|RuntimeError|AssertionError|"
    r"KeyError|IndexError|FileNotFoundError|PermissionError|"
    r"NotImplementedError|OSError|IOError|RecursionError)\b"
)

_PROBLEM_PHRASES = [
    (re.compile(r"\b(None|null|NoneType)\b", re.IGNORECASE), "null-check"),
    (re.compile(r"\b(import|module|package|dependency)\b", re.IGNORECASE), "imports"),
    (re.compile(r"\b(timeout|too slow|hung|hang)\b", re.IGNORECASE), "timeout"),
    (re.compile(r"\b(permission|access denied|forbidden)\b", re.IGNORECASE), "permissions"),
    (re.compile(r"\b(wrong variable|wrong name|typo|misspelled)\b", re.IGNORECASE), "naming"),
    (re.compile(r"\b(forgot|missing|didn.t add|didn.t check)\b", re.IGNORECASE), "oversight"),
    (re.compile(r"\b(file not found|path|directory)\b", re.IGNORECASE), "file-handling"),
    (re.compile(r"\b(type error|wrong type|cast|convert)\b", re.IGNORECASE), "types"),
    (re.compile(r"\b(assert|assertion|expected|got)\b", re.IGNORECASE), "assertions"),
]


class NotesParser:
    """Parse plain text notes into FailureRecord objects."""

    def parse(self, text: str) -> List[FailureRecord]:
        """Parse plain text and return failure records."""
        if not text or not text.strip():
            return []

        records = []

        # Check for explicit exception types
        for m in _ERROR_PATTERNS.finditer(text):
            error_type = m.group(1)
            # Get surrounding context (50 chars each side)
            start = max(0, m.start() - 50)
            end = min(len(text), m.end() + 100)
            context = text[start:end].strip()
            records.append(
                FailureRecord(
                    type=error_type,
                    message=context,
                    context=text[:500],
                    raw=text,
                )
            )

        # If no explicit errors found, classify by problem phrases
        if not records:
            found_categories = set()
            for pattern, category in _PROBLEM_PHRASES:
                if pattern.search(text) and category not in found_categories:
                    found_categories.add(category)
                    records.append(
                        FailureRecord(
                            type=f"note-{category}",
                            message=text[:200].strip(),
                            context=text[:500],
                            raw=text,
                        )
                    )

        # Always add a generic note record if nothing matched
        if not records:
            records.append(
                FailureRecord(
                    type="note-general",
                    message=text[:200].strip(),
                    context=text[:500],
                    raw=text,
                )
            )

        return records
