import unittest
from datetime import date

import weekly
from parsers import DayRow, FoodTotals, Measurement, Workout

STAGE = {"cardio_min": 100, "strength_days": 2}
SUNDAY = date(2026, 8, 2)

DAYS = {
    # прошлая неделя
    date(2026, 7, 20): DayRow(day=date(2026, 7, 20), weight=63.0, exercise_min=5, sleep_h=6.0),
    date(2026, 7, 22): DayRow(day=date(2026, 7, 22), weight=63.4, exercise_min=5, sleep_h=6.0),
    # текущая
    date(2026, 7, 27): DayRow(day=date(2026, 7, 27), weight=63.6, exercise_min=10, sleep_h=5.0, hrv=42.0, resting_hr=66),
    date(2026, 7, 29): DayRow(day=date(2026, 7, 29), exercise_min=35, sleep_h=6.2, hrv=41.6, resting_hr=66),
    date(2026, 7, 31): DayRow(day=date(2026, 7, 31), weight=63.9, exercise_min=0, sleep_h=8.6),
    date(2026, 8, 1): DayRow(day=date(2026, 8, 1), weight=64.1, exercise_min=20),
}
WORKOUTS = [
    Workout(date(2026, 7, 27), "Функциональный силовой тренинг", 30),
    Workout(date(2026, 7, 29), "Функциональный силовой тренинг", 28),
]
FOOD = {
    date(2026, 7, 31): FoodTotals(day=date(2026, 7, 31), kcal=1800, protein=100, fat=70, carbs=190),
    date(2026, 8, 1): FoodTotals(day=date(2026, 8, 1), kcal=2000, protein=120, fat=80, carbs=200),
}
MEASUREMENTS = {
    date(2026, 7, 26): Measurement(day=date(2026, 7, 26), weight=63.2, fat_pct=34.7),
    date(2026, 8, 1): Measurement(day=date(2026, 8, 1), weight=64.1, fat_pct=35.1),
}


def facts(**overrides):
    kwargs = dict(
        today=SUNDAY, days=DAYS, workouts=WORKOUTS, food=FOOD,
        measurements=MEASUREMENTS, stage=STAGE,
    )
    kwargs.update(overrides)
    return weekly.week_facts(**kwargs)


class ActivityFactsTest(unittest.TestCase):
    def test_cardio_and_strength_against_stage(self):
        data = facts()

        self.assertEqual(data["cardio_min"], 65)
        self.assertEqual(data["cardio_target"], 100)
        self.assertEqual(data["strength_days"], 2)

    def test_average_strength_session_length(self):
        self.assertEqual(facts()["strength_avg_min"], 29)


class WeightFactsTest(unittest.TestCase):
    def test_week_average_compared_with_previous_week(self):
        data = facts()

        self.assertEqual(data["weight_avg"], 63.9)
        self.assertEqual(data["weight_avg_prev"], 63.2)
        self.assertEqual(data["weight_delta"], 0.7)

    def test_previous_week_without_measurements_gives_none(self):
        data = facts(days={d: r for d, r in DAYS.items() if d >= date(2026, 7, 27)})

        self.assertIsNone(data["weight_avg_prev"])
        self.assertIsNone(data["weight_delta"])


class FoodFactsTest(unittest.TestCase):
    def test_averages_only_days_with_records(self):
        data = facts()

        self.assertEqual(data["food_days"], 2)
        self.assertEqual(data["kcal_avg"], 1900)
        self.assertEqual(data["protein_avg"], 110)

    def test_no_records_reports_zero_days(self):
        data = facts(food={})

        self.assertEqual(data["food_days"], 0)
        self.assertIsNone(data["kcal_avg"])


class BodyCompositionFactsTest(unittest.TestCase):
    def test_last_measurement_of_week_with_previous_one(self):
        data = facts()

        self.assertEqual(data["fat_pct"], 35.1)
        self.assertEqual(data["fat_pct_prev"], 34.7)


class RecoveryFactsTest(unittest.TestCase):
    def test_sleep_hrv_and_pulse_averages(self):
        data = facts()

        self.assertEqual(data["sleep_avg"], 6.6)
        self.assertEqual(data["hrv_avg"], 41.8)
        self.assertEqual(data["resting_hr_avg"], 66)


if __name__ == "__main__":
    unittest.main()
