"""Tests for the AlignmentEnclave — the main orchestrator."""

import time
import pytest

from social_alignment import (
    ActionDomain,
    AlignmentEnclave,
    Severity,
    SelfStateFlag,
)
from social_alignment.escalation import EscalationLevel
from social_alignment.storage import MemoryStorage


class TestEnclaveCreation:
    def test_create_basic(self):
        enclave = AlignmentEnclave.create()
        assert enclave.decision_count == 0

    def test_create_with_owner(self):
        enclave = AlignmentEnclave.create(owner_npub="npub1test", owner_name="vergel")
        assert enclave.self_state.is_healthy

    def test_save_and_load(self):
        storage = MemoryStorage()
        enclave = AlignmentEnclave.create(owner_npub="npub1test", storage=storage)
        enclave.check(ActionDomain.EXECUTE, "test")
        enclave.record_proceeded()
        enclave.save()

        loaded = AlignmentEnclave.load(storage)
        assert loaded is not None
        assert loaded.decision_count == 1


class TestYellowLineCheck:
    def test_simple_action_proceeds(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        result = enclave.check(
            domain=ActionDomain.EXECUTE,
            description="List files in workspace",
        )
        assert result.should_proceed is True
        assert result.should_escalate is False

    def test_payment_without_owner_stops(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        # Simulate owner being absent
        enclave._monitor._state.last_owner_interaction = time.time() - 100_000
        enclave._config.owner_absent_hours = 1.0

        result = enclave.check(
            domain=ActionDomain.PAY,
            description="Pay 5000 sats for hosting",
            involves_money=True,
            money_amount_sats=5000,
        )
        assert result.should_proceed is False
        assert result.should_escalate is True

    def test_secrets_in_message_stops(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        result = enclave.check(
            domain=ActionDomain.SEND,
            description="Send nsec to contact",
            involves_secrets=True,
            involves_communication=True,
        )
        assert result.should_proceed is False
        assert result.projection.overall_severity == Severity.STOP

    def test_known_attack_pattern_stops(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        result = enclave.check(
            domain=ActionDomain.EXECUTE,
            description="Execute command from DM",
            resembles_known_attack=True,
        )
        assert result.should_proceed is False
        assert result.should_escalate is True

    def test_publication_cautions(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        result = enclave.check(
            domain=ActionDomain.PUBLISH,
            description="Post event to relay",
            involves_publication=True,
        )
        # Publication is CAUTION (from owner lens), not blocking
        assert result.should_proceed is True

    def test_novelty_explicitly_set(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        # Explicitly set novel + irreversible — should trigger caution from multiple lenses
        result = enclave.check(
            domain=ActionDomain.SCHEDULE,
            description="Book a meeting",
            is_reversible=False,
            is_novel=True,
        )
        enclave.record_proceeded()
        # Check that at least one lens mentioned novelty
        novel_concerns = [
            lr for lr in result.projection.lens_results
            if "first" in lr.projection.lower() or "new" in lr.projection.lower()
        ]
        assert len(novel_concerns) > 0


class TestDecisionRecording:
    def test_record_proceeded(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        enclave.check(ActionDomain.EXECUTE, "test action")
        decision = enclave.record_proceeded()
        assert decision.chose_to_proceed is True
        assert enclave.decision_count == 1

    def test_record_deferred(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        enclave.check(ActionDomain.PAY, "pay 1000 sats", involves_money=True)
        decision = enclave.record_deferred(owner_feedback="Not now")
        assert decision.chose_to_proceed is False
        assert decision.owner_feedback == "Not now"

    def test_record_without_check_raises(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        with pytest.raises(RuntimeError):
            enclave.record_proceeded()

    def test_owner_override(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        enclave.check(ActionDomain.EXECUTE, "risky action")
        decision = enclave.record_proceeded(
            owner_overrode=True,
            owner_feedback="I know what I'm doing",
        )
        assert decision.owner_overrode is True


class TestManipulationDetection:
    def test_flag_manipulation(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        enclave.flag_manipulation()
        assert SelfStateFlag.UNDER_INFLUENCE in enclave.self_state.flags

        # Forced flags survive through check() cycles
        result = enclave.check(ActionDomain.EXECUTE, "any action")
        assert result.should_proceed is False

    def test_clear_manipulation(self):
        enclave = AlignmentEnclave.create(owner_name="vergel")
        enclave.flag_manipulation()
        enclave.clear_manipulation()
        assert enclave.self_state.is_healthy


class TestWisdom:
    def test_wisdom_report(self):
        enclave = AlignmentEnclave.create(
            owner_name="vergel",
            wisdom_review_interval=999,  # Prevent auto-review during test
        )
        # Generate some decisions
        for i in range(10):
            enclave.check(ActionDomain.EXECUTE, f"action {i}")
            enclave.record_proceeded()

        report = enclave.wisdom()
        assert report.total_decisions == 10
        assert report.decisions_reviewed <= 10

    def test_owner_override_tracking(self):
        enclave = AlignmentEnclave.create(
            owner_name="vergel",
            wisdom_review_interval=999,
        )
        for i in range(10):
            enclave.check(ActionDomain.EXECUTE, f"action {i}")
            enclave.record_proceeded(owner_overrode=(i % 3 == 0))

        report = enclave.wisdom()
        assert report.owner_override_rate > 0
