from collections.abc import Iterator

import pytest
from moto import mock_aws

from infrastructure.csv_s3_client import CsvS3Client
from tests.infrastructure import make_boto_client

BUCKET = "csv-bucket"


@pytest.fixture
def csv_client() -> Iterator[CsvS3Client]:
    with mock_aws():
        boto_client = make_boto_client("s3")
        boto_client.create_bucket(Bucket=BUCKET)
        yield CsvS3Client(boto_client, BUCKET)


def test_save_rows_returns_s3_uri(csv_client: CsvS3Client) -> None:
    # arrange
    rows = [{"address": "1 High St", "postcode": "AB1 2CD"}]
    # act
    uri = csv_client.save_rows(rows, "uploads/addresses.csv")
    # assert
    assert uri == f"s3://{BUCKET}/uploads/addresses.csv"


def test_round_trip_preserves_rows(csv_client: CsvS3Client) -> None:
    # arrange
    rows = [
        {"address": "1 High St", "postcode": "AB1 2CD"},
        {"address": "2 Low St", "postcode": "XY9 8ZW"},
    ]
    # act
    uri = csv_client.save_rows(rows, "uploads/addresses.csv")
    fetched = csv_client.read_rows(uri)
    # assert
    assert fetched == rows


def test_save_rows_rejects_empty_list(csv_client: CsvS3Client) -> None:
    # act / assert
    with pytest.raises(ValueError, match="empty"):
        csv_client.save_rows([], "uploads/empty.csv")


def test_read_rows_rejects_wrong_bucket(csv_client: CsvS3Client) -> None:
    # act / assert
    with pytest.raises(ValueError, match="does not match client bucket"):
        csv_client.read_rows("s3://other-bucket/uploads/addresses.csv")
