"""Tests for tools.confirmation_daemon — Human Confirmation Firewall."""

import pytest
import time
from tools.confirmation_daemon import (
    ConfirmationDaemon,
    ConfirmationRequest,
    ConfirmationStatus,
    RiskLevel,
    classify_action,
    _is_whitelisted,
    _DEFAULT_WHITELIST,
)


class TestClassifyAction:
    """Test action risk classification."""

    def test_crypto_tx_is_critical(self):
        assert classify_action("crypto_tx") == RiskLevel.CRITICAL

    def test_sign_transaction_is_critical(self):
        assert classify_action("sign_transaction") == RiskLevel.CRITICAL

    def test_send_email_is_high(self):
        assert classify_action("send_email") == RiskLevel.HIGH

    def test_send_message_is_medium(self):
        assert classify_action("send_message") == RiskLevel.MEDIUM

    def test_access_calendar_is_low(self):
        assert classify_action("access_calendar") == RiskLevel.LOW

    def test_unknown_action_is_medium(self):
        assert classify_action("unknown_action_xyz") == RiskLevel.MEDIUM


class TestWhitelist:
    """Test whitelist auto-approval."""

    def test_self_email_is_whitelisted(self):
        whitelist = dict(_DEFAULT_WHITELIST)
        payload = {"from": "me@test.com", "to": "me@test.com"}
        assert _is_whitelisted("send_email", payload, whitelist) is True

    def test_non_whitelisted_recipient_not_approved(self):
        whitelist = dict(_DEFAULT_WHITELIST)
        payload = {"to": "random@stranger.com"}
        assert _is_whitelisted("send_email", payload, whitelist) is False

    def test_whitelisted_contact_approved(self):
        whitelist = {
            "send_message": {"targets": ["alice", "bob"]},
        }
        assert _is_whitelisted("send_message", {"to": "alice"}, whitelist) is True
        assert _is_whitelisted("send_message", {"to": "charlie"}, whitelist) is False

    def test_no_whitelist_entry_means_not_whitelisted(self):
        whitelist = {}
        assert _is_whitelisted("crypto_tx", {"amount": 1.0}, whitelist) is False


class TestConfirmationRequest:
    """Test the request data model."""

    def test_defaults(self):
        req = ConfirmationRequest(
            request_id="test-1",
            action="send_email",
            description="Test email",
            risk_level="high",
            payload={},
        )
        assert req.status == ConfirmationStatus.PENDING.value
        assert req.created_at > 0
        assert req.expires_at > req.created_at

    def test_is_pending(self):
        req = ConfirmationRequest(
            request_id="test-2",
            action="send_email",
            description="Test",
            risk_level="high",
            payload={},
            expires_at=time.time() + 300,
        )
        assert req.is_pending is True

    def test_is_expired(self):
        req = ConfirmationRequest(
            request_id="test-3",
            action="send_email",
            description="Test",
            risk_level="high",
            payload={},
            expires_at=time.time() - 10,
        )
        assert req.is_expired is True
        assert req.is_pending is False

    def test_to_dict(self):
        req = ConfirmationRequest(
            request_id="test-4",
            action="send_email",
            description="Test",
            risk_level="medium",
            payload={"to": "a@b.com"},
        )
        d = req.to_dict()
        assert d["request_id"] == "test-4"
        assert d["action"] == "send_email"
        assert "is_pending" in d


class TestConfirmationDaemon:
    """Test the daemon logic (without HTTP layer)."""

    def test_auto_approve_low_risk(self):
        daemon = ConfirmationDaemon()
        req = daemon.request(
            action="access_calendar",
            description="Read today's events",
            risk_level="low",
        )
        assert req.status == ConfirmationStatus.AUTO_APPROVED.value

    def test_whitelisted_auto_approves(self):
        daemon = ConfirmationDaemon()
        daemon._whitelist = {"send_message": {"targets": ["alice"]}}
        req = daemon.request(
            action="send_message",
            description="Message alice",
            payload={"to": "alice"},
        )
        assert req.status == ConfirmationStatus.AUTO_APPROVED.value

    def test_non_whitelisted_goes_pending(self):
        daemon = ConfirmationDaemon()
        daemon._whitelist = {}
        req = daemon.request(
            action="send_email",
            description="Email to stranger",
            payload={"to": "stranger@test.com"},
            risk_level="high",
        )
        assert req.status == ConfirmationStatus.PENDING.value
        assert req.is_pending is True

    def test_approve_response(self):
        daemon = ConfirmationDaemon()
        daemon._whitelist = {}
        req = daemon.request(
            action="send_email",
            description="Email test",
            risk_level="high",
        )
        result = daemon.respond(req.request_id, approved=True, decided_by="human")
        assert result.status == ConfirmationStatus.APPROVED.value
        assert result.decided_by == "human"

    def test_deny_response(self):
        daemon = ConfirmationDaemon()
        daemon._whitelist = {}
        req = daemon.request(
            action="crypto_tx",
            description="Send 1 ETH",
            risk_level="critical",
        )
        result = daemon.respond(
            req.request_id, approved=False, decided_by="human", reason="Too risky"
        )
        assert result.status == ConfirmationStatus.DENIED.value
        assert result.reason == "Too risky"

    def test_get_pending(self):
        daemon = ConfirmationDaemon()
        daemon._whitelist = {}
        daemon.request(action="send_email", description="Test 1", risk_level="high")
        daemon.request(action="send_email", description="Test 2", risk_level="high")
        pending = daemon.get_pending()
        assert len(pending) >= 2

    def test_get_history(self):
        daemon = ConfirmationDaemon()
        req = daemon.request(
            action="access_calendar", description="Test", risk_level="low"
        )
        history = daemon.get_history()
        assert len(history) >= 1
        assert history[0]["action"] == "access_calendar"
