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

import re

from devplacepy.services.jobs.isslop.analysis.domsignals.base import DomPageContext, dom_check
from devplacepy.services.jobs.isslop.analysis.signals import AXIS_QUALITY, SEVERITY_WEAK, Signal

GENERIC_ALT_PATTERN = re.compile(r"^(image of|photo of|picture of)\b", re.IGNORECASE)
DUPLICATE_ALT_THRESHOLD: int = 3
EMPTY_ALT_THRESHOLD: int = 3


def _detect_generic_alt_text(images: list[dict]) -> Signal | None:
    empty_count = 0
    for image in images:
        alt = str(image.get("alt", "")).strip() if isinstance(image, dict) else ""
        if not alt:
            empty_count += 1
            continue
        if GENERIC_ALT_PATTERN.match(alt):
            return Signal(
                "GENERIC_ALT_TEXT",
                "Generic placeholder-style alt text on an image",
                SEVERITY_WEAK,
                AXIS_QUALITY,
                1.0,
                0,
                alt[:100],
            )
    if empty_count >= EMPTY_ALT_THRESHOLD and len(images) >= EMPTY_ALT_THRESHOLD:
        return Signal(
            "GENERIC_ALT_TEXT",
            f"{empty_count} images with empty alt text",
            SEVERITY_WEAK,
            AXIS_QUALITY,
            1.0,
            0,
            f"{empty_count} empty alt attributes",
        )
    return None


def _detect_duplicate_alt_text(images: list[dict]) -> Signal | None:
    counts: dict[str, int] = {}
    for image in images:
        alt = str(image.get("alt", "")).strip() if isinstance(image, dict) else ""
        if alt:
            counts[alt] = counts.get(alt, 0) + 1
    for alt, count in counts.items():
        if count >= DUPLICATE_ALT_THRESHOLD:
            return Signal(
                "DUPLICATE_ALT_TEXT",
                f"{count} images share the exact same alt text",
                SEVERITY_WEAK,
                AXIS_QUALITY,
                1.0,
                0,
                alt[:100],
            )
    return None


def _detect_skipped_heading_level(headings: list[dict]) -> Signal | None:
    levels = [
        heading.get("level")
        for heading in headings
        if isinstance(heading, dict) and isinstance(heading.get("level"), int)
    ]
    if len(levels) < 2 or levels[0] != 1:
        return None
    next_level = levels[1]
    if isinstance(next_level, int) and next_level > 2:
        return Signal(
            "SKIPPED_HEADING_LEVEL",
            f"H1 followed directly by H{next_level} with no H2 in between",
            SEVERITY_WEAK,
            AXIS_QUALITY,
            0.5,
            0,
            f"H1 -> H{next_level}",
        )
    return None


@dom_check
def detect_accessibility_signals(page: DomPageContext) -> list[Signal]:
    images = page.dom.get("images", []) or []
    headings = page.dom.get("headings", []) or []
    findings: list[Signal] = []
    for signal in (
        _detect_generic_alt_text(images),
        _detect_duplicate_alt_text(images),
        _detect_skipped_heading_level(headings),
    ):
        if signal is not None:
            findings.append(signal)
    return findings
