"""Accessibility helpers (contrast ratios, tints) for TokenMoulds."""

from __future__ import annotations

from typing import List

from .models import Color


def relative_luminance(color: Color) -> float:
    def lin(channel: float) -> float:
        return (
            channel / 12.92
            if channel <= 0.04045
            else ((channel + 0.055) / 1.055) ** 2.4
        )

    r = lin(color.r)
    g = lin(color.g)
    b = lin(color.b)
    return 0.2126 * r + 0.7152 * g + 0.0722 * b


def contrast_ratio(foreground: Color, background: Color) -> float:
    l1 = relative_luminance(foreground)
    l2 = relative_luminance(background)
    lighter = max(l1, l2)
    darker = min(l1, l2)
    return (lighter + 0.05) / (darker + 0.05)


def ensure_contrast(
    foreground: Color, background: Color, *, target: float = 4.5
) -> Color:
    """Adjust the foreground color to meet the desired contrast ratio."""

    working = foreground
    if contrast_ratio(working, background) >= target:
        return working

    for step in range(1, 7):
        delta = 0.1 * step
        for sign in (1, -1):
            candidate = working.lighten(delta * sign)
            if contrast_ratio(candidate, background) >= target:
                return candidate

    for delta in (0.25, -0.25, 0.4, -0.4):
        candidate = working.saturate(delta)
        if contrast_ratio(candidate, background) >= target:
            return candidate

    return working


def generate_tints(color: Color, steps: int = 3, delta: float = 0.1) -> List[Color]:
    tints: List[Color] = []
    for index in range(1, steps + 1):
        tints.append(color.lighten(delta * index))
    return tints


def generate_shades(color: Color, steps: int = 3, delta: float = 0.1) -> List[Color]:
    shades: List[Color] = []
    for index in range(1, steps + 1):
        shades.append(color.lighten(-delta * index))
    return shades


__all__ = [
    "relative_luminance",
    "contrast_ratio",
    "ensure_contrast",
    "generate_tints",
    "generate_shades",
]
