"""Tests for unified webhook verification."""

import hashlib
import hmac
import json
import time

import pytest

from primitif import verify_webhook, InvalidSignature


def _sign_mail(secret: str, timestamp: str, body: str) -> str:
    message = f"{timestamp}.{body}"
    sig = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
    return f"sha256={sig}"


def _sign_approval(secret: str, body: bytes) -> str:
    return hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()


def test_mail_webhook_valid():
    secret = "whsec_test123"
    payload = {"event": "message.received", "data": {"id": "msg_abc"}}
    body = json.dumps(payload)
    ts = str(int(time.time()))
    sig = _sign_mail(secret, ts, body)

    result = verify_webhook(secret=secret, signature=sig, body=body, timestamp=ts)
    assert result == payload


def test_mail_webhook_invalid_signature():
    secret = "whsec_test123"
    body = json.dumps({"event": "test"})
    ts = str(int(time.time()))

    with pytest.raises(InvalidSignature, match="Signature mismatch"):
        verify_webhook(secret=secret, signature="sha256=bad", body=body, timestamp=ts)


def test_mail_webhook_expired_timestamp():
    secret = "whsec_test123"
    body = json.dumps({"event": "test"})
    ts = str(int(time.time()) - 600)
    sig = _sign_mail(secret, ts, body)

    with pytest.raises(InvalidSignature, match="Timestamp too old"):
        verify_webhook(secret=secret, signature=sig, body=body, timestamp=ts)


def test_mail_webhook_tolerance_disabled():
    secret = "whsec_test123"
    payload = {"event": "test"}
    body = json.dumps(payload)
    ts = str(int(time.time()) - 9999)
    sig = _sign_mail(secret, ts, body)

    result = verify_webhook(secret=secret, signature=sig, body=body, timestamp=ts, tolerance=0)
    assert result == payload


def test_approval_webhook_valid():
    secret = "proj_secret_abc"
    payload = {"event": "request.approved", "data": {"id": "ar_123"}}
    body = json.dumps(payload).encode()
    sig = _sign_approval(secret, body)

    result = verify_webhook(secret=secret, signature=sig, body=body)
    assert result == payload


def test_approval_webhook_invalid():
    secret = "proj_secret_abc"
    body = json.dumps({"event": "test"}).encode()

    with pytest.raises(InvalidSignature, match="Signature mismatch"):
        verify_webhook(secret=secret, signature="bad", body=body)


def test_body_as_bytes():
    secret = "test_secret"
    payload = {"key": "value"}
    body = json.dumps(payload).encode()
    ts = str(int(time.time()))
    message = f"{ts}.{body.decode()}"
    sig = "sha256=" + hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()

    result = verify_webhook(secret=secret, signature=sig, body=body, timestamp=ts)
    assert result == payload


def test_empty_signature_raises():
    with pytest.raises(InvalidSignature, match="Missing signature"):
        verify_webhook(secret="test", signature="", body='{"event":"test"}')
