"""Normalize per-archive origin license metadata to the hef.catalog LICENSES vocab.

Maps Creative Commons URLs / identifiers and public-domain markers to
{public_domain, cc0, cc_by, cc_by_nc}. For the attribution licenses (cc_by,
cc_by_nc) it builds a non-empty attribution string — hef.catalog.validate()
rejects those licenses with an empty attribution. Anything unmappable is
rejected (a piece whose license can't be established is not ingested).
"""

from __future__ import annotations

import re


def _attribution(creator: str, license_name: str, raw: str, default_label: str) -> str:
    label = license_name or default_label or raw
    parts = []
    if creator:
        parts.append(creator)
    parts.append(label)
    return " — ".join(parts)


def normalize_license(raw, *, creator="", license_name=""):
    """Return (license, attribution) for an origin license string.

    Raises ValueError when `raw` does not map to an allowed license.
    """
    text = (raw or "").strip().lower()
    if not text:
        raise ValueError(f"unmappable license: {raw!r}")

    # CC0 / public-domain dedication (check before the generic publicdomain
    # markers, since the CC0 URL also contains "publicdomain").
    if "publicdomain/zero" in text or re.search(r"\bcc[ _-]?0\b", text):
        return ("cc0", "")

    # Public Domain Mark / explicit public domain / no-known-copyright.
    pd_markers = (
        "publicdomain/mark",
        "public_domain",
        "public domain",
        "publicdomain",
        "no known copyright",
        "pdm",
    )
    if any(m in text for m in pd_markers):
        return ("public_domain", "")

    # CC BY-NC must be checked before the bare CC BY.
    if re.search(r"by[ _-]?nc", text):
        return ("cc_by_nc", _attribution(creator, license_name, raw, "CC BY-NC"))

    # CC BY.
    if re.search(r"\bcc[ _-]?by\b", text) or "licenses/by" in text:
        return ("cc_by", _attribution(creator, license_name, raw, "CC BY"))

    raise ValueError(f"unmappable license: {raw!r}")


def librivox_license():
    """LibriVox recordings are public domain by charter (attribution not required)."""
    return ("public_domain", "")
