# retoor <retoor@molodetz.nl>
from __future__ import annotations

import re

from devplacepy.services.jobs.isslop.analysis.signals import (
    AXIS_QUALITY,
    SEVERITY_MEDIUM,
    SEVERITY_WEAK,
    FileContext,
    Signal,
)

VAR_PATTERN = re.compile(r"^\s*var\s+\w+")
MODERN_JS_PATTERN = re.compile(r"\b(?:const|let|=>|class\s+\w+|import\s)")
USE_EFFECT_FETCH_PATTERN = re.compile(r"useEffect\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{[^}]{0,400}\bfetch\s*\(", re.DOTALL)
ANY_TYPE_PATTERN = re.compile(r":\s*any\b")
OPEN_WITHOUT_WITH_PATTERN = re.compile(r"^\s*\w+\s*=\s*open\s*\(")
BROAD_EXCEPT_COUNT_PATTERN = re.compile(r"^\s*except\s+Exception\b", re.MULTILINE)
INLINE_STYLE_PATTERN = re.compile(r"\sstyle\s*=\s*\"")

VAR_THRESHOLD: int = 3
ANY_THRESHOLD: int = 5
OPEN_THRESHOLD: int = 2
BROAD_EXCEPT_THRESHOLD: int = 3
INLINE_STYLE_THRESHOLD: int = 10


def detect_language_tells(context: FileContext) -> list[Signal]:
    findings: list[Signal] = []
    if context.language in ("javascript", "typescript"):
        var_lines = [number for number, line in enumerate(context.lines, start=1) if VAR_PATTERN.match(line)]
        if len(var_lines) >= VAR_THRESHOLD and MODERN_JS_PATTERN.search(context.text):
            findings.append(
                Signal(
                    "LEGACY_VAR",
                    f"{len(var_lines)} var declarations mixed into modern code",
                    SEVERITY_MEDIUM,
                    AXIS_QUALITY,
                    1.0,
                    var_lines[0],
                    context.lines[var_lines[0] - 1].strip(),
                )
            )
        effect_match = USE_EFFECT_FETCH_PATTERN.search(context.text)
        if effect_match:
            line = context.text.count("\n", 0, effect_match.start()) + 1
            findings.append(
                Signal(
                    "USEEFFECT_FETCH",
                    "Data fetching inside useEffect without caching or retry",
                    SEVERITY_MEDIUM,
                    AXIS_QUALITY,
                    2.0,
                    line,
                    effect_match.group(0)[:120],
                )
            )
    if context.language == "typescript":
        any_hits = ANY_TYPE_PATTERN.findall(context.text)
        if len(any_hits) >= ANY_THRESHOLD:
            findings.append(
                Signal("ANY_TYPES", f"{len(any_hits)} explicit any types", SEVERITY_MEDIUM, AXIS_QUALITY, 1.0, 1, f"{len(any_hits)} occurrences of : any")
            )
    if context.language == "python":
        open_lines = [number for number, line in enumerate(context.lines, start=1) if OPEN_WITHOUT_WITH_PATTERN.match(line)]
        if len(open_lines) >= OPEN_THRESHOLD:
            findings.append(
                Signal(
                    "NO_CONTEXT_MANAGER",
                    f"{len(open_lines)} open() calls without context manager",
                    SEVERITY_MEDIUM,
                    AXIS_QUALITY,
                    1.0,
                    open_lines[0],
                    context.lines[open_lines[0] - 1].strip(),
                )
            )
        broad = BROAD_EXCEPT_COUNT_PATTERN.findall(context.text)
        if len(broad) >= BROAD_EXCEPT_THRESHOLD:
            findings.append(
                Signal(
                    "GENERIC_EXCEPTIONS",
                    f"{len(broad)} undifferentiated except Exception handlers",
                    SEVERITY_MEDIUM,
                    AXIS_QUALITY,
                    1.0,
                    1,
                    f"{len(broad)} broad handlers",
                )
            )
    if context.language == "html":
        inline_styles = INLINE_STYLE_PATTERN.findall(context.text)
        if len(inline_styles) >= INLINE_STYLE_THRESHOLD:
            findings.append(
                Signal("INLINE_STYLES", f"{len(inline_styles)} inline style attributes", SEVERITY_WEAK, AXIS_QUALITY, 1.0, 1, f"{len(inline_styles)} inline styles")
            )
    return findings
