from dataclasses import dataclass
from datetime import UTC, datetime
from pathlib import Path

from home_agent.contracts.types import (
    Alert,
    Item,
    ItemKind,
    LLMResult,
    LLMUsage,
    RetrievedMatch,
    UrgencyDecision,
    UrgencyLabel,
)
from home_agent.core.config import (
    AlertsConfig,
    AppConfig,
    BudgetConfig,
    LLMConfig,
    MemoryConfig,
    PollConfig,
    RetentionConfig,
)
from home_agent.memory.engine import ScopedMemoryEngine
from home_agent.orchestrator.service import Orchestrator
from home_agent.storage.sqlite_store import SqliteStore


@dataclass
class FakeMailReader:
    def list_recent(self) -> list[Item]:
        return [
            Item(
                provider="fake-mail",
                external_id="m1",
                kind=ItemKind.EMAIL,
                received_at=datetime.now(tz=UTC),
                subject="urgent notice",
                sender="ops@example.com",
                metadata={},
            )
        ]

    def search(self, query: str) -> list[Item]:
        _ = query
        return []

    def get_message(self, external_id: str) -> Item | None:
        _ = external_id
        return None


@dataclass
class FakePlugin:
    id: str = "fake"
    version: str = "1.0"

    def get_mail_reader(self) -> FakeMailReader:
        return FakeMailReader()

    def get_calendar_reader(self) -> None:
        return None


@dataclass
class FakeNotifier:
    def notify(self, alert: Alert) -> None:
        _ = alert


class FakeLLMRunner:
    def classify(
        self, item: Item, retrieved_matches: list[RetrievedMatch] | None = None
    ) -> LLMResult:
        _ = retrieved_matches
        _ = item
        return LLMResult(
            decision=UrgencyDecision(
                score=0.95,
                label=UrgencyLabel.CRITICAL,
                reasons=["test"],
                used_llm=True,
            ),
            usage=LLMUsage(
                provider="claude",
                model="test-model",
                total_cost_usd=0.25,
                input_tokens=10,
                output_tokens=5,
                raw={"total_cost_usd": 0.25},
            ),
            raw_response={},
        )


def test_orchestrator_persists_llm_usage(tmp_path: Path) -> None:
    cfg = AppConfig(
        poll=PollConfig(interval_minutes=15),
        budget=BudgetConfig(monthly_cap_usd=10.0),
        retention=RetentionConfig(days=30),
        alerts=AlertsConfig(auto_launch_terminal=False),
        llm=LLMConfig(),
        memory=MemoryConfig(),
        enabled_providers=["fake"],
        sqlite_path=tmp_path / "agent.db",
        daily_digest_enabled=True,
    )
    store = SqliteStore(cfg.sqlite_path)
    orchestrator = Orchestrator(
        config=cfg,
        plugins=[FakePlugin()],
        store=store,
        llm_runner=FakeLLMRunner(),
        notifier=FakeNotifier(),
        memory_engine=ScopedMemoryEngine(),
    )

    orchestrator.run_once()

    spend, _ = store.get_month_spend("9999-01", hard_cap_usd=10.0)
    assert spend == 0.0

    # query current month spend via helper logic
    now_key = datetime.now(tz=UTC).strftime("%Y-%m")
    month_spend, _ = store.get_month_spend(now_key, hard_cap_usd=10.0)
    assert month_spend >= 0.25
