"""Tests for social_alignment types."""

from social_alignment.types import (
    AlignmentConfig,
    Decision,
    Lens,
    LensResult,
    LENS_ORDER,
    Projection,
    ActionDomain,
    SelfState,
    SelfStateFlag,
    Severity,
    SEVERITY_ORDER,
)


def test_lens_order():
    assert len(LENS_ORDER) == 5
    assert LENS_ORDER[0] == Lens.BUILDER
    assert LENS_ORDER[-1] == Lens.PARTNERSHIP


def test_severity_order():
    assert SEVERITY_ORDER[0] == Severity.CLEAR
    assert SEVERITY_ORDER[-1] == Severity.STOP


def test_lens_result_blocking():
    clear = LensResult(Lens.BUILDER, Severity.CLEAR, "ok", "", "")
    caution = LensResult(Lens.OWNER, Severity.CAUTION, "hmm", "note", "")
    yield_ = LensResult(Lens.DEFENSE, Severity.YIELD, "wait", "concern", "fix")
    stop = LensResult(Lens.SOVEREIGN, Severity.STOP, "no", "danger", "halt")

    assert not clear.is_blocking
    assert not caution.is_blocking
    assert yield_.is_blocking
    assert stop.is_blocking


def test_lens_result_roundtrip():
    lr = LensResult(Lens.DEFENSE, Severity.YIELD, "proj", "concern", "suggest")
    d = lr.to_dict()
    restored = LensResult.from_dict(d)
    assert restored.lens == lr.lens
    assert restored.severity == lr.severity
    assert restored.projection == lr.projection


def test_projection_summary():
    lr = LensResult(Lens.BUILDER, Severity.CLEAR, "ok", "", "")
    proj = Projection(
        action_domain=ActionDomain.PAY,
        action_description="Pay 100 sats",
        lens_results=(lr,) * 5,
        overall_severity=Severity.CLEAR,
        should_proceed=True,
        should_escalate=False,
        rationale="All clear",
    )
    summary = proj.summary()
    assert "CLEAR" in summary
    assert "pay" in summary.lower()
    assert "5/5 clear" in summary


def test_projection_roundtrip():
    lr = LensResult(Lens.OWNER, Severity.CAUTION, "pub", "visible", "review")
    proj = Projection(
        action_domain=ActionDomain.PUBLISH,
        action_description="Post to relay",
        lens_results=(lr,),
        overall_severity=Severity.CAUTION,
        should_proceed=True,
        should_escalate=False,
        rationale="Caution noted",
    )
    d = proj.to_dict()
    restored = Projection.from_dict(d)
    assert restored.action_domain == ActionDomain.PUBLISH
    assert restored.overall_severity == Severity.CAUTION
    assert len(restored.lens_results) == 1


def test_decision_record_outcome():
    lr = LensResult(Lens.BUILDER, Severity.CLEAR, "ok", "", "")
    proj = Projection(
        action_domain=ActionDomain.EXECUTE,
        action_description="Run script",
        lens_results=(lr,),
        overall_severity=Severity.CLEAR,
        should_proceed=True,
        should_escalate=False,
        rationale="Clear",
    )
    dec = Decision(projection=proj, chose_to_proceed=True)
    assert dec.actual_outcome is None

    updated = dec.record_outcome("Script ran successfully", True, "Matched expectations")
    assert updated.actual_outcome == "Script ran successfully"
    assert updated.outcome_matched is True
    assert updated.reflection == "Matched expectations"
    # Original is unchanged (frozen)
    assert dec.actual_outcome is None


def test_decision_roundtrip():
    lr = LensResult(Lens.BUILDER, Severity.CLEAR, "ok", "", "")
    proj = Projection(
        action_domain=ActionDomain.SIGN,
        action_description="Sign event",
        lens_results=(lr,),
        overall_severity=Severity.CLEAR,
        should_proceed=True,
        should_escalate=False,
        rationale="Clear",
    )
    dec = Decision(projection=proj, chose_to_proceed=True, owner_overrode=True)
    d = dec.to_dict()
    restored = Decision.from_dict(d)
    assert restored.chose_to_proceed is True
    assert restored.owner_overrode is True


def test_self_state_healthy():
    state = SelfState()
    assert state.is_healthy
    assert not state.is_degraded
    assert "nominal" in state.degradation_summary


def test_self_state_degraded():
    state = SelfState(flags=[SelfStateFlag.STALE_CONTEXT, SelfStateFlag.TOOL_DEGRADED])
    assert not state.is_healthy
    assert state.is_degraded
    assert "stale_context" in state.degradation_summary


def test_self_state_should_defer():
    state = SelfState(flags=[SelfStateFlag.UNDER_INFLUENCE])
    assert state.should_defer()

    healthy = SelfState()
    assert not healthy.should_defer()


def test_self_state_average_confidence():
    state = SelfState(confidence_trend=[0.8, 0.7, 0.9, 0.6])
    avg = state.average_confidence()
    assert 0.74 < avg < 0.76


def test_self_state_roundtrip():
    state = SelfState(
        flags=[SelfStateFlag.RAPID_DECISIONS],
        context_age_seconds=120.0,
        tool_health={"relay": True, "wallet": False},
    )
    d = state.to_dict()
    restored = SelfState.from_dict(d)
    assert SelfStateFlag.RAPID_DECISIONS in restored.flags
    assert restored.tool_health["wallet"] is False


def test_alignment_config_defaults():
    config = AlignmentConfig()
    assert config.escalate_on_stop is True
    assert config.max_decisions_per_minute == 5
    assert config.confidence_floor == 0.3


def test_alignment_config_roundtrip():
    config = AlignmentConfig(owner_npub="npub1test", owner_name="vergel")
    d = config.to_dict()
    restored = AlignmentConfig.from_dict(d)
    assert restored.owner_npub == "npub1test"
    assert restored.owner_name == "vergel"
