import psycopg
from fastapi import status
from fastapi.testclient import TestClient


class TestClientTenantsPost:
    PATH = "/v1/client-tenants"

    def test_unique_client_tenant_name(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """全てのClientTenantと重複しないTenantNameのClientTenantを作成できることを確認。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": registered_identifiers["sfdc_whi_alpha"],
            "distribution": "whi_sfdc",
            "base_url": "https://dummy.example.com",
        }

        response = test_client.post(
            url=f"{self.PATH}/dummy_client_tenant",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_200_OK
        assert (
            response.text
            == "Tenant 'dummy_client_tenant' is registered and linked to Customer 'アルファ株式会社' successfully."
        )

        list_response = test_client.get(url=self.PATH, headers=headers)

        assert list_response.status_code == status.HTTP_200_OK
        assert list_response.json()["tenants"].count({"name": "dummy_client_tenant", "status": "active"}) == 1

        # Cleanup
        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                DELETE FROM client_tenants
                WHERE name = %s;
                """,
                ("dummy_client_tenant",),
            )
            db_connection.commit()

    def test_unregistered_customer_id(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """既存のTenantの取引先IDと一致しないClientTenantを登録できることを確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": "dummy_customer_id",
            "distribution": "whi_sfdc",
        }

        response = test_client.post(
            url=f"{self.PATH}/dummy_client_tenant",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_200_OK

        # Cleanup
        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                DELETE FROM pending_client_tenants
                WHERE name = %s;
                """,
                ("dummy_client_tenant",),
            )
            db_connection.commit()

    def test_base_url_is_optional(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """base_urlが存在しないClientTenantを登録できることを確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": registered_identifiers["sfdc_whi_alpha"],
            "distribution": "whi_sfdc",
        }

        response = test_client.post(
            url=f"{self.PATH}/dummy_client_tenant_without_base_url",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_200_OK

        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                SELECT base_url
                FROM client_tenants
                WHERE name = %s;
                """,
                ("dummy_client_tenant_without_base_url",),
            )
            assert cursor.fetchone() == (None,)

        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                DELETE FROM client_tenants
                WHERE name = %s;
                """,
                ("dummy_client_tenant_without_base_url",),
            )
            db_connection.commit()

    def test_missing_customer_id(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
    ) -> None:
        """customer_idが存在しないリクエストを拒否できるかを確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "distribution": "whi_sfdc",
        }

        response = test_client.post(
            url=f"{self.PATH}/dummy_client_tenant",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_invalid_distribution(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
    ) -> None:
        """存在しないdistributionのリクエストを拒否できるかを確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": registered_identifiers["sfdc_whi_alpha"],
            "distribution": "invalid_distribution",
        }

        response = test_client.post(
            url=f"{self.PATH}/dummy_client_tenant",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_missing_distribution(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
    ) -> None:
        """distributionが存在しないリクエストを拒否できるかを確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": registered_identifiers["sfdc_whi_alpha"],
        }

        response = test_client.post(
            url=f"{self.PATH}/dummy_client_tenant",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_client_tenant_name_already_exists(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """client_id=nullのClientTenantとTenantNameが重複するClientTenantを作成できるかを確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": registered_identifiers["sfdc_whi_alpha"],
            "distribution": "whi_sfdc",
        }

        response = test_client.post(
            url=f"{self.PATH}/{registered_identifiers['tenant_gen_ai_profile_1']}",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_200_OK
        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                DELETE FROM client_tenants
                WHERE name = %s
                    AND client_id IS NOT NULL;
                """,
                (registered_identifiers["tenant_gen_ai_profile_1"],),
            )
            db_connection.commit()

    def test_client_tenant_already_exists(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        header_names: dict[str, str],
    ) -> None:
        """client_idが同一かつTenantNameが重複するリクエストを拒否できるか確認する。"""
        headers = {
            header_names["api_key"]: registered_identifiers["api_key_gen_ai_profile"],
        }
        payload = {
            "customer_id": registered_identifiers["sfdc_whi_alpha"],
            "distribution": "whi_sfdc",
        }

        response = test_client.post(
            url=f"{self.PATH}/{registered_identifiers['tenant_gen_ai_profile_2']}",
            headers=headers,
            json=payload,
        )

        assert response.status_code == status.HTTP_409_CONFLICT
        assert response.json()["detail"] == "A tenant with the same name is already registered."
