# -*- coding: utf-8 -*-
"""Unit tests for cross_check_sources — all 6 state cases (ANCHOR-3).

Covers:
- CALLBACK_MISSING (all 4 absent + cron_list False)
- CRON_LIST_AUTODELETED_FIRED (cron_list False + schedule_history present)
- SCHEDULE_HISTORY_PENDING (pending records in schedule_history)
- SOURCE_CROSS_CHECK_PARTIAL (partial sources)
- OWNER_KEY_VERIFIED (all 4 present)
- RESULT_ARTIFACT_SELF_ATTESTED (result_artifact only, no schedule_history/cron_history)
"""
from __future__ import annotations

import pytest

from utils.callback_source_cross_checker import (
    STATE_CALLBACK_MISSING,
    STATE_CRON_LIST_AUTODELETED_FIRED,
    STATE_OWNER_KEY_VERIFIED,
    STATE_RESULT_ARTIFACT_SELF_ATTESTED,
    STATE_SCHEDULE_HISTORY_PENDING,
    STATE_SOURCE_CROSS_CHECK_PARTIAL,
    VERDICT_FAIL,
    VERDICT_PASS,
    cross_check_sources,
)

ANU_KEY = "c119085addb0f8b7"
SELF_KEY = "c38fb9955616e24d"


def _cross_check(**kwargs):
    defaults = dict(
        cron_id="TEST-01",
        schedule_history_records=[],
        cron_history_records={},
        envelope=None,
        result_artifact=None,
        cron_list_present=None,
    )
    defaults.update(kwargs)
    return cross_check_sources(**defaults)


class TestCallbackMissing:
    """All 4 sources absent + cron_list False → CALLBACK_MISSING."""

    def test_all_absent_cron_list_false(self):
        r = _cross_check(cron_list_present=False)
        assert r.state == STATE_CALLBACK_MISSING
        assert r.verdict == VERDICT_FAIL
        assert r.source_count_present == 0
        assert r.source_count_absent == 4

    def test_cron_list_none_not_missing(self):
        """cron_list=None → cannot conclude missing."""
        r = _cross_check(cron_list_present=None)
        assert r.state != STATE_CALLBACK_MISSING


class TestCronListAutodeletedFired:
    """cron_list False + schedule_history present → CRON_LIST_AUTODELETED_FIRED."""

    def test_fired_and_autodeleted(self):
        r = _cross_check(
            schedule_history_records=[{"cron_id": "TEST-01", "status": "fired"}],
            cron_list_present=False,
        )
        assert r.state == STATE_CRON_LIST_AUTODELETED_FIRED
        assert r.verdict == VERDICT_PASS

    def test_fired_takes_priority_over_missing(self):
        """Even with all other sources absent, schedule_history fired beats missing."""
        r = _cross_check(
            schedule_history_records=[{"cron_id": "TEST-01", "status": "fired"}],
            cron_history_records={},
            envelope=None,
            result_artifact=None,
            cron_list_present=False,
        )
        assert r.state == STATE_CRON_LIST_AUTODELETED_FIRED
        assert r.state != STATE_CALLBACK_MISSING


class TestScheduleHistoryPending:
    """Pending records in schedule_history → SCHEDULE_HISTORY_PENDING."""

    @pytest.mark.parametrize("pending_status", ["pending", "scheduled", "queued"])
    def test_pending_status(self, pending_status: str):
        r = _cross_check(
            schedule_history_records=[
                {"cron_id": "TEST-01", "status": pending_status}
            ],
            cron_list_present=False,
        )
        assert r.state == STATE_SCHEDULE_HISTORY_PENDING
        assert r.verdict == VERDICT_PASS

    def test_pending_overrides_cron_list_autodeleted(self):
        """Pending check fires first (before cron-list autodeleted check)."""
        r = _cross_check(
            schedule_history_records=[{"status": "pending"}],
            cron_list_present=False,
        )
        assert r.state == STATE_SCHEDULE_HISTORY_PENDING


class TestSourceCrossCheckPartial:
    """Partial sources → SOURCE_CROSS_CHECK_PARTIAL."""

    def test_only_envelope_present(self):
        r = _cross_check(
            envelope={"collector_key": ANU_KEY},
            cron_list_present=None,
        )
        assert r.state == STATE_SOURCE_CROSS_CHECK_PARTIAL
        assert r.verdict == VERDICT_PASS
        assert r.source_count_present == 1
        assert r.source_count_absent == 3

    def test_only_cron_history_present(self):
        r = _cross_check(
            cron_history_records={ANU_KEY: [{"cron_id": "TEST-01"}]},
            cron_list_present=None,
        )
        assert r.state == STATE_SOURCE_CROSS_CHECK_PARTIAL
        assert r.source_count_present == 1

    def test_three_sources_present(self):
        r = _cross_check(
            schedule_history_records=[{"cron_id": "TEST-01", "status": "fired"}],
            cron_history_records={ANU_KEY: [{"cron_id": "TEST-01"}]},
            envelope={"collector_key": ANU_KEY},
            result_artifact=None,
            cron_list_present=True,
        )
        # 3/4 sources present → PARTIAL (not all 4)
        assert r.state == STATE_SOURCE_CROSS_CHECK_PARTIAL


class TestOwnerKeyVerified:
    """All 4 sources present + actual owner extracted → OWNER_KEY_VERIFIED."""

    def test_all_four_sources_anu_key(self):
        r = _cross_check(
            schedule_history_records=[{"cron_id": "TEST-01", "status": "fired"}],
            cron_history_records={ANU_KEY: [{"cron_id": "TEST-01", "owner_key": ANU_KEY}]},
            envelope={"collector_key": ANU_KEY},
            result_artifact={"schedule_id": "TEST-01", "source": "result"},
            cron_list_present=True,
        )
        assert r.state == STATE_OWNER_KEY_VERIFIED
        assert r.verdict == VERDICT_PASS
        assert r.actual_owner_key == ANU_KEY
        assert r.source_count_present == 4

    def test_actual_owner_key_extracted(self):
        """actual_owner_key is ANU key when ANU key records found."""
        r = _cross_check(
            schedule_history_records=[{"status": "fired"}],
            cron_history_records={ANU_KEY: [{"owner_key": ANU_KEY}], SELF_KEY: []},
            envelope={"collector_key": ANU_KEY},
            result_artifact={"done": True},
        )
        assert r.actual_owner_key == ANU_KEY


class TestResultArtifactSelfAttested:
    """result_artifact only (no schedule_history, no cron_history) → RESULT_ARTIFACT_SELF_ATTESTED."""

    def test_result_only_is_self_attested(self):
        r = _cross_check(
            schedule_history_records=[],
            cron_history_records={ANU_KEY: [], SELF_KEY: []},
            envelope={"collector_key": ANU_KEY},
            result_artifact={"schedule_id": "TEST-01"},
            cron_list_present=None,
        )
        assert r.state == STATE_RESULT_ARTIFACT_SELF_ATTESTED
        assert r.verdict == VERDICT_FAIL

    def test_result_with_envelope_but_no_history(self):
        """envelope present + result_artifact present but no history → still self-attested."""
        r = _cross_check(
            schedule_history_records=[],
            cron_history_records={},
            envelope={"collector_key": ANU_KEY},
            result_artifact={"schedule_id": "TEST-01"},
            cron_list_present=None,
        )
        assert r.state == STATE_RESULT_ARTIFACT_SELF_ATTESTED
        assert r.verdict == VERDICT_FAIL
