import uuid

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


@pytest.mark.usefixtures("mock_cognito_client")
class TestUsersDelete:
    PATH = "/v1/users"

    def test_deletes_multiple_users(
        self,
        test_client_as_member: TestClient,
        registered_identifiers: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """複数ユーザーを一括削除できることを確認する。"""
        tenant_id = registered_identifiers["tenant_alpha_id"]
        user_ids: list[str] = []

        with db_connection.cursor() as cursor:
            for i in range(3):
                display_id = f"it-bulk-del-{uuid.uuid4().hex[:8]}"
                cursor.execute(
                    """
                    INSERT INTO users (tenant_id, display_id, display_name, email)
                    VALUES (%s, %s, %s, %s)
                    RETURNING id;
                    """,
                    (tenant_id, display_id, f"Bulk Delete Target {i}", f"{display_id}@example.com"),
                )
                row = cursor.fetchone()
                assert row is not None
                user_ids.append(str(row[0]))
            db_connection.commit()

        try:
            response = test_client_as_member.request("DELETE", self.PATH, json={"user_ids": user_ids})

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

            with db_connection.cursor() as cursor:
                cursor.execute(
                    """
                    SELECT COUNT(*)
                    FROM users
                    WHERE id = ANY(%s::uuid[]);
                    """,
                    (user_ids,),
                )
                assert cursor.fetchone() == (0,)
        finally:
            with db_connection.cursor() as cursor:
                cursor.execute(
                    """
                    DELETE FROM users
                    WHERE id = ANY(%s::uuid[]);
                    """,
                    (user_ids,),
                )
                db_connection.commit()

    def test_non_existing_users_returns_no_content(
        self,
        test_client_as_member: TestClient,
    ) -> None:
        """存在しないuser_idsでも削除リクエストを受け付けることを確認する。"""
        user_ids = [str(uuid.uuid4()), str(uuid.uuid4())]

        response = test_client_as_member.request("DELETE", self.PATH, json={"user_ids": user_ids})

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

    def test_other_tenant_users_are_not_deleted(
        self,
        test_client_as_member: TestClient,
        registered_identifiers: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """他テナントのユーザーを削除できないことを確認する。"""
        target_user_id = registered_identifiers["user_beta_member_id"]

        response = test_client_as_member.request("DELETE", self.PATH, json={"user_ids": [target_user_id]})

        assert response.status_code == status.HTTP_204_NO_CONTENT

        with db_connection.cursor() as cursor:
            cursor.execute(
                """
                SELECT COUNT(*)
                FROM users
                WHERE id = %s
                    AND tenant_id = %s;
                """,
                (target_user_id, registered_identifiers["tenant_beta_id"]),
            )
            assert cursor.fetchone() == (1,)

    def test_cant_delete_self(
        self,
        test_client_as_member: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """ユーザー自身を削除しようとした場合、400エラーが返ることを確認する。"""
        user_id = registered_identifiers["user_alpha_member_id"]
        other_id = str(uuid.uuid4())

        response = test_client_as_member.request("DELETE", self.PATH, json={"user_ids": [other_id, user_id]})

        assert response.status_code == status.HTTP_400_BAD_REQUEST
        body = response.json()
        assert body["detail"] == "Cannot delete the user itself."
