"""
Tests for the Amazon purchaseId#workItemId reference format

The pharmacy order id must be percent-encoded in the prescription JPEG
download URL — Amazon's purchaseId#workItemId format contains '#', which
would otherwise be treated as a URL fragment, truncating the path so 1Rx
looks up the wrong order.
"""

import asyncio
import sys
import tempfile
import unittest
from pathlib import Path
from unittest.mock import MagicMock, patch

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))

import app.src.file_processor as file_processor_mod
from app.src.file_processor import FileProcessor

HASH_REFERENCE_ID = "404-4539392-3665964#6364e0b9-566f-448a-97cb-702ba1c04ae6"


class MockConfig:
    """Mock configuration for testing"""

    def __init__(self):
        self.rx_api_key = "test-api-key"
        self.rx_api_base_url = "http://localhost:10000/api/1rx/v1"


def make_file_processor(config, request_store):
    with patch.object(file_processor_mod, "SFTPHandler"), patch.object(
        file_processor_mod, "PGPHandler"
    ):
        fp = FileProcessor(config, request_store)
    return fp


class FakeJpegResponse:
    """Fake aiohttp binary response usable as an async context manager"""

    def __init__(self, status):
        self.status = status

    async def read(self):
        return b"jpeg-bytes"

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        return False


class FakeGetSession:
    """Fake aiohttp session recording GET urls"""

    def __init__(self, response):
        self.response = response
        self.urls = []

    def get(self, url, *args, **kwargs):
        self.urls.append(url)
        return self.response

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        return False


class TestDownloadPrescriptionJpeg(unittest.TestCase):
    """Test cases for the JPEG download URL encoding"""

    def test_hash_in_order_id_is_percent_encoded(self):
        fp = make_file_processor(MockConfig(), MagicMock())
        session = FakeGetSession(FakeJpegResponse(200))
        rx_response = {"pharmacyOrderId": HASH_REFERENCE_ID}

        with tempfile.TemporaryDirectory() as tmp:
            jpeg_path = Path(tmp) / "out.jpg"
            with patch.object(
                file_processor_mod.aiohttp, "ClientSession", return_value=session
            ):
                ok = asyncio.run(fp.download_prescription_jpeg(rx_response, jpeg_path))

            self.assertTrue(ok)
            self.assertEqual(jpeg_path.read_bytes(), b"jpeg-bytes")

        self.assertEqual(len(session.urls), 1)
        url = session.urls[0]
        self.assertNotIn("#", url)
        self.assertIn(
            "/orders/404-4539392-3665964%236364e0b9-566f-448a-97cb-702ba1c04ae6/"
            "download-jpeg-prescription",
            url,
        )

    def test_plain_order_id_is_unchanged(self):
        fp = make_file_processor(MockConfig(), MagicMock())
        session = FakeGetSession(FakeJpegResponse(200))
        rx_response = {"pharmacyOrderId": "ORD-12345"}

        with tempfile.TemporaryDirectory() as tmp:
            jpeg_path = Path(tmp) / "out.jpg"
            with patch.object(
                file_processor_mod.aiohttp, "ClientSession", return_value=session
            ):
                ok = asyncio.run(fp.download_prescription_jpeg(rx_response, jpeg_path))

            self.assertTrue(ok)

        self.assertIn("/orders/ORD-12345/download-jpeg-prescription", session.urls[0])


if __name__ == "__main__":
    unittest.main()
