from fastapi import status
from fastapi.testclient import TestClient


class TestUsersGet:
    PATH = "/v1/users"

    def test_returns_users(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
    ) -> None:
        """認証テナントに紐づくユーザー一覧を取得できることを確認する。"""
        response = test_client.get(url=self.PATH)

        assert response.status_code == status.HTTP_200_OK
        body = response.json()
        assert body["links"] == {
            "first": None,
            "prev": None,
            "next": None,
            "last": None,
        }
        assert body["meta"] == {
            "page": 1,
            "page_size": 10,
            "total": 3,
        }
        assert sorted(body["data"], key=lambda user: user["id"]) == [
            {
                "id": registered_identifiers["user_alpha_admin_id"],
                "display_id": "admin",
                "display_name": "管理ユーザー#アルファ株式会社",
                "email": None,
            },
            {
                "id": registered_identifiers["user_alpha_member_id"],
                "display_id": "0001",
                "display_name": "社員001#アルファ株式会社",
                "email": "test001@test.com",
            },
            {
                "id": registered_identifiers["user_alpha_member2_id"],
                "display_id": "0002",
                "display_name": "社員002#アルファ株式会社",
                "email": "test002@test.com",
            },
        ]

    def test_returns_next_link_when_following_page_exists(
        self,
        test_client: TestClient,
    ) -> None:
        """後続ページが存在する場合にnextリンクを返すことを確認する。"""
        response = test_client.get(url=self.PATH, params={"page": 1, "page_size": 2})

        assert response.status_code == status.HTTP_200_OK
        body = response.json()
        assert body["links"] == {
            "first": None,
            "prev": None,
            "next": "/v1/users?page=2&page_size=2",
            "last": "/v1/users?page=2&page_size=2",
        }
        assert body["meta"] == {
            "page": 1,
            "page_size": 2,
            "total": 3,
        }
        assert len(body["data"]) == body["meta"]["page_size"]

    def test_returns_requested_page(
        self,
        test_client: TestClient,
    ) -> None:
        """指定したページ条件で一覧を取得できることを確認する。"""
        response = test_client.get(url=self.PATH, params={"page": 2, "page_size": 2})

        assert response.status_code == status.HTTP_200_OK
        body = response.json()
        assert body["links"] == {
            "first": "/v1/users?page=1&page_size=2",
            "prev": "/v1/users?page=1&page_size=2",
            "next": None,
            "last": None,
        }
        assert body["meta"] == {
            "page": 2,
            "page_size": 2,
            "total": 3,
        }
        assert len(body["data"]) == 1

    def test_returns_last_link_when_page_exceeds_last_page(
        self,
        test_client: TestClient,
    ) -> None:
        """最終ページを超えたページを指定した場合にlastリンクを返すことを確認する。"""
        response = test_client.get(url=self.PATH, params={"page": 3, "page_size": 2})

        assert response.status_code == status.HTTP_200_OK
        body = response.json()
        assert body["links"] == {
            "first": "/v1/users?page=1&page_size=2",
            "prev": "/v1/users?page=2&page_size=2",
            "next": None,
            "last": "/v1/users?page=2&page_size=2",
        }
        assert body["meta"] == {
            "page": 3,
            "page_size": 2,
            "total": 3,
        }
        assert body["data"] == []

    # NOTE: page < 1 のケースはテスト省略。
    # ルーター定義で Query(ge=1) 制約を設けており、
    # FastAPI が 422 Unprocessable Entity で拒否するためフレームワーク責務とする。
