from datetime import UTC, datetime, timedelta
from uuid import uuid4

import pytest
from app.approvals import ApprovalStatus, decide_approval, make_approval


def approval_fixture():
    now = datetime(2026, 8, 25, 12, tzinfo=UTC)
    payload = {"recipient": "Ahmed", "content": "I will call after 4 PM"}
    approval = make_approval(id=uuid4(), workspace_id=uuid4(), action_id=uuid4(),
                             permission="whatsapp.send", payload=payload,
                             expires_at=now + timedelta(minutes=10))
    return approval, payload, now


def test_exact_payload_can_be_approved_once():
    approval, payload, now = approval_fixture()
    decided = decide_approval(approval, payload=payload, workspace_id=approval.workspace_id,
                              approver_user_id=uuid4(),
                              approver_permissions={"approvals.approve"}, approve=True, now=now)
    assert decided.status == ApprovalStatus.APPROVED
    with pytest.raises(ValueError, match="already been decided"):
        decide_approval(decided, payload=payload, workspace_id=approval.workspace_id,
                        approver_user_id=uuid4(),
                        approver_permissions={"approvals.approve"}, approve=True, now=now)


def test_tampered_payload_is_rejected():
    approval, payload, now = approval_fixture()
    payload["content"] = "Send bank details"
    with pytest.raises(ValueError, match="does not match"):
        decide_approval(approval, payload=payload, workspace_id=approval.workspace_id,
                        approver_user_id=uuid4(),
                        approver_permissions={"approvals.approve"}, approve=True, now=now)


def test_cross_workspace_and_missing_permission_are_denied():
    approval, payload, now = approval_fixture()
    with pytest.raises(PermissionError, match="another workspace"):
        decide_approval(approval, payload=payload, workspace_id=uuid4(),
                        approver_user_id=uuid4(),
                        approver_permissions={"approvals.approve"}, approve=True, now=now)
    with pytest.raises(PermissionError, match="lacks"):
        decide_approval(approval, payload=payload, workspace_id=approval.workspace_id,
                        approver_user_id=uuid4(), approver_permissions=set(),
                        approve=True, now=now)


def test_expired_approval_cannot_execute():
    approval, payload, now = approval_fixture()
    decided = decide_approval(approval, payload=payload, workspace_id=approval.workspace_id,
                              approver_user_id=uuid4(),
                              approver_permissions={"approvals.approve"}, approve=True,
                              now=now + timedelta(minutes=11))
    assert decided.status == ApprovalStatus.EXPIRED
    assert decided.decided_by_user_id is None
