"""Smoke test: full fddb pipeline.

Requires live credentials in environment:
    FDDB_USERNAME, FDDB_PASSWORD
"""

import json
import os
import sqlite3
from datetime import datetime, timezone
from pathlib import Path

import pytest

from byteb4rb1e.homeostat.adapters.fddb import (
    FddbAdapter,
)
from byteb4rb1e.homeostat.projections.builder import (
    ProjectionBuilder,
)
from byteb4rb1e.homeostat.transformers.fddb import (
    transform_day_detail,
    transform_month_diary,
)
from byteb4rb1e.homeostat.warehouse.canonical import (
    CanonicalWarehouse,
)
from byteb4rb1e.homeostat.warehouse.raw import RawWarehouse


pytestmark = pytest.mark.skipif(
    not os.environ.get("FDDB_USERNAME"),
    reason="FDDB_USERNAME not set",
)


@pytest.fixture(scope="module")
def adapter():
    a = FddbAdapter(
        username=os.environ["FDDB_USERNAME"],
        password=os.environ["FDDB_PASSWORD"],
    )
    a.login()
    return a


@pytest.fixture(scope="module")
def today():
    return datetime.now().strftime("%Y-%m-%d")


@pytest.fixture(scope="module")
def now_dt():
    return datetime.now()


@pytest.fixture(scope="module")
def fetched_at():
    return datetime.now(timezone.utc).isoformat()


@pytest.fixture(scope="module")
def month_envelope(adapter, now_dt):
    return adapter.month_diary(now_dt.month, now_dt.year)


class TestFddbFetch:
    def test_login_and_fetch_month(self, month_envelope):
        assert month_envelope.source == "fddb"
        assert len(month_envelope.payload) > 0

    def test_month_diary_is_html(self, month_envelope):
        assert "<html" in month_envelope.payload.lower()


class TestRawWarehouse:
    def test_raw_write_and_read(
        self, tmp_path, month_envelope, today
    ):
        wh = RawWarehouse(root=tmp_path)
        wh.append(month_envelope, today)

        read_back = wh.read_partition("fddb", today)
        assert len(read_back) == 1
        assert read_back[0].source == "fddb"


class TestCanonicalTransform:
    def test_month_diary_parse(
        self, month_envelope, now_dt, fetched_at
    ):
        days = transform_month_diary(
            month_envelope.payload,
            now_dt.month,
            now_dt.year,
            fetched_at,
        )
        assert isinstance(days, dict)
        # There should be at least some days in the month
        # (might be empty if no diary entries)


class TestProjection:
    def test_fddb_pipeline(
        self,
        tmp_path,
        adapter,
        month_envelope,
        now_dt,
        today,
        fetched_at,
    ):
        days = transform_month_diary(
            month_envelope.payload,
            now_dt.month,
            now_dt.year,
            fetched_at,
        )

        wh = CanonicalWarehouse(root=tmp_path / "data")

        if today in days:
            day_data = days[today]
            if day_data.get("detail_url"):
                detail_env = adapter.day_detail(
                    day_data["detail_url"]
                )
                nutrition_days, meals, meal_items = (
                    transform_day_detail(
                        detail_env.payload,
                        today,
                        fetched_at,
                        day_data,
                    )
                )
                wh.append_many(
                    "nutrition-day", nutrition_days, today
                )
                wh.append_many("meal", meals, today)
                wh.append_many(
                    "meal-item", meal_items, today
                )

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

        builder = ProjectionBuilder(
            db=db, build_root=tmp_path / "build"
        )
        out = builder.build(today)

        assert (out / "status.json").exists()
        status = json.loads(
            (out / "status.json").read_text()
        )
        assert "nutrition" in status
