"""
Shared utility functions used by multiple modules.
"""

import secrets
import string
from sqlalchemy.orm import Session
from typing import Type, TypeVar
from src.apps.base.models import Base
import random
from slugify import slugify

ModelType = TypeVar("ModelType", bound=Base)


def generate_secure_id(prepend: str = "", length: int = 20) -> str:
    """
    Generate a secure random ID with optional prefix.
    
    Args:
        prepend: String to prepend to the ID
        length: Length of the random part
        
    Returns:
        Secure random ID string
    """
    # Generate random string using secrets for cryptographic randomness
    alphabet = string.ascii_letters + string.digits
    random_part = ''.join(secrets.choice(alphabet) for _ in range(length))
    
    if prepend:
        return f"{prepend}_{random_part}"
    return random_part


def round_half_up(number, decimals: int = 0) -> int:
    """
    This function rounds a number half up. Eg. 18.5 will round to 19
    """
    rounded_value = int(number * (10**decimals) + 0.5) / (10**decimals)
    if rounded_value % 1 == 0:
        rounded_value = int(rounded_value)
    return rounded_value


def format_amount(val: float, precision: int = 2) -> str:
    formatted_amount = "{{:,.{}f}}".format(precision)
    try:
        return formatted_amount.format(val / 100)
    except:
        return "0"


def random_string_generator(size: int = 5) -> str:
    """
    Generate a random string of given size
    """
    return "".join(random.choices(string.ascii_uppercase + string.digits, k=size))


def generate_unique_slug(
    db: Session, instance: Type[ModelType], slug_label: str = None, new_slug: str = None
) -> str:
    """
    This is for a FastAPI project and it assumes your instance
    is a model, and generates a unique slug
    """
    if new_slug is not None:
        slug = new_slug
    else:
        slug = slugify(slug_label)

    # Klass = instance.__class__
    qs_exists = db.query(instance).filter(instance.slug == slug).first()
    if qs_exists:
        new_slug = "{slug}-{randstr}".format(
            slug=slug, randstr=random_string_generator(size=4)
        )
        return generate_unique_slug(
            db=db, instance=instance, new_slug=new_slug, slug_label=None
        )
    return slug