"""One solution to pages_practice.py. is_right and the outcome labels follow Lab 08's 02_documents_as_images.py."""
import re


def is_right(answer: str, correct, kind: str) -> bool:
    if kind == "word":
        return re.sub(r"[^a-z]", "", answer.lower()) == correct.lower()
    if kind == "text":
        return str(correct).lower() in answer.lower()
    numbers = re.findall(r"\d+(?:\.\d+)?", answer.replace(",", ""))
    return any(abs(float(n) - correct) < 0.005 for n in numbers)


def outcome(answer: str, right: bool) -> str:
    if right:
        return "right"
    return "not found" if "not found" in answer.lower() else "wrong"


def split_columns(text: str, headers: list[str]) -> dict[str, list[str]]:
    columns: dict[str, list[str]] = {}
    current = None
    for line in text.splitlines():
        line = line.strip()
        if line in headers and line not in columns:
            current = line
            columns[current] = []
        elif current is not None and line:
            columns[current].append(line)
    return columns


def pair_in_order(columns: dict[str, list[str]], key: str, value: str) -> dict[str, str | None]:
    values = columns[value]
    return {k: (values[i] if i < len(values) else None) for i, k in enumerate(columns[key])}


def short_columns(columns: dict[str, list[str]]) -> list[str]:
    longest = max(len(v) for v in columns.values())
    return [h for h, v in columns.items() if len(v) < longest]


def cost_per_1000(input_tokens: int, output_tokens: int, n: int, price_in: float, price_out: float) -> float:
    return (input_tokens * price_in + output_tokens * price_out) / 1_000_000 / n * 1000


def lowest_good_dpi(results: dict[int, tuple[int, int]], need: float) -> int | None:
    for dpi in sorted(results):
        right, asked = results[dpi]
        if right / asked >= need:
            return dpi
    return None
