import hmac
import hashlib
import base64
import json
from unittest.mock import patch

from django.test import TestCase, override_settings


class ShopifyWebhookViewTests(TestCase):
    @override_settings(SHOPIFY_API_SECRET="test-secret")
    @patch("webhooks.views.WebhookService.handle_refund_created")
    def test_refund_webhook_with_valid_hmac_calls_service(self, refund_handler_mock):
        refund_handler_mock.return_value = {"ok": True}
        payload = {"id": "refund-1", "order_id": "12345"}
        body = json.dumps(payload).encode("utf-8")

        digest = hmac.new(
            b"test-secret",
            body,
            hashlib.sha256,
        ).digest()
        header_hmac = base64.b64encode(digest).decode("utf-8")

        response = self.client.post(
            "/webhooks/shopify/refunds-create/",
            data=body,
            content_type="application/json",
            **{
                "HTTP_X_SHOPIFY_HMAC_SHA256": header_hmac,
                "HTTP_X_SHOPIFY_WEBHOOK_ID": "wh-id-1",
            },
        )

        self.assertEqual(response.status_code, 200)
        refund_handler_mock.assert_called_once()

    @override_settings(SHOPIFY_API_SECRET="test-secret")
    @patch("webhooks.views.WebhookService.handle_fulfillment_created_or_updated")
    def test_fulfillment_create_webhook_with_valid_hmac_calls_service(
        self,
        fulfillment_handler_mock,
    ):
        fulfillment_handler_mock.return_value = {"ok": True, "delivery_id": "1"}
        payload = {
            "id": "ful-1",
            "order_id": "12345",
            "tracking_number": "1Z999",
        }
        body = json.dumps(payload).encode("utf-8")
        digest = hmac.new(b"test-secret", body, hashlib.sha256).digest()
        header_hmac = base64.b64encode(digest).decode("utf-8")

        response = self.client.post(
            "/webhooks/shopify/fulfillments-create/",
            data=body,
            content_type="application/json",
            **{
                "HTTP_X_SHOPIFY_HMAC_SHA256": header_hmac,
                "HTTP_X_SHOPIFY_WEBHOOK_ID": "wh-ful-1",
            },
        )

        self.assertEqual(response.status_code, 200)
        fulfillment_handler_mock.assert_called_once()
        call_kwargs = fulfillment_handler_mock.call_args.kwargs
        self.assertEqual(call_kwargs["webhook_id"], "wh-ful-1")
        self.assertEqual(call_kwargs["topic"], "fulfillments/create")

    @override_settings(SHOPIFY_API_SECRET="test-secret")
    @patch("webhooks.views.WebhookService.handle_fulfillment_created_or_updated")
    def test_fulfillment_update_webhook_with_valid_hmac_calls_service(
        self,
        fulfillment_handler_mock,
    ):
        fulfillment_handler_mock.return_value = {"ok": True}
        payload = {"id": "ful-2", "order_id": "12345", "tracking_number": "ABC"}
        body = json.dumps(payload).encode("utf-8")
        digest = hmac.new(b"test-secret", body, hashlib.sha256).digest()
        header_hmac = base64.b64encode(digest).decode("utf-8")

        response = self.client.post(
            "/webhooks/shopify/fulfillments-update/",
            data=body,
            content_type="application/json",
            **{
                "HTTP_X_SHOPIFY_HMAC_SHA256": header_hmac,
                "HTTP_X_SHOPIFY_WEBHOOK_ID": "wh-ful-2",
            },
        )

        self.assertEqual(response.status_code, 200)
        fulfillment_handler_mock.assert_called_once()
        self.assertEqual(
            fulfillment_handler_mock.call_args.kwargs["topic"],
            "fulfillments/update",
        )

    @override_settings(SHOPIFY_API_SECRET="test-secret")
    def test_webhook_rejects_invalid_hmac(self):
        response = self.client.post(
            "/webhooks/shopify/refunds-create/",
            data=json.dumps({"id": "refund-2"}),
            content_type="application/json",
            **{"HTTP_X_SHOPIFY_HMAC_SHA256": "invalid"},
        )
        self.assertEqual(response.status_code, 401)
