import math
from unittest import TestCase
import unittest
from pygeai.organization.clients import OrganizationClient
from pygeai.core.common.exceptions import APIResponseError 

@unittest.skip("Skipping due to access_token error")
class TestOrgGetOrganizationListIntegration(TestCase):
    __organization_attrs = [
        'id', 'name', 'administratorUserEmail', 'createdAt', 'updatedAt'
    ]    

    def setUp(self):
        """
        Set up the test environment.
        """
        self.organization_client = OrganizationClient(access_token="73bedd79-71bc-422d-b0ad-4433eb4f55a4!t7JDSw60gBqA7HM5rVRuik3gMso8QbZev4xgd1xxaSrg9PAaKL7g6uCFK7XgSyVyx6hY1ue04NnGRZ")


    def __get_organization_list(self, **kwargs):
        """
        Helper method to call get_organization_list with default or custom parameters.
        """
        return self.organization_client.get_organization_list(**kwargs)


    def test_get_organization_list_default_parameters(self):
        """Test successful retrieval of organization list with default parameters."""
        response = self.__get_organization_list()
        print(response)

        self.assertIn("count", response, "Response should have a 'count' key")        
        self.assertIn("pages", response, "Response should have a 'pages' key")
        self.assertIn("organizations", response, "Response should have an 'organizations' key")
        
        for organization in response["organizations"]:            
            for org_attr in self.__organization_attrs:
                self.assertIn(org_attr, organization, f"Response should have a '{org_attr}' key")


    def nonotest_get_organization_list_with_pagination(self):
        """Test organization list retrieval with pagination parameters."""
        test_params = [
            {"start_page": 1, "page_size": 1},
            {"start_page": 1, "page_size": 2},
            {"start_page": 1, "page_size": 3},
        ]
        
        for params in test_params:
            with self.subTest(params=params):
                response = self.__get_organization_list(**params)

                expected_pages = math.ceil(response["count"] / params["page_size"]) 
                self.assertEqual(
                    response["pages"], expected_pages,
                    f"Expected {expected_pages} pages for params {params}, got {response['pages']}"
                )


    def nonotest_get_organization_list_with_ordering(self):
        """Test organization list retrieval with different ordering parameters."""
        test_params = [
            {"order_key": "name", "order_direction": "asc"},
            {"order_key": "name", "order_direction": "desc"}
        ]
        
        for params in test_params:
            with self.subTest(params=params):
                response = self.__get_organization_list(**params)

                if len(response["organizations"]) > 1:
                    organizations = response["organizations"]
                    isOrdered = False
                    if params.get("order_direction") == "asc":
                        isOrdered = all(
                            organizations[i - 1]["name"] <= organizations[i]["name"]
                            for i in range(1, len(organizations))
                        )
                    else:
                        isOrdered = all(
                            organizations[i - 1]["name"] >= organizations[i]["name"]
                            for i in range(1, len(organizations))
                        )

                    self.assertTrue(
                        isOrdered, 
                        f"Organizations should be sorted in {'ascending' if params['order_direction'] == 'asc' else 'descending'} order by name"
                    )


    def nonotest_get_organization_list_with_filtering(self):
        """Test organization list retrieval with name filtering."""
        # First get list to find an organization name to filter by
        response = self.__get_organization_list(page_size=1)
        
        if response["count"] > 0:
            org_name = response["organizations"][0]["name"]
            
            filtered_response = self.__get_organization_list(
                filter_key="name",
                filter_value=org_name
            )
            
            # All returned organizations should match the filter
            for organization in filtered_response["organizations"]:
                self.assertIn(
                    org_name.lower(), organization["name"].lower(),
                    f"Organization name should contain filter value '{org_name}'"
                )


    def nonotest_get_organization_list_invalid_order_key(self):
        """Test behavior with invalid order key."""
        invalid_order_keys = ["invalid_field", "email", "id"]
        
        for order_key in invalid_order_keys:
            with self.subTest(order_key=order_key):
                with self.assertRaises(APIResponseError) as exception:
                    self.__get_organization_list(order_key=order_key)

                self.assertIn(
                    "Field orderKey is out of range",
                    str(exception.exception),
                    f"Expected error about invalid order key for {order_key}"
                )


    def nonotest_get_organization_list_invalid_filter_key(self):
        """Test behavior with invalid filter key."""
        invalid_filter_keys = ["invalid_field", "email", "id"]
        
        for filter_key in invalid_filter_keys:
            with self.subTest(filter_key=filter_key):
                with self.assertRaises(APIResponseError) as exception:
                    self.__get_organization_list(
                        filter_key=filter_key,
                        filter_value="test"
                    )

                self.assertIn(
                    "Field filterKey is out of range",
                    str(exception.exception),
                    f"Expected error about invalid filter key for {filter_key}"
                )


    def nonotest_get_organization_list_invalid_order_direction(self):
        """Test behavior with invalid order direction."""
        invalid_directions = ["invalid", "ascending", "descending"]
        
        for direction in invalid_directions:
            with self.subTest(direction=direction):
                with self.assertRaises(APIResponseError) as exception:
                    self.__get_organization_list(
                        order_key="name",
                        order_direction=direction
                    )

                self.assertIn(
                    "Field orderDirection is out of range",
                    str(exception.exception),
                    f"Expected error about invalid order direction for {direction}"
                )


    @unittest.skip("Requires System Administrator role - may not be available in test environment")
    def nonotest_get_organization_list_unauthorized_access(self):
        """Test error when user doesn't have System Administrator role."""
        # Create a client with invalid credentials
        unauthorized_client = OrganizationClient(api_key="invalid")
        
        with self.assertRaises(APIResponseError) as exception:
            unauthorized_client.get_organization_list()

        self.assertIn(
            "Unauthorized",
            str(exception.exception).lower(),
            "Expected authorization-related error message"
        )


    def nonotest_get_organization_list_nonexistent_organization_filter(self):
        """Test filtering with nonexistent organization name."""
        response = self.__get_organization_list(
            filter_key="name",
            filter_value="NonexistentOrganizationName123456789"
        )
        
        # Should return empty results or handle gracefully
        self.assertIn("count", response)
        self.assertIn("organizations", response)


    def nonotest_get_organization_list_edge_case_parameters(self):
        """Test edge cases for parameters."""
        # Test maximum valid values
        response = self.__get_organization_list(
            start_page=999999,
            page_size=100
        )
        self.assertIsInstance(response, dict)


    def nonotest_get_organization_list_empty_filter_value(self):
        """Test behavior with empty filter value."""
        response = self.__get_organization_list(
            filter_key="name",
            filter_value=""
        )
        
        # Should handle empty filter gracefully
        self.assertIsInstance(response, dict)
        self.assertIn("organizations", response)


    def nonotest_get_organization_list_large_page_size(self):
        """Test behavior with very large page sizes."""
        response = self.__get_organization_list(page_size=1000)
        
        self.assertIn("count", response)
        # Should handle large page sizes gracefully
        self.assertLessEqual(len(response["organizations"]), 1000)


    def nonotest_get_organization_list_combined_parameters(self):
        """Test organization list with combination of parameters."""
        response = self.__get_organization_list(
            start_page=1,
            page_size=5,
            order_key="name",
            order_direction="asc"
        )
        
        self.assertIn("count", response)
        self.assertIn("organizations", response)
        
        # If there are results, check ordering
        if len(response["organizations"]) > 1:
            organizations = response["organizations"]
            isOrdered = all(
                organizations[i - 1]["name"] <= organizations[i]["name"]
                for i in range(1, len(organizations))
            )
            self.assertTrue(isOrdered, "Organizations should be sorted in ascending order by name")


    def nonotest_get_organization_list_pagination_consistency(self):
        """Test that pagination returns consistent results."""
        # Get first page
        page1 = self.__get_organization_list(start_page=1, page_size=2)
        
        if page1["count"] > 2:
            # Get second page
            page2 = self.__get_organization_list(start_page=2, page_size=2)
            
            # Check that we got different organizations
            page1_ids = [org["id"] for org in page1["organizations"]]
            page2_ids = [org["id"] for org in page2["organizations"]]
            
            overlap = set(page1_ids).intersection(set(page2_ids))
            self.assertEqual(len(overlap), 0, "Pages should not contain overlapping organizations")
