from __future__ import annotations

from dataclasses import dataclass
from typing import Dict, Iterable, List, Mapping

from .model import Book

REDACTION = "********"


@dataclass(frozen=True)
class SecretRedactor:
    _text_values: List[str]
    _byte_values: List[bytes]

    @staticmethod
    def from_values(values: Iterable[str]) -> "SecretRedactor":
        uniq: list[str] = []
        seen = set()
        for v in values:
            s = str(v)
            if not s:
                continue
            if s in seen:
                continue
            seen.add(s)
            uniq.append(s)
        uniq.sort(key=len, reverse=True)
        return SecretRedactor(
            _text_values=uniq,
            _byte_values=[u.encode("utf-8", errors="ignore") for u in uniq],
        )

    def redact_text(self, text: str) -> str:
        out = text
        for v in self._text_values:
            out = out.replace(v, REDACTION)
        return out

    def redact_bytes(self, data: bytes) -> bytes:
        out = data
        repl = REDACTION.encode("utf-8")
        for v in self._byte_values:
            if not v:
                continue
            out = out.replace(v, repl)
        return out


def sensitive_values(book: Book, *, vars_map: Mapping[str, str]) -> list[str]:
    vals: list[str] = []

    for key in book.sensitive:
        v = vars_map.get(key)
        if v:
            vals.append(str(v))

    return vals


def redact_vars_map(book: Book, vars_map: Mapping[str, str]) -> Dict[str, str]:
    out: Dict[str, str] = dict(vars_map)
    for key in book.sensitive:
        if key in out:
            out[key] = REDACTION
    return out
