"""Forensic share tokens — time-limited, auditable evidence sharing.

Uses ``CertiSigmaClient.create_share_token()``,
``list_share_tokens()``, ``revoke_share_token()``, and
``get_share_token_info()`` from SDK v1.6.0+.

Share tokens enable chain-of-custody workflows: an investigator
shares specific attestation evidence with a third party (legal,
regulator, law enforcement) via a time-limited, use-limited token.
The token owner can track all access via the access log.
"""

from __future__ import annotations

import logging
import re
from dataclasses import dataclass, field
from typing import Any, Optional

logger = logging.getLogger(__name__)

_DURATION_RE = re.compile(r"^(\d+)\s*(m|min|h|hr|hour|d|day)s?$", re.IGNORECASE)

_DURATION_MULTIPLIERS: dict[str, int] = {
    "m": 60, "min": 60,
    "h": 3600, "hr": 3600, "hour": 3600,
    "d": 86400, "day": 86400,
}


def parse_duration_seconds(value: str) -> int:
    """Parse a human-friendly duration string to seconds.

    Accepted formats: ``30m``, ``24h``, ``7d``, ``1day``, ``2hours``.
    """
    match = _DURATION_RE.match(value.strip())
    if not match:
        raise ValueError(
            f"Invalid duration: {value!r}. "
            "Use formats like 30m, 24h, 7d."
        )
    amount = int(match.group(1))
    unit = match.group(2).lower()
    if amount <= 0:
        raise ValueError("Duration must be positive.")
    return amount * _DURATION_MULTIPLIERS[unit]


@dataclass
class ShareResult:
    success: bool
    token_id: Optional[str] = None
    share_token: Optional[str] = None
    attestation_ids: list[str] = field(default_factory=list)
    expires_at: Optional[str] = None
    recipient_label: Optional[str] = None
    max_uses: Optional[int] = None
    error: Optional[str] = None


@dataclass
class ShareInfo:
    token_id: str
    attestation_ids: list[str]
    recipient_label: Optional[str]
    max_uses: Optional[int]
    use_count: int
    expires_at: Optional[str]
    revoked_at: Optional[str]
    created_at: Optional[str]
    active: bool


def _parse_attestation_id(raw: str) -> int:
    """Convert a user-supplied attestation ID to the integer the SDK expects.

    Accepts ``"42"`` or ``"att_42"`` and returns ``42``.
    """
    cleaned = raw.strip().removeprefix("att_")
    try:
        return int(cleaned)
    except ValueError:
        raise ValueError(
            f"Invalid attestation ID: {raw!r}. "
            "Expected a numeric ID or att_<number>."
        ) from None


def create_share_token(
    attestation_ids: list[str],
    *,
    api_key: str | None = None,
    base_url: str | None = None,
    expires_in: str = "24h",
    recipient_label: str | None = None,
    max_uses: int | None = None,
) -> ShareResult:
    """Create a forensic share token for one or more attestations."""
    from certisigma import CertiSigmaClient, CertiSigmaError

    if not attestation_ids:
        return ShareResult(success=False, error="No attestation IDs provided.")

    try:
        int_ids = [_parse_attestation_id(a) for a in attestation_ids]
    except ValueError as exc:
        return ShareResult(success=False, error=str(exc))

    try:
        expires_seconds = parse_duration_seconds(expires_in)
    except ValueError as exc:
        return ShareResult(success=False, error=str(exc))

    kwargs: dict[str, Any] = {}
    if api_key:
        kwargs["api_key"] = api_key
    if base_url:
        kwargs["base_url"] = base_url
    client = CertiSigmaClient(**kwargs)
    try:
        try:
            result = client.create_share_token(
                attestation_ids=int_ids,
                expires_in=expires_seconds,
                recipient_label=recipient_label,
                max_uses=max_uses,
            )
            return ShareResult(
                success=True,
                token_id=result.id,
                share_token=result.share_token,
                attestation_ids=list(result.attestation_ids),
                expires_at=result.expires_at,
                recipient_label=recipient_label,
                max_uses=max_uses,
            )
        except CertiSigmaError as exc:
            return ShareResult(success=False, error=str(exc))
    finally:
        client.close()


def list_share_tokens(
    *,
    api_key: str | None = None,
    base_url: str | None = None,
) -> list[ShareInfo]:
    """List all share tokens owned by the authenticated user."""
    from certisigma import CertiSigmaClient, CertiSigmaError

    kwargs: dict[str, Any] = {}
    if api_key:
        kwargs["api_key"] = api_key
    if base_url:
        kwargs["base_url"] = base_url
    client = CertiSigmaClient(**kwargs)
    try:
        try:
            tokens = client.list_share_tokens()
        except CertiSigmaError as exc:
            logger.error("Failed to list share tokens: %s", exc)
            return []

        return [
            ShareInfo(
                token_id=t.id,
                attestation_ids=list(t.attestation_ids),
                recipient_label=t.recipient_label,
                max_uses=t.max_uses,
                use_count=t.use_count,
                expires_at=t.expires_at,
                revoked_at=t.revoked_at,
                created_at=t.created_at,
                active=t.active,
            )
            for t in tokens
        ]
    finally:
        client.close()


def revoke_share_token(
    token_id: str,
    *,
    api_key: str | None = None,
    base_url: str | None = None,
) -> ShareResult:
    """Revoke a share token."""
    from certisigma import CertiSigmaClient, CertiSigmaError

    kwargs: dict[str, Any] = {}
    if api_key:
        kwargs["api_key"] = api_key
    if base_url:
        kwargs["base_url"] = base_url
    client = CertiSigmaClient(**kwargs)
    try:
        try:
            client.revoke_share_token(token_id)
            return ShareResult(success=True, token_id=token_id)
        except CertiSigmaError as exc:
            return ShareResult(success=False, token_id=token_id, error=str(exc))
    finally:
        client.close()


def get_share_token_info(
    token_id: str,
    *,
    api_key: str | None = None,
    base_url: str | None = None,
) -> ShareInfo | ShareResult:
    """Get details about a specific share token."""
    from certisigma import CertiSigmaClient, CertiSigmaError

    kwargs: dict[str, Any] = {}
    if api_key:
        kwargs["api_key"] = api_key
    if base_url:
        kwargs["base_url"] = base_url
    client = CertiSigmaClient(**kwargs)
    try:
        try:
            t = client.get_share_token_info(token_id)
            return ShareInfo(
                token_id=t.id,
                attestation_ids=list(t.attestation_ids),
                recipient_label=t.recipient_label,
                max_uses=t.max_uses,
                use_count=t.use_count,
                expires_at=t.expires_at,
                revoked_at=t.revoked_at,
                created_at=t.created_at,
                active=t.active,
            )
        except CertiSigmaError as exc:
            return ShareResult(success=False, token_id=token_id, error=str(exc))
    finally:
        client.close()
