# -*- coding: utf-8 -*-
"""Regression: envelope=ANU but actual=self-key → OWNER_KEY_MISMATCH FAIL (ANCHOR-1).

Fixture used: 3 (envelope_anu_actual_self_mismatch).
Verifies that ENVELOPE_ACTUAL_MISMATCH is detected and rejected.
"""
from __future__ import annotations

import json
from pathlib import Path

import pytest

from utils.callback_authority_validator import (
    FAIL,
    STATE_OWNER_KEY_MISMATCH,
    validate_authority,
)
from utils.callback_registration import (
    ANU_KEY,
    VERDICT_FAIL,
    register_callback,
    verify_actual_owner,
)

FIXTURE_DIR = Path(__file__).parent.parent.parent / "fixtures" / "callback_authority_gate"
EXECUTOR_KEY = "c38fb9955616e24d"


def load_fixture(name: str) -> tuple[dict, dict]:
    base = FIXTURE_DIR / name
    return (
        json.loads((base / "evidence.json").read_text()),
        json.loads((base / "expected.json").read_text()),
    )


class TestFixture03EnvelopeMismatch:
    """fixture_03: envelope=ANU but actual=self-key → NON_AUTHORITATIVE_SELF_COLLECTOR.

    When actual_owner_key == executor_key, Rule 1 (ANCHOR-5 self-key) fires first
    regardless of the envelope. The ENVELOPE_ACTUAL_MISMATCH reason is also
    included (ANCHOR-1) since envelope=ANU but actual=self-key.
    """

    def test_state_is_non_authoritative_self_collector(self):
        evidence, expected = load_fixture(
            "fixture_03_envelope_anu_actual_self_mismatch"
        )
        verdict = validate_authority(
            envelope_collector_key=evidence["envelope"]["collector_key"],
            actual_owner_key=evidence["observed_owner_key"],
            executor_key=evidence["executor_key"],
        )
        assert verdict.state == expected["state"], (
            f"expected {expected['state']!r}, got {verdict.state!r}"
        )
        assert verdict.verdict == expected["verdict"]
        assert verdict.authority_marker == expected["authority_marker"]

    def test_envelope_actual_mismatch_reason_present(self):
        """ANCHOR-1: ENVELOPE_ACTUAL_MISMATCH reason must appear when envelope=ANU but actual=self-key."""
        evidence, _ = load_fixture("fixture_03_envelope_anu_actual_self_mismatch")
        verdict = validate_authority(
            envelope_collector_key=evidence["envelope"]["collector_key"],
            actual_owner_key=evidence["observed_owner_key"],
            executor_key=evidence["executor_key"],
        )
        reasons_text = " ".join(verdict.reasons)
        # Rule 1 (self-key) fires first; when envelope=ANU, ENVELOPE_ACTUAL_MISMATCH
        # is also included in the reasons (ANCHOR-1).
        assert "ENVELOPE_ACTUAL_MISMATCH" in reasons_text, (
            f"Expected ENVELOPE_ACTUAL_MISMATCH in reasons, got: {verdict.reasons}"
        )

    def test_validate_authority_directly(self):
        """Direct test: envelope=ANU but actual=self-key.
        actual == executor → NON_AUTHORITATIVE_SELF_COLLECTOR (ANCHOR-5 Rule 1 fires first).
        ENVELOPE_ACTUAL_MISMATCH reason also present (ANCHOR-1).
        """
        verdict = validate_authority(
            envelope_collector_key=ANU_KEY,
            actual_owner_key=EXECUTOR_KEY,
            executor_key=EXECUTOR_KEY,
        )
        assert verdict.verdict == FAIL

    def test_envelope_anu_actual_non_anu_non_self(self):
        """envelope=ANU, actual=non-ANU non-self-key → OWNER_KEY_MISMATCH."""
        verdict = validate_authority(
            envelope_collector_key=ANU_KEY,
            actual_owner_key="some-other-key-not-anu",
            executor_key=EXECUTOR_KEY,
        )
        assert verdict.verdict == FAIL
        assert verdict.state == STATE_OWNER_KEY_MISMATCH
        reasons_text = " ".join(verdict.reasons)
        assert "ENVELOPE_ACTUAL_MISMATCH" in reasons_text


class TestVerifyActualOwnerMismatch:
    """verify_actual_owner with mismatch → FAIL."""

    def test_verify_with_self_key_observed(self):
        """Register with ANU owner, but actual observed = self-key → mismatch."""
        rr = register_callback(
            kind="normal",
            task_id="task-mismatch-test",
            executor_key=EXECUTOR_KEY,
            owner_key=ANU_KEY,
            chat_id="chat-m",
            prompt="task_id=task-mismatch-test\nowner_key=c119085addb0f8b7\n",
            at="10m",
            dispatch_path=True,
            direct_cron_path=False,
            require_envelope=False,
        )
        verified = verify_actual_owner(
            registration_result=rr,
            observed_owner_key=EXECUTOR_KEY,  # self-key mismatch
            observed_chat_id="chat-m",
            observed_role="SELF",
        )
        assert verified.verdict == VERDICT_FAIL
        assert "MISMATCH" in verified.state or "NON_AUTHORITATIVE" in verified.state
        reasons_text = " ".join(verified.reasons)
        assert "MISMATCH" in reasons_text
