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


@pytest.mark.usefixtures("mock_cognito_client")
class TestContractEventsPost:
    PATH = "/v1/contract-events"

    def test_creates_quota_allocation_for_existing_tenant(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """既存テナントに対してクォータ割り当てを追加できることを確認する。"""
        payload = {
            "legal_name": "アルファ株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#integration_test_01",
            "type": "top_up",
            "amount": 5000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        # Cleanup（アサーション失敗時でも後処理が走るよう先に実行）
        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                DELETE FROM quota_allocations
                WHERE contract_id = %s;
                """,
                ("contract#integration_test_01",),
            )
            db_connection.commit()

        assert response.status_code == status.HTTP_200_OK
        assert response.content == b""

    def test_creates_tenant_and_quota_allocation_for_new_customer(
        self,
        test_client: TestClient,
        db_connection: psycopg.Connection,
    ) -> None:
        """未登録の取引先IDに対してテナント発行とクォータ割り当てを行えることを確認する。"""
        payload = {
            "legal_name": "統合テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": "whi#integration_test_new",
            "contract_id": "contract#integration_test_02",
            "type": "base",
            "amount": 10000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        try:
            response = test_client.post(url=self.PATH, json=payload)

            assert response.status_code == status.HTTP_200_OK
            assert response.content == b""
        finally:
            with db_connection.cursor() as cursor:
                cursor.execute(
                    """
                    DELETE FROM quota_allocations
                    WHERE tenant_id IN (
                        SELECT id FROM tenants
                        WHERE whi_customer_id @> ARRAY['whi#integration_test_new']
                    );
                    """,
                )
                cursor.execute(
                    """
                    DELETE FROM tenants
                    WHERE whi_customer_id @> ARRAY['whi#integration_test_new'];
                    """,
                )
                db_connection.commit()

    def test_missing_legal_name(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """legal_nameが欠損しているリクエストを拒否できることを確認する。"""
        payload = {
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_missing_distribution(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """distributionが欠損しているリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_invalid_distribution(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """存在しないdistributionのリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "invalid_distribution",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_missing_customer_id(
        self,
        test_client: TestClient,
    ) -> None:
        """customer_idが欠損しているリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_missing_contract_id(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """contract_idが欠損しているリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_invalid_type(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """存在しないtypeのリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "invalid_type",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_amount_zero(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """amountが0のリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 0,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_amount_negative(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """amountが負数のリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": -1,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_valid_from_date_after_valid_to_date(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """valid_from_dateがvalid_to_dateより後のリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-12-31",
            "valid_to_date": "2027-01-01",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_valid_from_date_equals_valid_to_date(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """valid_from_dateとvalid_to_dateが同日のリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "whi_sfdc",
            "customer_id": registered_identifiers["tenant_alpha_whi_customer_id"],
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-06-01",
            "valid_to_date": "2027-06-01",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT

    def test_distribution_mismatch_with_provider(
        self,
        test_client: TestClient,
    ) -> None:
        """プロバイダのdistributionと一致しないリクエストを拒否できることを確認する。"""
        payload = {
            "legal_name": "テスト株式会社",
            "distribution": "cydas_sfdc",
            "customer_id": "cydas#dummy",
            "contract_id": "contract#dummy",
            "type": "base",
            "amount": 1000,
            "valid_from_date": "2027-01-01",
            "valid_to_date": "2027-12-31",
        }

        response = test_client.post(url=self.PATH, json=payload)

        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert "Distribution does not match contract provider." in response.json()["detail"]
