"""Tests for webhook parsing and verification."""
from __future__ import annotations

import hashlib
import hmac
import json
import pytest

from runblob import (
    parse_webhook_payload,
    verify_webhook_signature,
    WebhookEvent,
)


class TestParseWebhookPayload:
    def test_parse_image_completed(self):
        event = parse_webhook_payload({
            "task_uuid": "uuid-123",
            "status": "completed",
            "result_image_url": "https://storage.runblob.io/out.png",
        })
        assert isinstance(event, WebhookEvent)
        assert event.is_completed
        assert event.id == "uuid-123"
        assert event.result_url == "https://storage.runblob.io/out.png"

    def test_parse_video_completed(self):
        event = parse_webhook_payload({
            "generation_id": "gen-456",
            "status": "completed",
            "video_url": "https://storage.runblob.io/video.mp4",
        })
        assert event.is_completed
        assert event.id == "gen-456"
        assert event.result_url == "https://storage.runblob.io/video.mp4"

    def test_parse_photo_completed(self):
        event = parse_webhook_payload({
            "generation_id": "photo-789",
            "status": "completed",
            "image_url": "https://storage.runblob.io/photo.png",
        })
        assert event.is_completed
        assert event.result_url == "https://storage.runblob.io/photo.png"

    def test_parse_failed(self):
        event = parse_webhook_payload({
            "task_uuid": "uuid-456",
            "status": "failed",
            "message": "MODERATION_FAILED",
        })
        assert event.is_failed
        assert event.is_terminal
        assert event.message == "MODERATION_FAILED"

    def test_parse_json_string(self):
        body = json.dumps({
            "task_uuid": "uuid-789",
            "status": "completed",
            "result_image_url": "https://example.com/img.png",
        })
        event = parse_webhook_payload(body)
        assert event.task_uuid == "uuid-789"

    def test_parse_json_bytes(self):
        body = json.dumps({
            "generation_id": "gen-abc",
            "status": "completed",
            "video_url": "https://example.com/v.mp4",
        }).encode()
        event = parse_webhook_payload(body)
        assert event.generation_id == "gen-abc"

    def test_invalid_json_raises(self):
        with pytest.raises(ValueError, match="Invalid JSON"):
            parse_webhook_payload("not json")

    def test_invalid_type_raises(self):
        with pytest.raises(ValueError, match="Unexpected body type"):
            parse_webhook_payload(12345)  # type: ignore


class TestVerifyWebhookSignature:
    def test_valid_signature(self):
        body = b'{"task_uuid":"test","status":"completed"}'
        secret = "my_webhook_secret"
        signature = hmac.new(
            secret.encode(), body, hashlib.sha256
        ).hexdigest()

        assert verify_webhook_signature(body, signature, secret) is True

    def test_invalid_signature(self):
        body = b'{"task_uuid":"test","status":"completed"}'
        assert verify_webhook_signature(body, "bad_sig", "secret") is False

    def test_tampered_body(self):
        secret = "my_secret"
        original_body = b'{"amount":"10.00"}'
        signature = hmac.new(
            secret.encode(), original_body, hashlib.sha256
        ).hexdigest()

        tampered_body = b'{"amount":"1000.00"}'
        assert verify_webhook_signature(tampered_body, signature, secret) is False
