"""Unit tests for the migrate CLI command."""

import json
import sqlite3
from argparse import Namespace
from pathlib import Path

import pytest

from byteb4rb1e.homeostat.cli.commands import MigrateCommand
from byteb4rb1e.homeostat.warehouse.canonical import (
    CanonicalWarehouse,
)


def _write_json(path: Path, data: dict) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(
        json.dumps(data, ensure_ascii=False)
    )


def _setup_legacy(data_dir: Path) -> None:
    """Write minimal legacy JSON fixtures."""
    _write_json(data_dir / "status.json", {
        "last_updated": "2026-03-19T15:00:00Z",
        "vitals": {
            "steps_goal": 10000,
            "active_minutes_goal": 30,
        },
    })
    _write_json(data_dir / "history" / "vitals.json", {
        "days": [
            {
                "date": "2026-03-19",
                "resting_hr": 62,
                "steps": 8000,
                "calories_burned": 2200,
                "active_minutes": 30,
            }
        ],
    })
    _write_json(
        data_dir / "history" / "activity.json", {
            "days": [
                {
                    "date": "2026-03-19",
                    "sedentary_minutes": 600,
                    "lightly_active_minutes": 120,
                    "fairly_active_minutes": 10,
                    "very_active_minutes": 20,
                    "floors": 5,
                    "elevation": 15.0,
                    "distance_km": 6.5,
                    "logged_activities": [
                        {
                            "name": "Run",
                            "calories": 300,
                            "duration_min": 30.0,
                            "steps": 3000,
                            "start_time": "07:00",
                        }
                    ],
                }
            ],
        },
    )
    _write_json(data_dir / "history" / "sleep.json", {
        "days": [
            {
                "date": "2026-03-19",
                "duration_hours": 7.5,
                "score": 88,
                "stages": {
                    "deep": 1.5,
                    "light": 3.0,
                    "rem": 1.5,
                    "awake": 0.5,
                },
            }
        ],
    })
    _write_json(
        data_dir / "history" / "nutrition.json", {
            "days": [
                {
                    "date": "2026-03-19",
                    "calories": 2400,
                    "target": 1800,
                    "macros": {
                        "protein_g": 160,
                        "carbs_g": 250,
                        "fat_g": 70,
                    },
                    "meals": [
                        {
                            "name": "Breakfast",
                            "calories": 500,
                            "macros": {
                                "protein_g": 30,
                                "carbs_g": 60,
                                "fat_g": 15,
                            },
                            "items": ["Oatmeal"],
                        }
                    ],
                }
            ],
        },
    )
    _write_json(
        data_dir / "history" / "measurements.json", {
            "days": [
                {
                    "date": "2026-03-19",
                    "weight_kg": 72.5,
                    "body_fat_pct": 18.0,
                    "bmi": 23.0,
                    "muscle_mass_kg": 0,
                    "body": None,
                }
            ],
        },
    )


class TestMigrateCommand:
    def test_migrates_all_entities(self, tmp_path):
        data_dir = tmp_path / "data"
        _setup_legacy(data_dir)

        cmd = MigrateCommand()
        rc = cmd.execute(Namespace(data_dir=data_dir))
        assert rc == 0

        wh = CanonicalWarehouse(root=data_dir)
        db = sqlite3.connect(":memory:")
        count = wh.hydrate(db)

        # Verify each entity was created
        db.row_factory = sqlite3.Row

        row = db.execute(
            "SELECT * FROM step_snapshot"
        ).fetchone()
        assert row["steps"] == 8000
        assert row["source"] == "legacy"

        row = db.execute(
            "SELECT * FROM calorie_snapshot"
        ).fetchone()
        assert row["calories"] == 2200

        row = db.execute(
            "SELECT * FROM resting_heart_rate_sample"
        ).fetchone()
        assert row["bpm"] == 62

        row = db.execute(
            "SELECT * FROM goal_snapshot"
        ).fetchone()
        assert row["steps_goal"] == 10000
        assert row["active_minutes_goal"] == 30

        row = db.execute(
            "SELECT * FROM active_minutes_snapshot"
        ).fetchone()
        assert row["fairly_active"] == 10
        assert row["very_active"] == 20

        row = db.execute(
            "SELECT * FROM activity_level_snapshot"
        ).fetchone()
        assert row["sedentary_minutes"] == 600

        row = db.execute(
            "SELECT * FROM distance_snapshot"
        ).fetchone()
        assert row["distance_km"] == 6.5

        row = db.execute(
            "SELECT * FROM activity_session"
        ).fetchone()
        assert row["name"] == "Run"

        row = db.execute(
            "SELECT * FROM sleep_session"
        ).fetchone()
        assert row["duration_hours"] == 7.5
        assert row["score"] == 88

        stages = db.execute(
            "SELECT * FROM sleep_stage"
            " ORDER BY stage"
        ).fetchall()
        assert len(stages) == 4

        row = db.execute(
            "SELECT * FROM nutrition_day"
        ).fetchone()
        assert row["calories_consumed"] == 2400

        row = db.execute(
            "SELECT * FROM meal"
        ).fetchone()
        assert row["meal_name"] == "Breakfast"

        row = db.execute(
            "SELECT * FROM meal_item"
        ).fetchone()
        assert row["item_name"] == "Oatmeal"

        row = db.execute(
            "SELECT * FROM body_measurement"
        ).fetchone()
        assert row["weight_kg"] == 72.5

    def test_skips_zero_data(self, tmp_path):
        data_dir = tmp_path / "data"
        _write_json(
            data_dir / "history" / "vitals.json", {
                "days": [
                    {
                        "date": "2026-03-19",
                        "resting_hr": 0,
                        "steps": 0,
                        "calories_burned": 0,
                    }
                ],
            },
        )
        _write_json(
            data_dir / "history" / "measurements.json",
            {"days": [
                {
                    "date": "2026-03-19",
                    "weight_kg": 0,
                    "body_fat_pct": 0,
                    "bmi": 0,
                }
            ]},
        )

        cmd = MigrateCommand()
        rc = cmd.execute(Namespace(data_dir=data_dir))
        assert rc == 0

        wh = CanonicalWarehouse(root=data_dir)
        db = sqlite3.connect(":memory:")
        wh.hydrate(db)

        assert db.execute(
            "SELECT COUNT(*) FROM step_snapshot"
        ).fetchone()[0] == 0
        assert db.execute(
            "SELECT COUNT(*) FROM body_measurement"
        ).fetchone()[0] == 0

    def test_empty_data_dir(self, tmp_path):
        data_dir = tmp_path / "data"
        data_dir.mkdir()

        cmd = MigrateCommand()
        rc = cmd.execute(Namespace(data_dir=data_dir))
        assert rc == 0
