# retoor <retoor@molodetz.nl>

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Callable, Optional

PASS = "pass"
WARN = "warn"
FAIL = "fail"
INFO = "info"
SKIP = "skip"

CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
INFORMATIONAL = "info"

SEVERITY_WEIGHT = {
    CRITICAL: 5.0,
    HIGH: 3.0,
    MEDIUM: 2.0,
    LOW: 1.0,
    INFORMATIONAL: 0.0,
}

STATUS_CREDIT = {PASS: 1.0, WARN: 0.5, FAIL: 0.0, INFO: 1.0, SKIP: 1.0}


@dataclass
class Check:
    id: str
    category: str
    title: str
    status: str
    severity: str = MEDIUM
    value: str = ""
    recommendation: str = ""
    details: dict = field(default_factory=dict)
    url: str = ""

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "category": self.category,
            "title": self.title,
            "status": self.status,
            "severity": self.severity,
            "value": self.value,
            "recommendation": self.recommendation,
            "details": self.details,
            "url": self.url,
        }


@dataclass
class PageContext:
    requested_url: str = ""
    url: str = ""
    status: int = 0
    ok: bool = False
    error: str = ""
    elapsed_ms: int = 0
    redirect_chain: list = field(default_factory=list)
    headers: dict = field(default_factory=dict)
    raw_html: str = ""
    rendered_html: str = ""
    dom: dict = field(default_factory=dict)
    metrics: dict = field(default_factory=dict)
    mobile: dict = field(default_factory=dict)
    screenshot: str = ""


@dataclass
class SiteContext:
    target_url: str = ""
    mode: str = "url"
    base_host: str = ""
    base_scheme: str = "https"
    robots: dict = field(default_factory=dict)
    sitemap: dict = field(default_factory=dict)
    llms_txt: dict = field(default_factory=dict)
    pages: list = field(default_factory=list)


PAGE_CHECKS: list[Callable] = []
SITE_CHECKS: list[Callable] = []


def page_check(func: Callable) -> Callable:
    PAGE_CHECKS.append(func)
    return func


def site_check(func: Callable) -> Callable:
    SITE_CHECKS.append(func)
    return func


def ok_check(
    cid: str,
    category: str,
    title: str,
    passed: bool,
    *,
    severity: str = MEDIUM,
    value: str = "",
    recommendation: str = "",
    details: Optional[dict] = None,
    url: str = "",
    warn: bool = False,
) -> Check:
    if passed:
        status = PASS
    else:
        status = WARN if warn else FAIL
    return Check(
        id=cid,
        category=category,
        title=title,
        status=status,
        severity=severity,
        value=value,
        recommendation=recommendation if not passed else "",
        details=details or {},
        url=url,
    )
