"""Integration test configuration with proper cleanup."""

import os
import uuid
from collections.abc import Generator
from typing import Any

import boto3
import pytest

from augint_billing_lib.models import Link


class TestDataTracker:
    """Track test data created during test session for cleanup."""

    def __init__(self):
        self.created_items = set()

    def track(self, api_key_id: str):
        """Track an item that was created."""
        self.created_items.add(api_key_id)

    def get_all(self):
        """Get all tracked items."""
        return list(self.created_items)

    def clear(self):
        """Clear tracked items."""
        self.created_items.clear()


@pytest.fixture(scope="session")
def test_data_tracker():
    """Session-wide tracker for test data."""
    return TestDataTracker()


@pytest.fixture(scope="session")
def dynamodb_table_session():
    """Get DynamoDB table for the session."""
    table_name = os.environ.get("TEST_DYNAMODB_TABLE", "test-customer-links")
    dynamodb = boto3.resource("dynamodb", region_name=os.environ.get("AWS_REGION", "us-east-1"))

    try:
        table = dynamodb.Table(table_name)
        table.load()
        return table  # noqa: TRY300
    except Exception as e:
        pytest.skip(f"DynamoDB table {table_name} not available: {e}")


@pytest.fixture
def dynamodb_table(dynamodb_table_session, test_data_tracker) -> Generator[Any, None, None]:
    """
    Provide DynamoDB table with automatic cleanup.

    This fixture:
    1. Provides the table for the test
    2. Tracks any items created during the test
    3. Cleans up those specific items after the test
    """
    table = dynamodb_table_session
    items_before_test = set()

    # Record what's in the table before the test (just test items)
    try:
        # Scan with pagination support
        paginator = table.meta.client.get_paginator("scan")
        page_iterator = paginator.paginate(
            TableName=table.name,
            FilterExpression=(
                "begins_with(api_key_id, :prefix1) OR "
                "begins_with(api_key_id, :prefix2) OR "
                "begins_with(api_key_id, :prefix3)"
            ),
            ExpressionAttributeValues={
                ":prefix1": "test-",
                ":prefix2": "metered-",
                ":prefix3": "key_",
            },
        )

        for page in page_iterator:
            items_before_test.update(item["api_key_id"] for item in page.get("Items", []))
    except Exception as e:
        print(f"Note: Could not scan existing items: {e}")
        # Continue anyway - we'll clean up everything that matches our prefixes

    # Provide table to test
    yield table

    # Clean up items created during this specific test
    try:
        # Scan again with pagination
        items_after_test = set()
        paginator = table.meta.client.get_paginator("scan")
        page_iterator = paginator.paginate(
            TableName=table.name,
            FilterExpression=(
                "begins_with(api_key_id, :prefix1) OR "
                "begins_with(api_key_id, :prefix2) OR "
                "begins_with(api_key_id, :prefix3)"
            ),
            ExpressionAttributeValues={
                ":prefix1": "test-",
                ":prefix2": "metered-",
                ":prefix3": "key_",
            },
        )

        for page in page_iterator:
            items_after_test.update(item["api_key_id"] for item in page.get("Items", []))

        new_items = items_after_test - items_before_test

        if new_items:
            print(f"\n✓ Cleaning up {len(new_items)} items created by this test")
            # Delete in batches of 25 (DynamoDB limit)
            batch_items = list(new_items)
            for i in range(0, len(batch_items), 25):
                with table.batch_writer() as batch:
                    for key_id in batch_items[i : i + 25]:
                        batch.delete_item(Key={"api_key_id": key_id})
                        test_data_tracker.track(key_id)
            print(f"  Deleted {len(new_items)} test items")
    except Exception as e:
        print(f"\n⚠️  Warning: Failed to clean up test items: {e}")
        print("  Run 'make cleanup-test-data' to manually clean up")


@pytest.fixture
def repo(dynamodb_table):
    """Create DdbRepo instance with cleanup tracking."""
    from augint_billing_lib.adapters.ddb_repo import DdbRepo

    return DdbRepo(dynamodb_table)


@pytest.fixture
def test_link(dynamodb_table) -> Link:
    """
    Create test Link object with automatic cleanup.

    This fixture ensures that any Link created is deleted after the test.
    """
    return Link(
        api_key_id=f"test-key-{uuid.uuid4()}",
        stripe_customer_id=f"cus_test_{uuid.uuid4().hex[:8]}",
        plan="free",
        usage_plan_id="FREE_10K",
    )

    # Cleanup is handled by dynamodb_table fixture
