"""Structured error hierarchy for the license layer.

Mirrors the ``src.core.errors`` pattern — every subclass extends a
stdlib base so existing ``except OSError`` / ``except ValueError``
handlers keep working. The UI / CLI branches on the subclass to render
the right next step (activate, renew, contact support).
"""

from __future__ import annotations


class LicenseError(ValueError):
    """Base class for every licensing failure. Subclass-only — callers
    should catch the specific failure mode they handle."""


class NotActivatedError(LicenseError):
    """No license file present, or file present but signature missing.

    Recovery: open the activation page (GUI) or run
    ``datatools-license activate <blob>`` (CLI).
    """


class InvalidLicenseError(LicenseError):
    """The license file is present but failed verification.

    Common causes: tampered signature, blob from a different build
    (different secret), corrupted JSON. Recovery: re-paste the blob
    from the original delivery email or contact support.
    """


class ExpiredLicenseError(LicenseError):
    """The license is structurally valid but past its expiration date.

    Recovery: renew via ``datatools-license renew <blob>`` or paste a
    new blob into the activation page.
    """


class UnsupportedFeatureError(LicenseError):
    """The active license's tier doesn't unlock a requested feature.

    Raised by :func:`require_feature` when, e.g., a TRIAL user tries
    to access an ENTERPRISE-only tool. Recovery: upgrade tier.
    """
