import io
import uuid

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


@pytest.mark.usefixtures("mock_cognito_client")
class TestUsersImportPost:
    # NOTE: 詳細なバリデーションは/test_users_import_validate.pyで行うため、ここでは正常系と代表的な異常系のみをテストする。

    PATH = "/v1/users/import"

    def _make_csv(self, rows: list[list[str]]) -> io.BytesIO:
        """CSVデータを生成するヘルパー。rowsの先頭行はヘッダー。"""
        lines = [",".join(row) for row in rows]
        content = "\n".join(lines).encode("utf-8-sig")
        return io.BytesIO(content)

    def test_creates_users(
        self,
        test_client: TestClient,
        registered_identifiers: dict[str, str],
        db_connection: psycopg.Connection,
    ) -> None:
        """有効なCSVで複数ユーザーが作成されることを確認する。"""
        display_id_1 = "it-import-1"
        display_id_2 = "it-import-2"
        email_1 = f"{display_id_1}@example.com"
        email_2 = f"{display_id_2}@example.com"
        csv_bytes = self._make_csv(
            [
                ["ID", "名称", "メールアドレス"],
                [display_id_1, "インポートユーザー1", email_1],
                [display_id_2, "インポートユーザー2", email_2],
            ],
        )

        try:
            response = test_client.post(
                url=self.PATH,
                files={"file": ("users.csv", csv_bytes, "text/csv")},
            )

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

            with db_connection.cursor() as cursor:
                cursor.execute(
                    """
                    SELECT display_id, display_name, email
                    FROM users
                    WHERE tenant_id = %(tenant_id)s
                        AND display_id = ANY(%(display_ids)s)
                    ORDER BY display_id;
                    """,
                    {
                        "tenant_id": registered_identifiers["tenant_alpha_id"],
                        "display_ids": [display_id_1, display_id_2],
                    },
                )
                rows = cursor.fetchall()
                assert len(rows) == 2
                assert rows[0] == (display_id_1, "インポートユーザー1", email_1)
                assert rows[1] == (display_id_2, "インポートユーザー2", email_2)
        finally:
            with db_connection.cursor() as cursor:
                cursor.execute(
                    """
                    DELETE FROM users
                    WHERE tenant_id = %(tenant_id)s
                        AND display_id = ANY(%(display_ids)s);
                    """,
                    {
                        "tenant_id": registered_identifiers["tenant_alpha_id"],
                        "display_ids": [display_id_1, display_id_2],
                    },
                )

    def test_display_id_conflicts_with_existing(self, test_client: TestClient) -> None:
        """既存ユーザーのdisplay_idと重複する場合に409で拒否されることを確認する。"""
        csv_bytes = self._make_csv(
            [
                ["ID", "名称", "メールアドレス"],
                ["0001", "重複テスト", f"it-conflict-{uuid.uuid4().hex[:8]}@example.com"],
            ],
        )

        response = test_client.post(
            url=self.PATH,
            files={"file": ("users.csv", csv_bytes, "text/csv")},
        )

        assert response.status_code == status.HTTP_409_CONFLICT
        assert response.json() == {
            "detail": "Conflict detected for one or more fields.",
            "invalid_parameters": [
                {"name": "users[0].display_id", "code": "ALREADY_EXISTS"},
            ],
        }

    def test_email_conflicts_with_existing(self, test_client: TestClient) -> None:
        """既存ユーザーのemailと重複する場合に409で拒否されることを確認する。"""
        csv_bytes = self._make_csv(
            [
                ["ID", "名称", "メールアドレス"],
                [f"it-conflict-{uuid.uuid4().hex[:8]}", "重複テスト", "test001@test.com"],
            ],
        )

        response = test_client.post(
            url=self.PATH,
            files={"file": ("users.csv", csv_bytes, "text/csv")},
        )
        assert response.status_code == status.HTTP_409_CONFLICT
        assert response.json() == {
            "detail": "Conflict detected for one or more fields.",
            "invalid_parameters": [
                {"name": "users[0].email", "code": "ALREADY_EXISTS"},
            ],
        }
