import base64
import hashlib
import time

from typing import Optional, TypedDict, Literal

Operation = Literal["read", "write"]


class Signature(TypedDict):
    signature: str
    expiration: Optional[int]  # Unix timestamp or None


def get_signature(
    path: str,
    operation: Operation,
    user: Optional[str],
    envd_access_token: Optional[str],
    expiration_in_seconds: Optional[int] = None,
) -> Signature:
    """
    Generate a v1 signature for sandbox file URLs.
    """
    if not envd_access_token:
        raise ValueError("Access token is not set and signature cannot be generated!")

    expiration = (
        int(time.time()) + expiration_in_seconds
        if expiration_in_seconds is not None
        else None
    )

    # if user is None, set it to empty string to handle default user
    if user is None:
        user = ""

    raw = (
        f"{path}:{operation}:{user}:{envd_access_token}"
        if expiration is None
        else f"{path}:{operation}:{user}:{envd_access_token}:{expiration}"
    )

    digest = hashlib.sha256(raw.encode("utf-8")).digest()
    encoded = base64.b64encode(digest).rstrip(b"=").decode("ascii")

    return {"signature": f"v1_{encoded}", "expiration": expiration}
