import os
import httpx
import pytest

ALLOWED_DOMAINS = os.environ["ALLOWED_DOMAINS"]

class TestAPIClient:
    def test_ping_api_successful(self, api_service):
        docker_ip, port = api_service
        client = httpx.get(f"http://{docker_ip}:{port}/merge/")

        assert client.status_code == 200

    def test_allowed_domains(self, api_service):
        docker_ip, port = api_service
        client = httpx.get(f"http://{docker_ip}:{port}/merge/allowed")
        r = client.text

        assert r == f'["{ALLOWED_DOMAINS}"]'

    def test_endpoint_cubes_fastapi_successful(self, api_service):
        docker_ip, port = api_service
        client = httpx.get(f"http://{docker_ip}:{port}/merge/cubes")

        assert client.status_code == 200

    def test_endpoint_structures_fastapi_successful(self, api_service):
        docker_ip, port = api_service
        client = httpx.get(f"http://{docker_ip}:{port}/merge/structures")

        assert client.status_code == 200

    def test_endpoint_dimensions_measures_fastapi_successful(self, api_service):
        docker_ip, port = api_service
        data = '{"cube_name":["customers","orders"],"locale": "en"}'
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/dimensions_measures", content=data)

        assert client.status_code == 200

    def test_endpoint_cubes_merge_fastapi_successful(self, api_service):
        docker_ip, port = api_service
        data = {
            "queries": [
            {
                "cube": "orders_a",
                "drilldowns": ["Customers", "Order Date"],
                "measures": ["Quantity", "Unit Price"]
            },
            {
                "cube": "orders_b",
                "drilldowns": ["Customers", "Product"],
                "measures": ["Quantity", "Unit Price"]
            }],
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "joins": [{
                "on": ["Customers"],
                "how": "inner"
            }]
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/query.jsonrecords", json=data)

        assert client.status_code == 200, f"Expected 200, got {client.status_code}. Response: {client.content}"

    def test_endpoint_cubes_merge_fastapi_no_join(self, api_service):
        docker_ip, port = api_service
        data = {
            "queries": [
            {
                "cube": "orders_a",
                "drilldowns": ["Customers", "Order Date"],
                "measures": ["Quantity", "Unit Price"],
                "cuts": {"Customers": ["C002"]}
            },
            {
                "cube": "orders_b",
                "drilldowns": ["Customers", "Product"],
                "measures": ["Quantity", "Unit Price"],
                "cuts": {"Customers": ["C001"]}
            }],
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "joins": [{
                "on": ["Customers"],
                "how": "inner"
            }]
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/query.jsonrecords", json=data)

        assert client.status_code == 200, f"Expected 200, got {client.status_code}. Response: {client.content}"

    def test_endpoint_cubes_merge_fastapi_empty(self, api_service):
        docker_ip, port = api_service
        data = {
            "queries": [
            {
                "cube": "orders_a",
                "drilldowns": ["Customers", "Order Date"],
                "measures": ["Quantity", "Unit Price"],
                "cuts": {"Customers": ["Unknown"]}
            },
            {
                "cube": "orders_b",
                "drilldowns": ["Customers", "Product"],
                "measures": ["Quantity", "Unit Price"],
                "cuts": {"Customers": ["C001"]}
            }],
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "joins": [{
                "on": ["Customers"],
                "how": "inner"
            }]
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/query.jsonrecords", json=data)

        assert client.status_code == 400, f"Expected 400, got {client.status_code}. Response: {client.content}"

    @pytest.mark.xfail
    def test_endpoint_cubes_external_merge_fastapi_missing_column(self, api_service):
        docker_ip, port = api_service
        data = {
            "queries": [
            {
                "cube": "orders_a",
                "drilldowns": ["Customers", "Order Date"],
                "measures": ["Quantity", "Unit Price"],
                "cuts": {"Customers": ["C002"]}
            },
            {
                "cube": "orders_b",
                "drilldowns": ["Customers", "Product"],
                "measures": ["Quantity", "Unit Price"],
                "cuts": {"Customers": ["C001"]}
            }],
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "joins": [{
                "on": ["Product"],
                "how": "inner"
            }]
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/merge.jsonrecords", json=data)

        assert client.status_code == 400, f"Expected 400, got {client.status_code}. Response: {client.content}"

    @pytest.mark.xfail
    def test_endpoint_cubes_external_merge_fastapi_successful(self, api_service):
        docker_ip, port = api_service
        data = {
            "query_left": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.csv?locale=en&cube=trade_i_baci_a_96&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "query_right": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.jsonrecords?locale=en&cube=trade_i_baci_a_22&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "join": {
                "on": "Year",
                "how": "left",
                "suffix": " (right)"
            }
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/merge.jsonrecords", json=data)

        assert client.status_code == 200, f"Expected 200, got {client.status_code}. Response: {client.content}"

    @pytest.mark.xfail
    def test_endpoint_cubes_external_merge_fastapi_no_join(self, api_service):
        docker_ip, port = api_service
        data = {
            "query_left": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.csv?locale=en&cube=trade_i_baci_a_96&measures=Trade+Value&drilldowns=Year&Year=2015"
            },
            "query_right": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.jsonrecords?locale=en&cube=trade_i_baci_a_22&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "join": {
                "on": "Year",
                "how": "left",
                "suffix": " (right)"
            }
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/merge.jsonrecords", json=data)

        assert client.status_code == 200, f"Expected 200, got {client.status_code}. Response: {client.content}"

    @pytest.mark.xfail
    def test_endpoint_cubes_external_merge_fastapi_empty(self, api_service):
        docker_ip, port = api_service
        data = {
            "query_left": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.csv?locale=en&cube=trade_i_baci_a_96&measures=Trade+Value&drilldowns=Year&Year=0"
            },
            "query_right": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.jsonrecords?locale=en&cube=trade_i_baci_a_22&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "join": {
                "on": "Year",
                "how": "left",
                "suffix": " (right)"
            }
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/merge.jsonrecords", json=data)

        assert client.status_code == 400, f"Expected 400, got {client.status_code}. Response: {client.content}"

    @pytest.mark.xfail
    def test_endpoint_cubes_external_merge_fastapi_missing_column(self, api_service):
        docker_ip, port = api_service
        data = {
            "query_left": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.csv?locale=en&cube=trade_i_baci_a_96&measures=Trade+Value&drilldowns=HS2&HS2=101"
            },
            "query_right": {
                "url": f"https://{ALLOWED_DOMAINS}/tesseract/data.jsonrecords?locale=en&cube=trade_i_baci_a_22&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "join": {
                "on": "Year",
                "how": "left",
                "suffix": " (right)"
            }
        }
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/merge.jsonrecords", json=data)

        assert client.status_code == 400, f"Expected 400, got {client.status_code}. Response: {client.content}"

    def test_endpoint_cubes_external_merge_fastapi_error(self, api_service):
        docker_ip, port = api_service
        data = """{
            "query_left": {
                "url": "https://not-allowed.com/tesseract/data.csv?locale=en&cube=trade_i_baci_a_96&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "query_right": {
                "url": "https://not-allowed.com/tesseract/data.jsonrecords?locale=en&cube=trade_i_baci_a_22&measures=Trade+Value&drilldowns=Year&time=Year.latest.10"
            },
            "pagination": {
                "limit": 0,
                "offset": 0
            },
            "join": {
                "on": "Year",
                "how": "left",
                "suffix": " (right)"
            }
        }"""
        client = httpx.post(f"http://{docker_ip}:{port}/merge/cubes/merge.jsonrecords", content=data)

        assert client.status_code == 500, f"Expected 500, got {client.status_code}. Response: {client.content}"
