import hashlib
import os
import unittest


os.environ.setdefault("DATABASE_URL", "mysql+pymysql://test:test@127.0.0.1/documenta")
os.environ.setdefault("REDIS_URL", "redis://127.0.0.1:6379/0")
os.environ.setdefault("APP_ENCRYPTION_KEY", "test-encryption-key")
os.environ.setdefault("PII_HMAC_KEY", "test-pii-key")
os.environ.setdefault("ACCESS_TOKEN_HMAC_KEY", "test-access-key")

from app.api.routes import _parse_getnet_notification
from app.main import app
from app.services.integrations import (
    getnet_notification_signature,
    getnet_notification_signature_is_valid,
)


class GetnetNotificationContractTests(unittest.TestCase):
    def test_return_path_accepts_get_and_post_without_changing_url(self):
        methods = set()
        for route in app.routes:
            if route.path == "/api/v1/pagos/getnet/retorno":
                methods.update(route.methods or set())
        self.assertTrue({"GET", "POST"}.issubset(methods))

    def test_signature_matches_documented_formula_and_prefix(self):
        request_id = 1234
        status = "APPROVED"
        date = "2026-03-29T16:43:54-05:00"
        secret = "secret-key"
        expected = hashlib.sha256(f"{request_id}{status}{date}{secret}".encode()).hexdigest()
        self.assertEqual(
            getnet_notification_signature(request_id, status, date, secret), expected
        )
        self.assertTrue(getnet_notification_signature_is_valid(
            f"sha256:{expected.upper()}", request_id, status, date, secret
        ))
        self.assertFalse(getnet_notification_signature_is_valid(
            "sha256:" + "0" * 64, request_id, status, date, secret
        ))

    def test_parser_normalizes_documented_payload(self):
        parsed = _parse_getnet_notification({
            "status": {
                "status": "APPROVED",
                "message": "Testing notification",
                "reason": "00",
                "date": "2026-03-29T16:43:54-05:00",
            },
            "requestId": 1234,
            "reference": "DOC104d29f41ff",
            "signature": "sha256:" + "a" * 64,
        })
        self.assertEqual(parsed, (
            "1234", "DOC104d29f41ff", "APPROVED",
            "2026-03-29T16:43:54-05:00", "sha256:" + "a" * 64,
        ))

    def test_parser_rejects_unbounded_or_invalid_identifiers(self):
        invalid = {
            "status": {"status": "APPROVED", "date": "2026-03-29T16:43:54-05:00"},
            "requestId": "not-a-number",
            "reference": "DOC 1",
            "signature": "sha256:" + "a" * 64,
        }
        with self.assertRaises(ValueError):
            _parse_getnet_notification(invalid)


if __name__ == "__main__":
    unittest.main()
