"""Unit tests for entry cost calculation."""
from __future__ import annotations

from datetime import datetime, time
from decimal import Decimal
from types import SimpleNamespace

import pytest

from events.bp.calendar_entries.routes import calculate_entry_cost


def _slot(cost=None, flexible=False, time_start=None, time_end=None):
    return SimpleNamespace(
        cost=cost,
        flexible=flexible,
        time_start=time_start or time(9, 0),
        time_end=time_end or time(17, 0),
    )


class TestCalculateEntryCost:
    def test_no_cost(self):
        assert calculate_entry_cost(_slot(cost=None),
                                    datetime(2025, 1, 1, 9), datetime(2025, 1, 1, 17)) == Decimal("0")

    def test_fixed_slot(self):
        result = calculate_entry_cost(_slot(cost=100, flexible=False),
                                      datetime(2025, 1, 1, 10), datetime(2025, 1, 1, 12))
        assert result == Decimal("100")

    def test_flexible_full_duration(self):
        slot = _slot(cost=80, flexible=True, time_start=time(9, 0), time_end=time(17, 0))
        # 8 hours slot, booking full 8 hours
        result = calculate_entry_cost(slot,
                                      datetime(2025, 1, 1, 9, 0), datetime(2025, 1, 1, 17, 0))
        assert result == Decimal("80")

    def test_flexible_half_duration(self):
        slot = _slot(cost=80, flexible=True, time_start=time(9, 0), time_end=time(17, 0))
        # 4 hours of 8-hour slot = half
        result = calculate_entry_cost(slot,
                                      datetime(2025, 1, 1, 9, 0), datetime(2025, 1, 1, 13, 0))
        assert result == Decimal("40")

    def test_flexible_no_time_end(self):
        slot = _slot(cost=50, flexible=True, time_end=None)
        result = calculate_entry_cost(slot,
                                      datetime(2025, 1, 1, 9), datetime(2025, 1, 1, 12))
        # When time_end is None, function still calculates based on booking duration
        assert isinstance(result, Decimal)

    def test_flexible_zero_slot_duration(self):
        slot = _slot(cost=50, flexible=True, time_start=time(9, 0), time_end=time(9, 0))
        result = calculate_entry_cost(slot,
                                      datetime(2025, 1, 1, 9, 0), datetime(2025, 1, 1, 10, 0))
        assert result == Decimal("0")
