"""Unit tests for Fitbit transformers."""

import pytest

from byteb4rb1e.homeostat.transformers.fitbit import (
    transform_heart_rate,
    transform_steps,
    transform_calories,
    transform_activities,
    transform_sleep,
    transform_body,
)

FETCHED = "2026-03-19T15:00:00+00:00"
DATE = "2026-03-19"


class TestTransformHeartRate:
    def test_extracts_samples_and_resting(self):
        payload = {
            "activities-heart": [
                {
                    "dateTime": DATE,
                    "value": {
                        "restingHeartRate": 62,
                    },
                }
            ],
            "activities-heart-intraday": {
                "dataset": [
                    {"time": "14:00:00", "value": 72},
                    {"time": "14:01:00", "value": 75},
                ]
            },
        }
        samples, resting = transform_heart_rate(
            payload, DATE, FETCHED
        )
        assert len(samples) == 2
        assert samples[0].bpm == 72
        assert samples[0].time == "14:00:00"
        assert samples[1].bpm == 75

        assert len(resting) == 1
        assert resting[0].bpm == 62

    def test_no_resting_hr(self):
        payload = {
            "activities-heart-intraday": {
                "dataset": [
                    {"time": "14:00:00", "value": 72},
                ]
            }
        }
        samples, resting = transform_heart_rate(
            payload, DATE, FETCHED
        )
        assert len(samples) == 1
        assert resting == []

    def test_empty_dataset(self):
        payload = {
            "activities-heart-intraday": {"dataset": []}
        }
        samples, resting = transform_heart_rate(
            payload, DATE, FETCHED
        )
        assert samples == []
        assert resting == []

    def test_missing_key(self):
        samples, resting = transform_heart_rate(
            {}, DATE, FETCHED
        )
        assert samples == []
        assert resting == []

    def test_string_value_does_not_crash(self):
        payload = {
            "activities-heart": [
                {
                    "dateTime": DATE,
                    "value": "74.86",
                }
            ],
            "activities-heart-intraday": {
                "dataset": [
                    {"time": "00:00:00", "value": 65},
                ]
            },
        }
        samples, resting = transform_heart_rate(
            payload, DATE, FETCHED
        )
        assert len(samples) == 1
        assert resting == []


class TestTransformSteps:
    def test_extracts_step_count(self):
        payload = {
            "activities-steps": [{"value": "8000"}]
        }
        snapshots = transform_steps(payload, DATE, FETCHED)
        assert len(snapshots) == 1
        assert snapshots[0].steps == 8000

    def test_empty_entries(self):
        assert transform_steps(
            {"activities-steps": []}, DATE, FETCHED
        ) == []


class TestTransformCalories:
    def test_extracts_calories(self):
        payload = {
            "activities-calories": [{"value": "2200"}]
        }
        snapshots = transform_calories(
            payload, DATE, FETCHED
        )
        assert len(snapshots) == 1
        assert snapshots[0].calories == 2200


class TestTransformActivities:
    def test_extracts_all_five_types(self):
        payload = {
            "summary": {
                "sedentaryMinutes": 600,
                "lightlyActiveMinutes": 120,
                "fairlyActiveMinutes": 30,
                "veryActiveMinutes": 15,
                "floors": 5,
                "elevation": 15.0,
                "distances": [
                    {"activity": "total", "distance": 6.5}
                ],
            },
            "activities": [
                {
                    "name": "Run",
                    "calories": 300,
                    "duration": 1800000,
                    "steps": 3000,
                    "startTime": "2026-03-19T07:00:00.000",
                }
            ],
            "goals": {
                "steps": 10000,
                "activeMinutes": 30,
            },
        }
        am, al, dist, sessions, goals = (
            transform_activities(payload, DATE, FETCHED)
        )

        assert len(am) == 1
        assert am[0].fairly_active == 30
        assert am[0].very_active == 15

        assert len(al) == 1
        assert al[0].sedentary_minutes == 600

        assert len(dist) == 1
        assert dist[0].distance_km == 6.5
        assert dist[0].floors == 5

        assert len(sessions) == 1
        assert sessions[0].name == "Run"
        assert sessions[0].duration_min == 30.0

        assert len(goals) == 1
        assert goals[0].steps_goal == 10000
        assert goals[0].active_minutes_goal == 30

    def test_no_activities(self):
        payload = {"summary": {}, "activities": []}
        am, al, dist, sessions, goals = (
            transform_activities(payload, DATE, FETCHED)
        )
        assert len(sessions) == 0
        assert len(am) == 1
        assert len(goals) == 0

    def test_no_goals(self):
        payload = {
            "summary": {},
            "activities": [],
        }
        _, _, _, _, goals = transform_activities(
            payload, DATE, FETCHED
        )
        assert goals == []


class TestTransformSleep:
    def test_extracts_sessions_and_stages(self):
        payload = {
            "sleep": [
                {
                    "startTime": "2026-03-18T23:00:00.000",
                    "endTime": "2026-03-19T07:00:00.000",
                    "duration": 28800000,
                    "efficiency": 92,
                    "isMainSleep": True,
                    "levels": {
                        "summary": {
                            "deep": {"minutes": 90},
                            "light": {"minutes": 200},
                            "rem": {"minutes": 80},
                            "wake": {"minutes": 30},
                        }
                    },
                }
            ]
        }
        sessions, stages = transform_sleep(
            payload, DATE, FETCHED
        )
        assert len(sessions) == 1
        assert sessions[0].bedtime == (
            "2026-03-18T23:00:00.000"
        )
        assert sessions[0].is_main is True
        assert sessions[0].score == 92

        assert len(stages) == 4
        stage_names = {s.stage for s in stages}
        assert stage_names == {
            "deep", "light", "rem", "awake"
        }
        assert all(
            s.bedtime == "2026-03-18T23:00:00.000"
            for s in stages
        )

    def test_renames_wake_to_awake(self):
        payload = {
            "sleep": [
                {
                    "startTime": "23:00",
                    "endTime": "07:00",
                    "duration": 28800000,
                    "efficiency": 90,
                    "isMainSleep": True,
                    "levels": {
                        "summary": {
                            "wake": {"minutes": 20},
                        }
                    },
                }
            ]
        }
        _, stages = transform_sleep(
            payload, DATE, FETCHED
        )
        assert stages[0].stage == "awake"

    def test_no_sleep(self):
        sessions, stages = transform_sleep(
            {"sleep": []}, DATE, FETCHED
        )
        assert sessions == []
        assert stages == []


class TestTransformBody:
    def test_extracts_body_data(self):
        payload = {
            "body": {
                "weight": 72.5,
                "fat": 18.2,
                "bmi": 23.0,
            }
        }
        records = transform_body(payload, DATE, FETCHED)
        assert len(records) == 1
        assert records[0].weight_kg == 72.5
        assert records[0].body_fat_pct == 18.2

    def test_all_zeros_returns_empty(self):
        payload = {
            "body": {"weight": 0, "fat": 0, "bmi": 0}
        }
        assert transform_body(payload, DATE, FETCHED) == []
