from __future__ import annotations

from pathlib import Path

from canonical_layer.features import FeatureService
from canonical_layer.models import CanonicalEntity, EntityLink
from canonical_layer.store import CanonicalStore
from config.settings import OneCSettings


def _build_settings(db_url: str) -> OneCSettings:
    return OneCSettings(
        base_url="http://localhost",
        infobase="buh_test",
        username="",
        password="",
        odata_path="/odata/standard.odata/",
        timeout=30,
        verify_tls=False,
        probe_top=5,
        probe_entity_sets=(),
        canonical_db_url=db_url,
        refresh_default_limit_per_set=50,
        refresh_default_entity_keywords=("document", "posting"),
        feature_default_baseline_window_hours=24,
        anomaly_stale_refresh_threshold_hours=6,
        feature_entity_scan_limit=200000,
        risk_medium_threshold=0.45,
        risk_high_threshold=0.75,
        risk_anomaly_scan_limit=5000,
    )


def _seed_entities(store: CanonicalStore) -> None:
    links = [
        EntityLink(
            relation="reference",
            target_entity="Counterparty",
            target_id=f"cp-{idx}",
            source_field="Counterparty_Key",
        )
        for idx in range(12)
    ]
    entities = [
        CanonicalEntity(
            source_entity="DocumentSales",
            source_id="doc-001",
            display_name="Invoice 001",
            attributes={"Amount": 1000},
            links=links,
        ),
        CanonicalEntity(
            source_entity="DocumentSales",
            source_id="doc-002",
            display_name="Invoice 002",
            attributes={"Amount": 500},
            links=[],
        ),
    ]
    store.upsert_entities(run_id="seed", entities=entities)


def test_feature_engine_generates_metrics_and_anomalies(tmp_path: Path) -> None:
    db_url = f"sqlite:///{(tmp_path / 'feature_engine.db').as_posix()}"
    settings = _build_settings(db_url)
    store = CanonicalStore(settings.canonical_db_url)
    store.ensure_created()
    _seed_entities(store)

    refresh_run_id = store.start_refresh_run(
        mode="incremental",
        requested_entity_sets=["DocumentSales"],
        date_from=None,
        date_to=None,
        limit_per_set=10,
    )
    store.finish_refresh_run(
        run_id=refresh_run_id,
        status="success",
        records_read=2,
        entities_written=2,
        links_written=12,
        checkpoints_updated=1,
        details={},
    )

    service = FeatureService(settings=settings, store=store)
    result = service.run_feature_engine(top_account_tokens=10)

    assert result.status == "success"
    assert result.metrics_written > 0
    assert result.anomalies_written > 0

    anomalies = service.list_anomalies(limit=100, active_only=True)
    signal_types = {item["signal_type"] for item in anomalies}
    assert "high_link_degree" in signal_types


def test_feature_engine_detects_missing_refresh_baseline(tmp_path: Path) -> None:
    db_url = f"sqlite:///{(tmp_path / 'feature_engine_no_refresh.db').as_posix()}"
    settings = _build_settings(db_url)
    store = CanonicalStore(settings.canonical_db_url)
    store.ensure_created()
    _seed_entities(store)

    service = FeatureService(settings=settings, store=store)
    result = service.run_feature_engine(top_account_tokens=10)

    assert result.status == "success"
    anomalies = service.list_anomalies(limit=100, active_only=True)
    signal_types = {item["signal_type"] for item in anomalies}
    assert "missing_refresh_baseline" in signal_types
