"""
Tests for Multi-Timeframe (MTF) Utilities.

Tests the core bar index computation with pre-computed expected values.
"""

import pytest
import numpy as np
from datetime import datetime, timezone, timedelta

from sixtysix.strategy import compute_mtf_bar_indices


def make_hourly_timestamps(n: int) -> np.ndarray:
    """Create hourly timestamps starting from midnight Jan 1, 2024."""
    start = datetime(2024, 1, 1, tzinfo=timezone.utc)
    return np.array([
        int((start + timedelta(hours=i)).timestamp() * 1000)
        for i in range(n)
    ])


def make_daily_timestamps(n: int) -> np.ndarray:
    """Create daily timestamps starting from midnight Jan 1, 2024."""
    start = datetime(2024, 1, 1, tzinfo=timezone.utc)
    return np.array([
        int((start + timedelta(days=i)).timestamp() * 1000)
        for i in range(n)
    ])


def make_4h_timestamps(n: int) -> np.ndarray:
    """Create 4-hour timestamps starting from midnight Jan 1, 2024."""
    start = datetime(2024, 1, 1, tzinfo=timezone.utc)
    return np.array([
        int((start + timedelta(hours=i * 4)).timestamp() * 1000)
        for i in range(n)
    ])


class TestComputeMtfBarIndices:
    """Tests for compute_mtf_bar_indices function."""

    def test_hourly_to_daily_alignment(self):
        """Test hourly bars correctly map to daily bars."""
        # 48 hourly bars = 2 days
        hourly = make_hourly_timestamps(48)
        # 3 daily bars
        daily = make_daily_timestamps(3)

        indices = compute_mtf_bar_indices(hourly, daily)

        # Hours 0-23 -> day 0, hours 24-47 -> day 1
        expected = np.array([0] * 24 + [1] * 24)
        np.testing.assert_array_equal(indices, expected)

    def test_hourly_to_4h_alignment(self):
        """Test hourly bars correctly map to 4-hour bars."""
        # 24 hourly bars
        hourly = make_hourly_timestamps(24)
        # 7 4h bars
        four_hour = make_4h_timestamps(7)

        indices = compute_mtf_bar_indices(hourly, four_hour)

        # Hours 0-3 -> bar 0, hours 4-7 -> bar 1, etc.
        expected = np.array([
            0, 0, 0, 0,
            1, 1, 1, 1,
            2, 2, 2, 2,
            3, 3, 3, 3,
            4, 4, 4, 4,
            5, 5, 5, 5,
        ])
        np.testing.assert_array_equal(indices, expected)

    def test_exact_boundary_alignment(self):
        """Test bars at exact timeframe boundaries."""
        # 25 hourly bars (0 to 24 hours)
        hourly = make_hourly_timestamps(25)
        # 2 daily bars
        daily = make_daily_timestamps(2)

        indices = compute_mtf_bar_indices(hourly, daily)

        # Hour 0-23 -> day 0, hour 24 -> day 1
        expected = np.array([0] * 24 + [1])
        np.testing.assert_array_equal(indices, expected)

    def test_single_mtf_bar(self):
        """Test when all base bars fall within single MTF bar."""
        hourly = make_hourly_timestamps(12)
        daily = make_daily_timestamps(1)

        indices = compute_mtf_bar_indices(hourly, daily)

        expected = np.array([0] * 12)
        np.testing.assert_array_equal(indices, expected)

    def test_clips_to_valid_range(self):
        """Test that indices are clipped to valid range."""
        hourly = make_hourly_timestamps(48)
        daily = make_daily_timestamps(2)

        indices = compute_mtf_bar_indices(hourly, daily)

        # All indices should be 0 or 1
        assert indices.min() >= 0
        assert indices.max() <= 1


if __name__ == '__main__':
    pytest.main([__file__, '-v'])
