"""
Hotel KPI formulas as standalone functions.
These can be used independently or imported by services.
"""


def occupancy_rate(rooms_sold: int, capacity: int, days: int = 1) -> float:
    """
    Taux d'Occupation (TO) - Occupancy Rate

    Formula: TO = (Chambres vendues / (Capacité × Jours)) × 100

    Args:
        rooms_sold: Number of rooms sold in the period
        capacity: Total room capacity
        days: Number of days in the period

    Returns:
        Occupancy rate as percentage (0-100)
    """
    if capacity <= 0 or days <= 0:
        return 0.0
    return (rooms_sold / (capacity * days)) * 100


def bed_occupancy_rate(nights: int, bed_capacity: int, days: int = 1) -> float:
    """
    Taux d'Occupation Lits (TO Lits) - Bed Occupancy Rate

    Formula: TO Lits = (Nuitées / (Capacité lits × Jours)) × 100

    Args:
        nights: Number of guest nights
        bed_capacity: Total bed capacity
        days: Number of days in the period

    Returns:
        Bed occupancy rate as percentage (0-100)
    """
    if bed_capacity <= 0 or days <= 0:
        return 0.0
    return (nights / (bed_capacity * days)) * 100


def frequency_index(nights: int, rooms_sold: int) -> float:
    """
    Indice de Fréquentation (IF) - Frequency Index

    Formula: IF = Nuitées / Chambres vendues

    Represents the average number of guests per room.

    Args:
        nights: Number of guest nights
        rooms_sold: Number of rooms sold

    Returns:
        Frequency index (typically 1.0-2.5)
    """
    if rooms_sold <= 0:
        return 0.0
    return nights / rooms_sold


def adr(revenue: float, rooms_sold: int) -> float:
    """
    Average Daily Rate (ADR) - Prix Moyen par Chambre

    Formula: ADR = CA Hébergement / Chambres vendues

    Args:
        revenue: Accommodation revenue
        rooms_sold: Number of rooms sold

    Returns:
        Average daily rate
    """
    if rooms_sold <= 0:
        return 0.0
    return revenue / rooms_sold


def revpar(revenue: float, capacity: int, days: int = 1) -> float:
    """
    Revenue Per Available Room (RevPAR)

    Formula: RevPAR = CA Hébergement / (Capacité × Jours)

    Can also be calculated as: ADR × Taux d'occupation

    Args:
        revenue: Accommodation revenue
        capacity: Total room capacity
        days: Number of days in the period

    Returns:
        RevPAR value
    """
    if capacity <= 0 or days <= 0:
        return 0.0
    return revenue / (capacity * days)


def average_guest_revenue(total_revenue: float, nights: int) -> float:
    """
    Recette Moyenne Client (RMC) - Average Guest Revenue

    Formula: RMC = CA Total / Nuitées

    Args:
        total_revenue: Total revenue from all departments
        nights: Number of guest nights

    Returns:
        Average revenue per guest night
    """
    if nights <= 0:
        return 0.0
    return total_revenue / nights


def fb_ratio(food_cost: float, fb_revenue: float) -> float:
    """
    Food & Beverage Ratio

    Formula: Ratio F&B = (Coût alimentaire HT / CA F&B HT) × 100

    Used to measure food cost efficiency.
    Industry benchmark: 25-35%

    Args:
        food_cost: Food cost before tax
        fb_revenue: F&B revenue before tax

    Returns:
        F&B ratio as percentage
    """
    if fb_revenue <= 0:
        return 0.0
    return (food_cost / fb_revenue) * 100


def trevpar(total_revenue: float, capacity: int, days: int = 1) -> float:
    """
    Total Revenue Per Available Room (TRevPAR)

    Formula: TRevPAR = CA Total / (Capacité × Jours)

    Args:
        total_revenue: Total revenue from all departments
        capacity: Total room capacity
        days: Number of days in the period

    Returns:
        TRevPAR value
    """
    if capacity <= 0 or days <= 0:
        return 0.0
    return total_revenue / (capacity * days)


def goppar(gop: float, capacity: int, days: int = 1) -> float:
    """
    Gross Operating Profit Per Available Room (GOPPAR)

    Formula: GOPPAR = GOP / (Capacité × Jours)

    Args:
        gop: Gross Operating Profit
        capacity: Total room capacity
        days: Number of days in the period

    Returns:
        GOPPAR value
    """
    if capacity <= 0 or days <= 0:
        return 0.0
    return gop / (capacity * days)


def double_occupancy(nights: int, rooms_sold: int) -> float:
    """
    Double Occupancy Rate

    Formula: ((Nuitées - Chambres vendues) / Chambres vendues) × 100

    Measures the percentage of rooms with more than one guest.

    Args:
        nights: Number of guest nights
        rooms_sold: Number of rooms sold

    Returns:
        Double occupancy rate as percentage
    """
    if rooms_sold <= 0:
        return 0.0
    return ((nights - rooms_sold) / rooms_sold) * 100


def calculate_tax(amount_ht: float, tax_rate: float) -> tuple:
    """
    Calculate tax amounts.

    Args:
        amount_ht: Amount before tax (HT)
        tax_rate: Tax rate as percentage (e.g., 10.0 for 10%)

    Returns:
        Tuple of (tax_amount, amount_ttc)
    """
    tax_amount = round(amount_ht * (tax_rate / 100), 2)
    amount_ttc = round(amount_ht + tax_amount, 2)
    return tax_amount, amount_ttc


def variance(current: float, previous: float) -> tuple:
    """
    Calculate variance between two values.

    Args:
        current: Current period value
        previous: Previous period value

    Returns:
        Tuple of (absolute_variance, percentage_variance)
    """
    absolute = current - previous
    if previous == 0:
        percentage = 100.0 if current > 0 else 0.0
    else:
        percentage = (absolute / previous) * 100
    return round(absolute, 2), round(percentage, 2)
