from datetime import datetime, timedelta, timezone

from services.pchome_sales_source_reconciliation import build_source_reconciliation


NOW = datetime(2026, 7, 14, 18, 30, tzinfo=timezone(timedelta(hours=8)))


def _source(source_id, *, enabled=True, ready=True, status="ready"):
    return {
        "id": source_id,
        "enabled": enabled,
        "ready": ready,
        "status": status,
    }


def _receipt(provider, *, completed_at, reconciliation=None):
    stages = {"providers": [provider]}
    if reconciliation:
        stages["source_reconciliation"] = reconciliation
    return {
        "status": "blocked_with_safe_next_action",
        "completed_at": completed_at,
        "stages": stages,
    }


def test_stale_single_source_schedules_retry_and_reports_fallback_gap():
    payload = build_source_reconciliation(
        sources=[
            _source("google_drive"),
            _source("authorized_https", enabled=False, ready=False, status="disabled"),
        ],
        provider_attempts=[
            {"source": "google_drive", "status": "upstream_stale", "file_count": 0},
            {"source": "authorized_https", "status": "disabled"},
        ],
        prior_receipts=[],
        freshness={"latest_sales_date": "2026-06-24", "data_lag_days": 20, "decision_ready": False},
        now=NOW,
    )

    assert payload["contract"] == "pchome_sales_source_reconciliation_v1"
    assert payload["status"] == "degraded"
    assert payload["fallback_chain"] == ["google_drive"]
    assert payload["single_source_dependency"] is True
    assert payload["next_retry_at"] == "2026-07-14T19:00:00+08:00"
    assert payload["safe_next_action"] == "scheduled_retry_and_enabled_fallback_probe"
    assert payload["notification_policy"]["severity"] == "critical"
    assert payload["notification_policy"]["send"] is True
    assert payload["sources"][0]["consecutive_empty_runs"] == 1
    assert payload["sources"][1]["runtime_state"] == "disabled"


def test_arrival_sla_grace_closes_freshness_without_false_alert():
    payload = build_source_reconciliation(
        sources=[_source("google_drive")],
        provider_attempts=[{"source": "google_drive", "status": "no_pending_file"}],
        prior_receipts=[],
        freshness={
            "contract_version": "pchome_sales_freshness_sla_v1",
            "latest_sales_date": "2026-07-13",
            "data_lag_days": 2,
            "sla_lag_days": 0,
            "expected_latest_sales_date": "2026-07-13",
            "grace_period_active": True,
            "decision_ready": True,
        },
        now=NOW,
    )

    assert payload["status"] == "closed"
    assert payload["safe_next_action"] == "none"
    assert payload["notification_policy"]["severity"] == "info"
    assert payload["notification_policy"]["send"] is False


def test_same_state_within_cooldown_suppresses_duplicate_notification():
    first = build_source_reconciliation(
        sources=[_source("google_drive")],
        provider_attempts=[{"source": "google_drive", "status": "upstream_stale"}],
        prior_receipts=[],
        freshness={"data_lag_days": 20, "decision_ready": False},
        now=NOW - timedelta(minutes=10),
    )
    history = [_receipt(
        {"source": "google_drive", "status": "upstream_stale"},
        completed_at=(NOW - timedelta(minutes=10)).isoformat(),
        reconciliation=first,
    )]

    second = build_source_reconciliation(
        sources=[_source("google_drive")],
        provider_attempts=[{"source": "google_drive", "status": "upstream_stale"}],
        prior_receipts=history,
        freshness={"data_lag_days": 20, "decision_ready": False},
        now=NOW,
    )

    assert second["notification_policy"]["fingerprint"] == first["notification_policy"]["fingerprint"]
    assert second["notification_policy"]["send"] is False
    assert second["notification_policy"]["reason"] == "duplicate_within_cooldown"
    assert second["sources"][0]["consecutive_empty_runs"] == 2


def test_provider_failures_use_bounded_exponential_backoff():
    failed = {"source": "authorized_https", "status": "failed", "error_kind": "http_fetch_failed"}
    history = [
        _receipt(failed, completed_at=(NOW - timedelta(minutes=30)).isoformat()),
        _receipt(failed, completed_at=(NOW - timedelta(minutes=60)).isoformat()),
    ]

    payload = build_source_reconciliation(
        sources=[_source("authorized_https")],
        provider_attempts=[failed],
        prior_receipts=history,
        freshness={"data_lag_days": 5, "decision_ready": False},
        now=NOW,
        retry_interval_minutes=30,
        max_failure_backoff_minutes=240,
    )

    source = payload["sources"][0]
    assert source["runtime_state"] == "failed"
    assert source["consecutive_failure_runs"] == 3
    assert source["retry_minutes"] == 120
    assert source["next_retry_at"] == "2026-07-14T20:30:00+08:00"
    assert source["action"] == "retry_with_bounded_backoff_and_probe_fallback"


def test_duplicate_source_remains_on_scheduled_retry_without_writing():
    payload = build_source_reconciliation(
        sources=[_source("google_drive")],
        provider_attempts=[{
            "source": "google_drive",
            "status": "duplicate",
            "duplicate_count": 1,
        }],
        prior_receipts=[],
        freshness={"data_lag_days": 10, "decision_ready": False},
        now=NOW,
    )

    source = payload["sources"][0]
    assert source["runtime_state"] == "duplicate"
    assert source["retry_minutes"] == 30
    assert source["next_retry_at"] == "2026-07-14T19:00:00+08:00"
    assert payload["safe_next_action"] == "scheduled_retry_and_enabled_fallback_probe"
