from __future__ import annotations

import re
import secrets
from typing import Tuple

BASE62_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
FG_ID_LENGTH = 12
FG_ID_PATTERN = re.compile(r"^fg:(co|ev):[0-9A-Za-z]{12}$")


def _int_to_base62(n: int, min_length: int = FG_ID_LENGTH) -> str:
    """Convert integer to base62 string, left-padded to min_length."""
    if n < 0:
        raise ValueError("n must be non-negative")
    if n == 0:
        result = BASE62_ALPHABET[0]
    else:
        result = ""
        while n > 0:
            result = BASE62_ALPHABET[n % 62] + result
            n //= 62
    return result.zfill(min_length)


def generate_fg_id(entity_type: str = "co") -> str:
    """
    Generate fg_id with exactly 12 base62 chars.
    Uses 72 bits of entropy (9 bytes) -> max value fits in 12 base62 chars.
    """
    random_bytes = secrets.token_bytes(9)
    random_int = int.from_bytes(random_bytes, "big")
    suffix = _int_to_base62(random_int, FG_ID_LENGTH)
    if len(suffix) > FG_ID_LENGTH:
        suffix = suffix[:FG_ID_LENGTH]
    return f"fg:{entity_type}:{suffix}"


def generate_event_id() -> str:
    """Generate event ID using same format: fg:ev:xxxxxxxxxxxx"""
    return generate_fg_id(entity_type="ev")


def parse_fg_id(fg_id: str) -> Tuple[str, str, str]:
    """Parse fg_id into (prefix, entity_type, random_part). Raises ValueError if invalid."""
    if not FG_ID_PATTERN.match(fg_id or ""):
        raise ValueError(f"Invalid fg_id format: {fg_id}")
    parts = fg_id.split(":")
    return (parts[0], parts[1], parts[2])


def validate_fg_id(fg_id: str) -> bool:
    """Validate fg_id format without database lookup."""
    return bool(FG_ID_PATTERN.match(fg_id or ""))
