"""Unit tests for BulkImports data plane operations."""

from __future__ import annotations

import pytest
import respx

from httpx import Response

from pinecone._internal.http import HTTPClient, HTTPConfig
from pinecone.index.bulk_imports import BulkImports


pytestmark = pytest.mark.unit

BASE_URL = "https://my-index-abc123.svc.pinecone.io"


def _make_bulk_imports() -> BulkImports:
    return BulkImports(
        http=HTTPClient(api_key="test-key", config=HTTPConfig()),
        base_url=BASE_URL,
    )


class TestStart:
    """Tests for BulkImports.start()."""

    @respx.mock
    def test_start_basic(self):
        route = respx.post(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(200, json={"id": "import-123"})
        )

        bi = _make_bulk_imports()
        result = bi.start(uri="s3://my-bucket/my-data/")

        assert route.called
        assert result.id == "import-123"

    @respx.mock
    def test_start_with_integration_id(self):
        route = respx.post(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(200, json={"id": "import-456"})
        )

        bi = _make_bulk_imports()
        bi.start(uri="s3://bucket/data/", integration_id="int-abc")

        request = route.calls.last.request
        assert b'"integrationId"' in request.content
        assert b'"int-abc"' in request.content

    @respx.mock
    def test_start_with_error_mode(self):
        route = respx.post(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(200, json={"id": "import-789"})
        )

        bi = _make_bulk_imports()
        bi.start(uri="s3://bucket/data/", error_mode="continue")

        request = route.calls.last.request
        assert b'"errorMode"' in request.content
        assert b'"onError"' in request.content
        assert b'"continue"' in request.content

    @respx.mock
    def test_start_sends_api_version_header(self):
        route = respx.post(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(200, json={"id": "import-abc"})
        )

        bi = _make_bulk_imports()
        bi.start(uri="s3://bucket/data/")

        request = route.calls.last.request
        assert request.headers["X-Pinecone-Api-Version"] == "2025-10"

    def test_start_empty_uri_raises(self):
        bi = _make_bulk_imports()
        with pytest.raises(ValueError):
            bi.start(uri="")


class TestList:
    """Tests for BulkImports.list()."""

    @respx.mock
    def test_list_basic(self):
        route = respx.get(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(
                200,
                json={
                    "data": [
                        {
                            "id": "import-1",
                            "uri": "s3://bucket/data1/",
                            "status": "Completed",
                            "createdAt": "2025-01-01T00:00:00Z",
                            "percentComplete": 100.0,
                            "recordsImported": 1000,
                        },
                        {
                            "id": "import-2",
                            "uri": "s3://bucket/data2/",
                            "status": "InProgress",
                            "createdAt": "2025-01-02T00:00:00Z",
                            "percentComplete": 50.0,
                            "recordsImported": 500,
                        },
                    ],
                },
            )
        )

        bi = _make_bulk_imports()
        result = bi.list()

        assert route.called
        assert len(result.data) == 2
        assert result.data[0].id == "import-1"
        assert result.data[0].status == "Completed"
        assert result.data[0].percent_complete == 100.0
        assert result.data[0].records_imported == 1000
        assert result.data[1].id == "import-2"
        assert result.data[1].status == "InProgress"

    @respx.mock
    def test_list_with_limit(self):
        route = respx.get(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(200, json={"data": []})
        )

        bi = _make_bulk_imports()
        bi.list(limit=10)

        request = route.calls.last.request
        assert "limit=10" in str(request.url)

    @respx.mock
    def test_list_with_pagination(self):
        respx.get(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(
                200,
                json={
                    "data": [
                        {
                            "id": "import-3",
                            "status": "Pending",
                            "createdAt": "2025-01-03T00:00:00Z",
                            "percentComplete": 0.0,
                            "recordsImported": 0,
                        },
                    ],
                    "pagination": {"next": "token-xyz"},
                },
            )
        )

        bi = _make_bulk_imports()
        result = bi.list(limit=1)

        assert result.pagination_token == "token-xyz"

    @respx.mock
    def test_list_no_pagination(self):
        respx.get(f"{BASE_URL}/bulk/imports").mock(return_value=Response(200, json={"data": []}))

        bi = _make_bulk_imports()
        result = bi.list()

        assert result.pagination_token is None


class TestDescribe:
    """Tests for BulkImports.describe()."""

    @respx.mock
    def test_describe_basic(self):
        route = respx.get(f"{BASE_URL}/bulk/imports/import-123").mock(
            return_value=Response(
                200,
                json={
                    "id": "import-123",
                    "uri": "s3://bucket/data/",
                    "status": "Completed",
                    "createdAt": "2025-01-01T00:00:00Z",
                    "finishedAt": "2025-01-01T01:00:00Z",
                    "percentComplete": 100.0,
                    "recordsImported": 5000,
                },
            )
        )

        bi = _make_bulk_imports()
        result = bi.describe(id="import-123")

        assert route.called
        assert result.id == "import-123"
        assert result.uri == "s3://bucket/data/"
        assert result.status == "Completed"
        assert result.finished_at == "2025-01-01T01:00:00Z"
        assert result.percent_complete == 100.0
        assert result.records_imported == 5000

    @respx.mock
    def test_describe_with_error(self):
        respx.get(f"{BASE_URL}/bulk/imports/import-fail").mock(
            return_value=Response(
                200,
                json={
                    "id": "import-fail",
                    "uri": "s3://bucket/bad-data/",
                    "status": "Failed",
                    "createdAt": "2025-01-01T00:00:00Z",
                    "percentComplete": 25.0,
                    "recordsImported": 100,
                    "error": "Invalid record format at line 101",
                },
            )
        )

        bi = _make_bulk_imports()
        result = bi.describe(id="import-fail")

        assert result.status == "Failed"
        assert result.error == "Invalid record format at line 101"

    @respx.mock
    def test_describe_url_includes_id(self):
        route = respx.get(f"{BASE_URL}/bulk/imports/my-import-id").mock(
            return_value=Response(
                200,
                json={
                    "id": "my-import-id",
                    "status": "Pending",
                    "createdAt": "2025-01-01T00:00:00Z",
                    "percentComplete": 0.0,
                    "recordsImported": 0,
                },
            )
        )

        bi = _make_bulk_imports()
        bi.describe(id="my-import-id")

        assert route.called
        assert "/bulk/imports/my-import-id" in str(route.calls.last.request.url)

    def test_describe_empty_id_raises(self):
        bi = _make_bulk_imports()
        with pytest.raises(ValueError):
            bi.describe(id="")


class TestCancel:
    """Tests for BulkImports.cancel()."""

    @respx.mock
    def test_cancel_basic(self):
        route = respx.delete(f"{BASE_URL}/bulk/imports/import-123").mock(
            return_value=Response(200, json={})
        )

        bi = _make_bulk_imports()
        result = bi.cancel(id="import-123")

        assert route.called
        assert result is not None

    @respx.mock
    def test_cancel_url_includes_id(self):
        route = respx.delete(f"{BASE_URL}/bulk/imports/my-cancel-id").mock(
            return_value=Response(200, json={})
        )

        bi = _make_bulk_imports()
        bi.cancel(id="my-cancel-id")

        assert route.called
        assert "/bulk/imports/my-cancel-id" in str(route.calls.last.request.url)

    def test_cancel_empty_id_raises(self):
        bi = _make_bulk_imports()
        with pytest.raises(ValueError):
            bi.cancel(id="")


class TestModelRepr:
    """Tests for model __repr__ methods."""

    def test_import_model_repr(self):
        from pinecone.models.bulk_imports.import_model import ImportModel

        imp = ImportModel(id="import-123", status="Completed")
        assert repr(imp) == "ImportModel(id='import-123', status='Completed')"

    @respx.mock
    def test_list_imports_response_repr(self):
        respx.get(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(
                200,
                json={
                    "data": [
                        {
                            "id": "import-1",
                            "status": "Completed",
                            "createdAt": "2025-01-01T00:00:00Z",
                            "percentComplete": 100.0,
                            "recordsImported": 1000,
                        },
                    ],
                },
            )
        )

        bi = _make_bulk_imports()
        result = bi.list()

        assert "data=1" in repr(result)


class TestImportsConvenienceProperty:
    """Tests for ListImportsResponse.imports property."""

    @respx.mock
    def test_imports_returns_same_as_data(self):
        respx.get(f"{BASE_URL}/bulk/imports").mock(
            return_value=Response(
                200,
                json={
                    "data": [
                        {
                            "id": "import-1",
                            "status": "Completed",
                            "createdAt": "2025-01-01T00:00:00Z",
                            "percentComplete": 100.0,
                            "recordsImported": 1000,
                        },
                        {
                            "id": "import-2",
                            "status": "InProgress",
                            "createdAt": "2025-01-02T00:00:00Z",
                            "percentComplete": 50.0,
                            "recordsImported": 500,
                        },
                    ],
                },
            )
        )

        bi = _make_bulk_imports()
        result = bi.list()

        assert result.imports is result.data
        assert len(result.imports) == 2
        assert result.imports[0].id == "import-1"
        assert result.imports[1].id == "import-2"

    @respx.mock
    def test_imports_empty_list(self):
        respx.get(f"{BASE_URL}/bulk/imports").mock(return_value=Response(200, json={"data": []}))

        bi = _make_bulk_imports()
        result = bi.list()

        assert result.imports == []
