# -*- coding: utf-8 -*-

"""
Common fixtures and utilities for testing Kiro Gateway.

Provides test isolation from external services and global state.
All tests MUST be completely isolated from the network.
"""

import asyncio
import json
import pytest
import time
from typing import AsyncGenerator, Dict, Any, List
from unittest.mock import AsyncMock, MagicMock, Mock, patch
from datetime import datetime, timezone

import httpx
from fastapi.testclient import TestClient


# =============================================================================
# Event Loop Fixtures
# =============================================================================

@pytest.fixture(scope="session")
def event_loop():
    """
    Creates an event loop for the entire test session.
    Required for proper async fixture operation.
    """
    print("Creating event loop for test session...")
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    print("Closing event loop...")
    loop.close()


# =============================================================================
# Environment Fixtures
# =============================================================================

@pytest.fixture(scope="session", autouse=True)
def setup_test_environment(tmp_path_factory):
    """
    CRITICAL FIXTURE: Sets up isolated test environment.
    
    Creates temporary credentials.json and state.json to prevent:
    1. Tests failing when .env doesn't exist
    2. Pollution of working directory with test files
    
    This fixture:
    - Creates temporary directory for test files
    - Creates mock credentials.json with valid test data
    - Creates mock Kiro credentials file
    - Patches config paths to use temporary files
    """
    print("🔧 Setting up isolated test environment...")
    
    # Create temporary directory for test files
    tmp_dir = tmp_path_factory.mktemp("test_config")
    
    # Create mock Kiro credentials file (JSON format)
    mock_kiro_creds = {
        "accessToken": "mock_access_token_from_fixture",
        "refreshToken": "mock_refresh_token_from_fixture",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/mock",
        "region": "us-east-1"
    }
    mock_creds_file = tmp_dir / "mock_kiro_creds.json"
    mock_creds_file.write_text(json.dumps(mock_kiro_creds, indent=2))
    
    # Create credentials.json pointing to mock file
    credentials_data = [
        {
            "type": "json",
            "path": str(mock_creds_file),
            "enabled": True
        }
    ]
    creds_file = tmp_dir / "credentials.json"
    creds_file.write_text(json.dumps(credentials_data, indent=2))
    
    # Patch config paths to use temporary files
    import kiro.config
    original_creds_file = kiro.config.ACCOUNTS_CONFIG_FILE
    original_state_file = kiro.config.ACCOUNTS_STATE_FILE
    
    kiro.config.ACCOUNTS_CONFIG_FILE = str(creds_file)
    kiro.config.ACCOUNTS_STATE_FILE = str(tmp_dir / "state.json")
    
    print(f"✅ Test credentials: {creds_file}")
    print(f"✅ Test state: {tmp_dir / 'state.json'}")
    
    yield
    
    # Restore original paths
    kiro.config.ACCOUNTS_CONFIG_FILE = original_creds_file
    kiro.config.ACCOUNTS_STATE_FILE = original_state_file
    
    print("🧹 Test environment cleaned up")


@pytest.fixture
def mock_env_vars(monkeypatch):
    """
    Mocks environment variables for isolation from real credentials.
    """
    print("Setting up mocked environment variables...")
    monkeypatch.setenv("REFRESH_TOKEN", "test_refresh_token_abcdef")
    monkeypatch.setenv("PROXY_API_KEY", "test_proxy_key_12345")
    monkeypatch.setenv("PROFILE_ARN", "arn:aws:codewhisperer:us-east-1:123456789:profile/test")
    monkeypatch.setenv("KIRO_REGION", "us-east-1")
    return {
        "REFRESH_TOKEN": "test_refresh_token_abcdef",
        "PROXY_API_KEY": "test_proxy_key_12345",
        "PROFILE_ARN": "arn:aws:codewhisperer:us-east-1:123456789:profile/test",
        "KIRO_REGION": "us-east-1"
    }


# =============================================================================
# Token and Authentication Fixtures
# =============================================================================

@pytest.fixture
def valid_kiro_token():
    """Returns a valid mock Kiro access token."""
    return "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.test_kiro_access_token"


@pytest.fixture
def mock_kiro_token_response(valid_kiro_token):
    """
    Factory for creating mock Kiro token refresh endpoint responses.
    """
    def _create_response(expires_in: int = 3600, token: str = None):
        return {
            "accessToken": token or valid_kiro_token,
            "refreshToken": "new_refresh_token_xyz",
            "expiresIn": expires_in,
            "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test"
        }
    return _create_response


@pytest.fixture
def valid_proxy_api_key():
    """
    Returns the actual PROXY_API_KEY that the application is using.
    
    This reads the value from kiro.config, which was loaded when the app
    was imported. This ensures tests use the same key the app validates against.
    """
    from kiro.config import PROXY_API_KEY
    return PROXY_API_KEY


@pytest.fixture
def invalid_proxy_api_key():
    """Returns an invalid API key for negative tests."""
    return "invalid_wrong_secret_key"


@pytest.fixture
def auth_headers(valid_proxy_api_key):
    """
    Factory for creating valid and invalid Authorization headers.
    """
    def _create_headers(api_key: str = None, invalid: bool = False):
        if invalid:
            return {"Authorization": "Bearer wrong_key_123"}
        key = api_key or valid_proxy_api_key
        return {"Authorization": f"Bearer {key}"}
    
    return _create_headers


# =============================================================================
# Kiro Models Fixtures
# =============================================================================

@pytest.fixture
def mock_kiro_models_response():
    """
    Mock successful response from Kiro API for ListAvailableModels.
    """
    return {
        "models": [
            {
                "modelId": "claude-sonnet-4.5",
                "displayName": "Claude Sonnet 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            },
            {
                "modelId": "claude-opus-4.5",
                "displayName": "Claude Opus 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            },
            {
                "modelId": "claude-haiku-4.5",
                "displayName": "Claude Haiku 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            }
        ]
    }


# =============================================================================
# Kiro Streaming Response Fixtures
# =============================================================================

@pytest.fixture
def mock_kiro_streaming_chunks():
    """
    Returns a list of mock SSE chunks from Kiro API for streaming response.
    Covers: regular text, tool calls, usage.
    """
    return [
        # Chunk 1: Text start
        b'{"content":"Hello"}',
        # Chunk 2: Text continuation
        b'{"content":" World!"}',
        # Chunk 3: Tool call start
        b'{"name":"get_weather","toolUseId":"call_abc123"}',
        # Chunk 4: Tool call input
        b'{"input":"{\\"location\\": \\"Moscow\\"}"}',
        # Chunk 5: Tool call stop
        b'{"stop":true}',
        # Chunk 6: Usage
        b'{"usage":1.5}',
        # Chunk 7: Context usage
        b'{"contextUsagePercentage":25.5}',
    ]

@pytest.fixture
def mock_kiro_simple_text_chunks():
    """
    Mock simple text response from Kiro (without tool calls).
    """
    return [
        b'{"content":"This is a complete response."}',
        b'{"usage":0.5}',
        b'{"contextUsagePercentage":10.0}',
    ]


@pytest.fixture
def mock_kiro_stream_with_usage():
    """
    Mock Kiro SSE response with usage information.
    """
    return [
        b'{"content":"Final text."}',
        b'{"usage":1.3}',
        b'{"contextUsagePercentage":50.0}',
    ]


# =============================================================================
# OpenAI Request Fixtures
# =============================================================================

@pytest.fixture
def sample_openai_chat_request():
    """
    Factory for creating valid OpenAI chat completion requests.
    """
    def _create_request(
        model: str = "claude-sonnet-4-5",
        messages: list = None,
        stream: bool = False,
        temperature: float = None,
        max_tokens: int = None,
        tools: list = None,
        **kwargs
    ):
        if messages is None:
            messages = [{"role": "user", "content": "Hello, AI!"}]
        
        request = {
            "model": model,
            "messages": messages,
            "stream": stream
        }
        
        if temperature is not None:
            request["temperature"] = temperature
        if max_tokens is not None:
            request["max_tokens"] = max_tokens
        if tools is not None:
            request["tools"] = tools
        
        request.update(kwargs)
        return request
    
    return _create_request


@pytest.fixture
def sample_tool_definition():
    """
    Sample tool definition for testing tool calling.
    """
    return {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"}
                },
                "required": ["location"]
            }
        }
    }


# =============================================================================
# HTTP Client Fixtures
# =============================================================================

@pytest.fixture
async def mock_httpx_client():
    """
    Creates a mocked httpx.AsyncClient for isolation from network requests.
    """
    print("Creating mocked httpx.AsyncClient...")
    mock_client = AsyncMock(spec=httpx.AsyncClient)
    
    # Mock methods
    mock_client.post = AsyncMock()
    mock_client.get = AsyncMock()
    mock_client.aclose = AsyncMock()
    mock_client.build_request = Mock()
    mock_client.send = AsyncMock()
    mock_client.is_closed = False
    
    return mock_client


@pytest.fixture
def mock_httpx_response():
    """
    Factory for creating mocked httpx.Response objects.
    """
    def _create_response(
        status_code: int = 200,
        json_data: Dict[str, Any] = None,
        text: str = None,
        stream_chunks: list = None
    ):
        print(f"Creating mock httpx.Response (status={status_code})...")
        mock_response = AsyncMock(spec=httpx.Response)
        mock_response.status_code = status_code
        
        if json_data is not None:
            mock_response.json = Mock(return_value=json_data)
        
        if text is not None:
            mock_response.text = text
            mock_response.content = text.encode()
        
        if stream_chunks is not None:
            # For streaming responses
            async def mock_aiter_bytes():
                for chunk in stream_chunks:
                    yield chunk
            
            mock_response.aiter_bytes = mock_aiter_bytes
        
        mock_response.raise_for_status = Mock()
        mock_response.aclose = AsyncMock()
        mock_response.aread = AsyncMock(return_value=b'{"error": "mocked error"}')
        
        return mock_response
    
    return _create_response


# =============================================================================
# Global Network Blocking
# =============================================================================

@pytest.fixture(scope="session", autouse=True)
def block_all_network_calls():
    """
    CRITICAL FIXTURE: Globally blocks ALL network calls.
    Ensures that NO test can make a real network request.
    
    Provides mock responses for:
    - Token refresh (Kiro Desktop Auth and AWS SSO OIDC)
    - ListAvailableModels API
    - Streaming responses (for route tests)
    """
    
    # Create a mock that will be used for all AsyncClient instances
    mock_async_client = AsyncMock(spec=httpx.AsyncClient)

    # Mock response for token refresh (Kiro Desktop Auth format)
    # Used by KiroAuthManager._refresh_token_kiro_desktop()
    mock_token_response = AsyncMock(spec=httpx.Response)
    mock_token_response.status_code = 200
    mock_token_response.json.return_value = {
        "accessToken": "mock_access_token_global_fixture",
        "refreshToken": "mock_refresh_token_global_fixture",
        "expiresIn": 3600,
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/mock"
    }
    mock_token_response.raise_for_status = Mock()

    # Mock response for ListAvailableModels
    # Used by AccountManager._initialize_account()
    mock_models_response = AsyncMock(spec=httpx.Response)
    mock_models_response.status_code = 200
    mock_models_response.json.return_value = {
        "models": [
            {
                "modelId": "claude-sonnet-4.5",
                "displayName": "Claude Sonnet 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            },
            {
                "modelId": "claude-opus-4.5",
                "displayName": "Claude Opus 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            }
        ]
    }
    mock_models_response.raise_for_status = Mock()

    # Mock streaming response for route tests
    # Used by test_routes_openai.py and test_routes_anthropic.py
    mock_streaming_response = AsyncMock(spec=httpx.Response)
    mock_streaming_response.status_code = 200
    
    # Create proper bytes chunks for streaming (NOT AsyncMock)
    async def mock_aiter_bytes():
        """Generator that yields real bytes chunks, not AsyncMock objects."""
        chunks = [
            b'{"content":"Hello"}',
            b'{"content":" World"}',
            b'{"usage":1.0}',
        ]
        for chunk in chunks:
            yield chunk
    
    mock_streaming_response.aiter_bytes = mock_aiter_bytes
    mock_streaming_response.raise_for_status = Mock()
    mock_streaming_response.aclose = AsyncMock()

    # Mock HTTP methods to return appropriate responses
    # POST: token refresh or streaming (context-dependent)
    # GET/request: ListAvailableModels
    mock_async_client.post = AsyncMock(return_value=mock_token_response)
    mock_async_client.get = AsyncMock(return_value=mock_models_response)
    mock_async_client.request = AsyncMock(return_value=mock_models_response)
    mock_async_client.send = AsyncMock(return_value=mock_streaming_response)
    
    # Mock stream() method for streaming requests
    # Returns a context manager that yields streaming response
    async def mock_stream(*args, **kwargs):
        """Mock stream() method that returns streaming response."""
        class StreamContextManager:
            async def __aenter__(self):
                return mock_streaming_response
            async def __aexit__(self, *args):
                pass
        return StreamContextManager()
    
    mock_async_client.stream = mock_stream
    
    # Mock context manager
    mock_async_client.__aenter__ = AsyncMock(return_value=mock_async_client)
    mock_async_client.__aexit__ = AsyncMock()
    mock_async_client.aclose = AsyncMock()
    mock_async_client.is_closed = False

    # Patch AsyncClient in modules where it's used
    patchers = [
        patch('kiro.auth.httpx.AsyncClient', return_value=mock_async_client),
        patch('kiro.http_client.httpx.AsyncClient', return_value=mock_async_client),
        patch('kiro.streaming_openai.httpx.AsyncClient', return_value=mock_async_client),
        patch('kiro.account_manager.httpx.AsyncClient', return_value=mock_async_client),
    ]
    
    # Start patchers
    for patcher in patchers:
        patcher.start()
    
    print("🛡️ GLOBAL NETWORK BLOCKING ACTIVATED")
    
    yield

    # Stop patchers
    for patcher in patchers:
        patcher.stop()
    
    print("🛡️ GLOBAL NETWORK BLOCKING DEACTIVATED")


# =============================================================================
# Application Fixtures
# =============================================================================

@pytest.fixture
def clean_app():
    """
    Returns a "clean" application instance for each test.
    """
    print("Importing application for test...")
    from main import app
    # Reset all dependency overrides before test
    app.dependency_overrides = {}
    return app


@pytest.fixture
def test_client(clean_app):
    """
    Creates a FastAPI TestClient for synchronous endpoint tests,
    properly handling lifespan events.
    """
    print("Creating TestClient with lifespan support...")
    with TestClient(clean_app) as client:
        yield client
    print("Closing TestClient...")


@pytest.fixture
async def async_test_client(clean_app):
    """
    Creates an asynchronous test client for async endpoints.
    """
    print("Creating async test client...")
    from httpx import AsyncClient, ASGITransport
    
    transport = ASGITransport(app=clean_app)
    async with AsyncClient(transport=transport, base_url="http://test") as client:
        yield client
    
    print("Closing async test client...")


# =============================================================================
# KiroAuthManager Fixtures
# =============================================================================

@pytest.fixture
def mock_auth_manager():
    """
    Creates a mocked KiroAuthManager for tests.
    """
    from kiro.auth import KiroAuthManager
    
    manager = KiroAuthManager(
        refresh_token="test_refresh_token",
        profile_arn="arn:aws:codewhisperer:us-east-1:123456789:profile/test",
        region="us-east-1"
    )
    
    # Set valid token
    manager._access_token = "test_access_token"
    manager._expires_at = datetime.now(timezone.utc).replace(
        year=2099  # Far in the future
    )
    
    return manager


@pytest.fixture
def expired_auth_manager():
    """
    Creates a KiroAuthManager with an expired token.
    """
    from kiro.auth import KiroAuthManager
    
    manager = KiroAuthManager(
        refresh_token="test_refresh_token",
        profile_arn="arn:aws:codewhisperer:us-east-1:123456789:profile/test",
        region="us-east-1"
    )
    
    # Set expired token
    manager._access_token = "expired_token"
    manager._expires_at = datetime.now(timezone.utc).replace(
        year=2020  # In the past
    )
    
    return manager


# =============================================================================
# ModelInfoCache Fixtures
# =============================================================================

@pytest.fixture
def sample_models_data():
    """
    Returns a list of models for testing ModelInfoCache.
    """
    return [
        {
            "modelId": "claude-sonnet-4",
            "displayName": "Claude Sonnet 4",
            "tokenLimits": {
                "maxInputTokens": 200000,
                "maxOutputTokens": 8192
            }
        },
        {
            "modelId": "claude-opus-4.5",
            "displayName": "Claude Opus 4.5",
            "tokenLimits": {
                "maxInputTokens": 200000,
                "maxOutputTokens": 8192
            }
        },
        {
            "modelId": "claude-haiku-4.5",
            "displayName": "Claude Haiku 4.5",
            "tokenLimits": {
                "maxInputTokens": 100000,
                "maxOutputTokens": 4096
            }
        }
    ]


@pytest.fixture
def empty_model_cache():
    """
    Creates an empty ModelInfoCache.
    """
    from kiro.cache import ModelInfoCache
    return ModelInfoCache()


@pytest.fixture
async def populated_model_cache(mock_kiro_models_response):
    """
    Creates a ModelInfoCache with pre-populated data.
    """
    from kiro.cache import ModelInfoCache
    
    cache = ModelInfoCache()
    await cache.update(mock_kiro_models_response["models"])
    return cache


# =============================================================================
# Time Fixtures
# =============================================================================

@pytest.fixture
def mock_time():
    """
    Mocks time.time() for predictable behavior in tests.
    """
    with patch('time.time') as mock:
        # Fixed point in time: 2024-01-01 12:00:00
        mock.return_value = 1704110400.0
        yield mock


@pytest.fixture
def mock_datetime():
    """
    Mocks datetime.now() for predictable behavior.
    """
    fixed_time = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc)
    
    with patch('kiro.auth.datetime') as mock_dt:
        mock_dt.now.return_value = fixed_time
        mock_dt.fromisoformat = datetime.fromisoformat
        mock_dt.fromtimestamp = datetime.fromtimestamp
        yield mock_dt


# =============================================================================
# Temporary File Fixtures
# =============================================================================

@pytest.fixture
def temp_creds_file(tmp_path):
    """
    Creates a temporary credentials file for tests (Kiro Desktop format).
    """
    creds_file = tmp_path / "kiro-auth-token.json"
    creds_data = {
        "accessToken": "file_access_token",
        "refreshToken": "file_refresh_token",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test",
        "region": "us-east-1"
    }
    creds_file.write_text(json.dumps(creds_data))
    return str(creds_file)


@pytest.fixture
def temp_aws_sso_creds_file(tmp_path):
    """
    Creates a temporary credentials file for tests (AWS SSO OIDC format).
    Contains clientId and clientSecret, indicating AWS SSO OIDC authentication.
    """
    creds_file = tmp_path / "aws-sso-cache.json"
    creds_data = {
        "accessToken": "aws_sso_access_token",
        "refreshToken": "aws_sso_refresh_token",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "region": "us-east-1",
        "clientId": "test_client_id_12345",
        "clientSecret": "test_client_secret_67890"
    }
    creds_file.write_text(json.dumps(creds_data))
    return str(creds_file)


@pytest.fixture
def temp_sqlite_db(tmp_path):
    """
    Creates a temporary SQLite database for tests (kiro-cli format).
    
    Contains auth_kv table with keys:
    - 'codewhisperer:odic:token': JSON with access_token, refresh_token, expires_at, region
    - 'codewhisperer:odic:device-registration': JSON with client_id, client_secret
    """
    import sqlite3
    
    db_file = tmp_path / "data.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    # Create auth_kv table
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert token data
    token_data = {
        "access_token": "sqlite_access_token",
        "refresh_token": "sqlite_refresh_token",
        "expires_at": "2099-01-01T00:00:00Z",
        "region": "eu-west-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    
    # Insert device registration data
    registration_data = {
        "client_id": "sqlite_client_id",
        "client_secret": "sqlite_client_secret",
        "region": "eu-west-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:device-registration", json.dumps(registration_data))
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture
def temp_sqlite_db_token_only(tmp_path):
    """
    Creates a SQLite database with token only (without device-registration).
    Used for testing partial loading.
    """
    import sqlite3
    
    db_file = tmp_path / "data_token_only.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    token_data = {
        "access_token": "partial_access_token",
        "refresh_token": "partial_refresh_token",
        "region": "ap-southeast-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture
def temp_sqlite_db_invalid_json(tmp_path):
    """
    Creates a SQLite database with invalid JSON in value.
    Used for testing error handling.
    """
    import sqlite3
    
    db_file = tmp_path / "data_invalid.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert invalid JSON
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", "not a valid json {{{")
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture
def mock_aws_sso_oidc_token_response():
    """
    Factory for creating mock AWS SSO OIDC token endpoint responses.
    """
    def _create_response(
        access_token: str = "new_aws_sso_access_token",
        refresh_token: str = "new_aws_sso_refresh_token",
        expires_in: int = 3600
    ):
        return {
            "accessToken": access_token,
            "refreshToken": refresh_token,
            "expiresIn": expires_in,
            "tokenType": "Bearer"
        }
    return _create_response


@pytest.fixture
def temp_debug_dir(tmp_path):
    """
    Creates a temporary directory for debug files.
    """
    debug_dir = tmp_path / "debug_logs"
    debug_dir.mkdir()
    return debug_dir


# =============================================================================
# Parser Fixtures
# =============================================================================

@pytest.fixture
def aws_event_parser():
    """
    Creates an AwsEventStreamParser instance for tests.
    """
    from kiro.parsers import AwsEventStreamParser
    return AwsEventStreamParser()


# =============================================================================
# Test Utilities
# =============================================================================

def create_kiro_content_chunk(content: str) -> bytes:
    """Utility for creating a Kiro SSE chunk with content."""
    return f'{{"content":"{content}"}}'.encode()


def create_kiro_tool_start_chunk(name: str, tool_id: str) -> bytes:
    """Utility for creating a Kiro SSE chunk with tool call start."""
    return f'{{"name":"{name}","toolUseId":"{tool_id}"}}'.encode()


def create_kiro_tool_input_chunk(input_json: str) -> bytes:
    """Utility for creating a Kiro SSE chunk with tool call input."""
    escaped = input_json.replace('"', '\\"')
    return f'{{"input":"{escaped}"}}'.encode()


def create_kiro_tool_stop_chunk() -> bytes:
    """Utility for creating a Kiro SSE chunk with tool call stop."""
    return b'{"stop":true}'


def create_kiro_usage_chunk(usage: float) -> bytes:
    """Utility for creating a Kiro SSE chunk with usage."""
    return f'{{"usage":{usage}}}'.encode()


def create_kiro_context_usage_chunk(percentage: float) -> bytes:
    """Utility for creating a Kiro SSE chunk with context usage."""
    return f'{{"contextUsagePercentage":{percentage}}}'.encode()


# =============================================================================
# Social Login Fixtures (for new functionality)
# =============================================================================

@pytest.fixture
def temp_sqlite_db_social(tmp_path):
    """
    Creates a temporary SQLite database with social login credentials.
    
    Contains auth_kv table with key:
    - 'kirocli:social:token': JSON with access_token, refresh_token, expires_at, provider
    
    This simulates kiro-cli with Google/GitHub social login (no client_id/client_secret).
    """
    import sqlite3
    
    db_file = tmp_path / "data_social.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    # Create auth_kv table
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert social login token data
    token_data = {
        "access_token": "social_access_token",
        "refresh_token": "social_refresh_token",
        "expires_at": "2099-01-01T00:00:00Z",
        "provider": "google",
        "profile_arn": "arn:aws:codewhisperer:us-east-1:123456789:profile/social",
        "region": "us-east-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("kirocli:social:token", json.dumps(token_data))
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture
def temp_sqlite_db_all_keys(tmp_path):
    """
    Creates a SQLite database with ALL three token keys.
    
    Used for testing key priority:
    1. kirocli:social:token (highest priority)
    2. kirocli:odic:token
    3. codewhisperer:odic:token (lowest priority)
    """
    import sqlite3
    
    db_file = tmp_path / "data_all_keys.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert all three keys with different tokens
    social_data = {
        "access_token": "social_token",
        "refresh_token": "social_refresh",
        "expires_at": "2099-01-01T00:00:00Z",
        "provider": "google"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("kirocli:social:token", json.dumps(social_data))
    )
    
    odic_data = {
        "access_token": "odic_token",
        "refresh_token": "odic_refresh",
        "expires_at": "2099-01-01T00:00:00Z"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("kirocli:odic:token", json.dumps(odic_data))
    )
    
    legacy_data = {
        "access_token": "legacy_token",
        "refresh_token": "legacy_refresh",
        "expires_at": "2099-01-01T00:00:00Z"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(legacy_data))
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


# =============================================================================
# Enterprise Kiro IDE Fixtures (Issue #45)
# =============================================================================

@pytest.fixture
def temp_enterprise_ide_creds_file(tmp_path):
    """
    Creates a temporary credentials file for Enterprise Kiro IDE.
    
    Contains:
    - clientIdHash: Hash used to locate device registration file
    - refreshToken, accessToken, expiresAt, region
    
    This simulates Enterprise Kiro IDE with IdC (AWS IAM Identity Center) login.
    """
    creds_file = tmp_path / "kiro-auth-token.json"
    creds_data = {
        "accessToken": "enterprise_access_token",
        "refreshToken": "enterprise_refresh_token",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/enterprise",
        "region": "us-east-1",
        "clientIdHash": "abc123def456"
    }
    creds_file.write_text(json.dumps(creds_data))
    return str(creds_file)


@pytest.fixture
def temp_enterprise_device_registration(tmp_path):
    """
    Creates a temporary device registration file for Enterprise Kiro IDE.
    
    Located at: ~/.aws/sso/cache/{clientIdHash}.json
    Contains: clientId, clientSecret
    """
    # Create .aws/sso/cache directory structure
    aws_dir = tmp_path / ".aws" / "sso" / "cache"
    aws_dir.mkdir(parents=True, exist_ok=True)
    
    # Create device registration file
    device_reg_file = aws_dir / "abc123def456.json"
    device_reg_data = {
        "clientId": "enterprise_client_id_12345",
        "clientSecret": "enterprise_client_secret_67890",
        "region": "us-east-1"
    }
    device_reg_file.write_text(json.dumps(device_reg_data))
    
    return str(device_reg_file)


@pytest.fixture
def temp_enterprise_ide_complete(tmp_path, monkeypatch):
    """
    Creates a complete Enterprise IDE setup with both credentials and device registration.
    
    Returns tuple: (creds_file_path, device_reg_file_path)
    """
    # Mock Path.home() to return tmp_path
    monkeypatch.setattr('pathlib.Path.home', lambda: tmp_path)
    
    # Create credentials file
    creds_file = tmp_path / "kiro-auth-token.json"
    creds_data = {
        "accessToken": "enterprise_access_token",
        "refreshToken": "enterprise_refresh_token",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/enterprise",
        "region": "us-east-1",
        "clientIdHash": "abc123def456"
    }
    creds_file.write_text(json.dumps(creds_data))
    
    # Create device registration file
    aws_dir = tmp_path / ".aws" / "sso" / "cache"
    aws_dir.mkdir(parents=True, exist_ok=True)
    
    device_reg_file = aws_dir / "abc123def456.json"
    device_reg_data = {
        "clientId": "enterprise_client_id_12345",
        "clientSecret": "enterprise_client_secret_67890",
        "region": "us-east-1"
    }
    device_reg_file.write_text(json.dumps(device_reg_data))
    
    return (str(creds_file), str(device_reg_file))


# =============================================================================
# API Region Auto-Detection Fixtures
# =============================================================================

@pytest.fixture
def temp_sqlite_db_with_profile_arn(tmp_path):
    """
    Creates SQLite database with state table containing profile ARN.
    
    Tables:
    - auth_kv: token data with SSO region=eu-west-1
    - state: profile ARN with API region=eu-central-1
    
    This simulates kiro-cli with profile ARN that has different API region.
    """
    import sqlite3
    
    db_file = tmp_path / "data_with_arn.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    # Create auth_kv table
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert token data with SSO region
    token_data = {
        "access_token": "arn_access_token",
        "refresh_token": "arn_refresh_token",
        "expires_at": "2099-01-01T00:00:00Z",
        "region": "eu-west-1"  # SSO region
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    
    # Insert device registration
    registration_data = {
        "client_id": "test_client_id",
        "client_secret": "test_client_secret",
        "region": "eu-west-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:device-registration", json.dumps(registration_data))
    )
    
    # Create state table with profile ARN
    cursor.execute("""
        CREATE TABLE state (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert profile with ARN containing different API region
    profile_data = {
        "arn": "arn:aws:codewhisperer:eu-central-1:123456789012:profile/test-profile",
        "name": "test-profile"
    }
    cursor.execute(
        "INSERT INTO state (key, value) VALUES (?, ?)",
        ("api.codewhisperer.profile", json.dumps(profile_data))
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture
def temp_sqlite_db_with_empty_state_table(tmp_path):
    """
    Creates SQLite database with empty state table (no profile key).
    
    Used for testing fallback behavior when state table exists but has no profile.
    """
    import sqlite3
    
    db_file = tmp_path / "data_empty_state.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    # Create auth_kv table
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert token data
    token_data = {
        "access_token": "empty_state_access",
        "refresh_token": "empty_state_refresh",
        "expires_at": "2099-01-01T00:00:00Z",
        "region": "us-west-2"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    
    # Create empty state table
    cursor.execute("""
        CREATE TABLE state (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture(params=[
    "not-an-arn",
    "arn:aws:codewhisperer",
    "arn:aws:codewhisperer:INVALID_REGION:account:profile",
    "arn:aws:codewhisperer::account:profile",
])
def temp_sqlite_db_with_invalid_arn(tmp_path, request):
    """
    Creates SQLite database with invalid ARN formats.
    
    Parametrized fixture that tests various invalid ARN formats:
    - Not an ARN at all
    - Too short ARN
    - Invalid region format
    - Empty region
    """
    import sqlite3
    
    db_file = tmp_path / f"data_invalid_arn_{request.param_index}.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    # Create auth_kv table
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert token data
    token_data = {
        "access_token": "invalid_arn_access",
        "refresh_token": "invalid_arn_refresh",
        "expires_at": "2099-01-01T00:00:00Z",
        "region": "ap-southeast-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    
    # Create state table with invalid ARN
    cursor.execute("""
        CREATE TABLE state (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    profile_data = {
        "arn": request.param,  # Invalid ARN from parametrize
        "name": "test-profile"
    }
    cursor.execute(
        "INSERT INTO state (key, value) VALUES (?, ?)",
        ("api.codewhisperer.profile", json.dumps(profile_data))
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


@pytest.fixture
def temp_sqlite_db_with_malformed_state_json(tmp_path):
    """
    Creates SQLite database with malformed JSON in state table.
    
    Used for testing graceful error handling when state table contains invalid JSON.
    """
    import sqlite3
    
    db_file = tmp_path / "data_malformed_state.sqlite3"
    conn = sqlite3.connect(str(db_file))
    cursor = conn.cursor()
    
    # Create auth_kv table
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert token data
    token_data = {
        "access_token": "malformed_state_access",
        "refresh_token": "malformed_state_refresh",
        "expires_at": "2099-01-01T00:00:00Z",
        "region": "ap-south-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    
    # Create state table with malformed JSON
    cursor.execute("""
        CREATE TABLE state (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    
    # Insert malformed JSON
    cursor.execute(
        "INSERT INTO state (key, value) VALUES (?, ?)",
        ("api.codewhisperer.profile", "not a valid json {{{")
    )
    
    conn.commit()
    conn.close()
    
    return str(db_file)


# =============================================================================
# Account System Fixtures
# =============================================================================

@pytest.fixture
def sample_credentials_single_account():
    """
    Sample credentials.json with single account (JSON type).
    """
    return [
        {
            "type": "json",
            "path": "~/.aws/sso/cache/kiro-auth-token.json",
            "enabled": True
        }
    ]


@pytest.fixture
def sample_credentials_multi_account():
    """
    Sample credentials.json with multiple accounts (different types).
    """
    return [
        {
            "type": "json",
            "path": "~/.aws/sso/cache/main.json",
            "enabled": True
        },
        {
            "type": "sqlite",
            "path": "~/.local/share/kiro-cli/data.sqlite3",
            "enabled": True
        },
        {
            "type": "refresh_token",
            "refresh_token": "eyJhbGc...",
            "profile_arn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test",
            "region": "us-east-1",
            "enabled": True
        }
    ]


@pytest.fixture
def sample_credentials_with_folder():
    """
    Sample credentials.json with folder scanning.
    """
    return [
        {
            "type": "json",
            "path": "/home/user/kiro-accounts/",
            "enabled": True
        }
    ]


@pytest.fixture
def sample_credentials_with_disabled():
    """
    Sample credentials.json with disabled account.
    """
    return [
        {
            "type": "json",
            "path": "~/.aws/sso/cache/main.json",
            "enabled": True
        },
        {
            "type": "json",
            "path": "~/.aws/sso/cache/disabled.json",
            "enabled": False
        }
    ]


@pytest.fixture
def sample_credentials_with_overrides():
    """
    Sample credentials.json with per-account region overrides.
    """
    return [
        {
            "type": "json",
            "path": "~/.aws/sso/cache/eu-account.json",
            "enabled": True,
            "profile_arn": "arn:aws:codewhisperer:eu-central-1:123456789:profile/eu",
            "region": "eu-west-1",
            "api_region": "eu-central-1"
        }
    ]


@pytest.fixture
def sample_state_empty():
    """
    Empty state.json (initial state).
    """
    return {
        "current_account_index": 0,
        "model_to_accounts": {},
        "accounts": {}
    }


@pytest.fixture
def sample_state_with_data():
    """
    Sample state.json with runtime data.
    """
    return {
        "current_account_index": 0,
        "model_to_accounts": {
            "claude-opus-4.5": {
                "accounts": [
                    "/home/user/.aws/sso/cache/main.json",
                    "/home/user/.local/share/kiro-cli/data.sqlite3"
                ]
            },
            "claude-sonnet-4.5": {
                "accounts": ["/home/user/.aws/sso/cache/main.json"]
            }
        },
        "accounts": {
            "/home/user/.aws/sso/cache/main.json": {
                "failures": 0,
                "last_failure_time": 0.0,
                "models_cached_at": 1704110400.0,
                "stats": {
                    "total_requests": 150,
                    "successful_requests": 145,
                    "failed_requests": 5
                }
            },
            "/home/user/.local/share/kiro-cli/data.sqlite3": {
                "failures": 2,
                "last_failure_time": 1704114000.0,
                "models_cached_at": 1704106800.0,
                "stats": {
                    "total_requests": 50,
                    "successful_requests": 48,
                    "failed_requests": 2
                }
            }
        }
    }


@pytest.fixture
def sample_state_with_failures():
    """
    Sample state.json with account failures (Circuit Breaker state).
    """
    return {
        "current_account_index": 0,
        "model_to_accounts": {
            "claude-opus-4.5": {
                "accounts": [
                    "/home/user/.aws/sso/cache/main.json",
                    "/home/user/.aws/sso/cache/backup.json"
                ]
            }
        },
        "accounts": {
            "/home/user/.aws/sso/cache/main.json": {
                "failures": 5,
                "last_failure_time": 1704110400.0,
                "models_cached_at": 1704106800.0,
                "stats": {
                    "total_requests": 100,
                    "successful_requests": 95,
                    "failed_requests": 5
                }
            },
            "/home/user/.aws/sso/cache/backup.json": {
                "failures": 0,
                "last_failure_time": 0.0,
                "models_cached_at": 1704110400.0,
                "stats": {
                    "total_requests": 10,
                    "successful_requests": 10,
                    "failed_requests": 0
                }
            }
        }
    }


@pytest.fixture
def temp_credentials_json(tmp_path, sample_credentials_single_account):
    """
    Creates a temporary credentials.json file.
    
    Factory fixture that accepts credentials data.
    """
    def _create_file(credentials_data=None):
        if credentials_data is None:
            credentials_data = sample_credentials_single_account
        
        creds_file = tmp_path / "credentials.json"
        creds_file.write_text(json.dumps(credentials_data, indent=2))
        return str(creds_file)
    
    return _create_file


@pytest.fixture
def temp_state_json(tmp_path, sample_state_empty):
    """
    Creates a temporary state.json file.
    
    Factory fixture that accepts state data.
    """
    def _create_file(state_data=None):
        if state_data is None:
            state_data = sample_state_empty
        
        state_file = tmp_path / "state.json"
        state_file.write_text(json.dumps(state_data, indent=2))
        return str(state_file)
    
    return _create_file


@pytest.fixture
def temp_credentials_folder(tmp_path):
    """
    Creates a temporary folder with multiple credential files.
    
    Returns tuple: (folder_path, list_of_created_files)
    """
    folder = tmp_path / "kiro-accounts"
    folder.mkdir()
    
    # Create valid JSON credentials
    valid_file1 = folder / "account1.json"
    valid_file1.write_text(json.dumps({
        "accessToken": "token1",
        "refreshToken": "refresh1",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test1",
        "region": "us-east-1"
    }))
    
    valid_file2 = folder / "account2.json"
    valid_file2.write_text(json.dumps({
        "accessToken": "token2",
        "refreshToken": "refresh2",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test2",
        "region": "us-east-1"
    }))
    
    # Create invalid file (should be skipped)
    invalid_file = folder / "invalid.json"
    invalid_file.write_text("not a valid json {{{")
    
    # Create non-JSON file (should be skipped)
    text_file = folder / "readme.txt"
    text_file.write_text("This is not a credentials file")
    
    return (str(folder), [str(valid_file1), str(valid_file2)])


@pytest.fixture
def mock_account():
    """
    Creates a mock Account object with all dependencies.
    """
    from kiro.account_manager import Account, AccountStats
    from kiro.auth import KiroAuthManager
    from kiro.cache import ModelInfoCache
    from kiro.model_resolver import ModelResolver
    
    # Create mock auth_manager
    auth_manager = KiroAuthManager(
        refresh_token="test_refresh_token",
        profile_arn="arn:aws:codewhisperer:us-east-1:123456789:profile/test",
        region="us-east-1"
    )
    auth_manager._access_token = "test_access_token"
    auth_manager._expires_at = datetime(2099, 1, 1, tzinfo=timezone.utc)
    
    # Create mock model_cache
    model_cache = ModelInfoCache()
    
    # Create mock model_resolver
    model_resolver = ModelResolver(
        cache=model_cache,
        hidden_models={},
        aliases={},
        hidden_from_list=set()
    )
    
    # Create Account
    account = Account(
        id="/home/user/.aws/sso/cache/test.json",
        auth_manager=auth_manager,
        model_cache=model_cache,
        model_resolver=model_resolver,
        failures=0,
        last_failure_time=0.0,
        models_cached_at=time.time(),
        stats=AccountStats()
    )
    
    return account


@pytest.fixture
def mock_account_manager(tmp_path):
    """
    Creates a mock AccountManager with temporary files.
    
    Factory fixture that accepts credentials and state data.
    """
    async def _create_manager(credentials_data=None, state_data=None):
        from kiro.account_manager import AccountManager
        
        # Create temporary files
        creds_file = tmp_path / "credentials.json"
        state_file = tmp_path / "state.json"
        
        if credentials_data is None:
            credentials_data = [
                {
                    "type": "json",
                    "path": str(tmp_path / "test.json"),
                    "enabled": True
                }
            ]
            # Create the test.json file
            test_creds = tmp_path / "test.json"
            test_creds.write_text(json.dumps({
                "accessToken": "test_token",
                "refreshToken": "test_refresh",
                "expiresAt": "2099-01-01T00:00:00.000Z",
                "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test",
                "region": "us-east-1"
            }))
        
        creds_file.write_text(json.dumps(credentials_data, indent=2))
        
        if state_data is not None:
            state_file.write_text(json.dumps(state_data, indent=2))
        
        # Create AccountManager
        manager = AccountManager(
            credentials_file=str(creds_file),
            state_file=str(state_file)
        )
        
        return manager
    
    return _create_manager


@pytest.fixture
def mock_list_models_response():
    """
    Mock response from Kiro API /ListAvailableModels endpoint.
    
    Returns list of models for account initialization.
    """
    return {
        "models": [
            {
                "modelId": "claude-opus-4.5",
                "displayName": "Claude Opus 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            },
            {
                "modelId": "claude-sonnet-4.5",
                "displayName": "Claude Sonnet 4.5",
                "tokenLimits": {
                    "maxInputTokens": 200000,
                    "maxOutputTokens": 8192
                }
            },
            {
                "modelId": "claude-haiku-4.5",
                "displayName": "Claude Haiku 4.5",
                "tokenLimits": {
                    "maxInputTokens": 100000,
                    "maxOutputTokens": 4096
                }
            }
        ]
    }


@pytest.fixture
def mock_kiro_error_response():
    """
    Factory for creating mock Kiro API error responses.
    """
    def _create_error(status_code: int, reason: str = None, message: str = None):
        error_data = {
            "message": message or "Improperly formed request."
        }
        if reason:
            error_data["reason"] = reason
        
        return {
            "status_code": status_code,
            "json": error_data,
            "text": json.dumps(error_data)
        }
    
    return _create_error


@pytest.fixture
def temp_account_credentials_files(tmp_path):
    """
    Creates multiple temporary credential files for multi-account testing.
    
    Returns dict with account_id -> file_path mapping.
    """
    files = {}
    
    # Account 1: JSON (Kiro Desktop)
    account1 = tmp_path / "account1.json"
    account1.write_text(json.dumps({
        "accessToken": "token1",
        "refreshToken": "refresh1",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "profileArn": "arn:aws:codewhisperer:us-east-1:123456789:profile/test1",
        "region": "us-east-1"
    }))
    files["account1"] = str(account1)
    
    # Account 2: JSON (AWS SSO OIDC)
    account2 = tmp_path / "account2.json"
    account2.write_text(json.dumps({
        "accessToken": "token2",
        "refreshToken": "refresh2",
        "expiresAt": "2099-01-01T00:00:00.000Z",
        "region": "us-east-1",
        "clientId": "client_id_2",
        "clientSecret": "client_secret_2"
    }))
    files["account2"] = str(account2)
    
    # Account 3: SQLite
    import sqlite3
    account3 = tmp_path / "account3.sqlite3"
    conn = sqlite3.connect(str(account3))
    cursor = conn.cursor()
    cursor.execute("""
        CREATE TABLE auth_kv (
            key TEXT PRIMARY KEY,
            value TEXT
        )
    """)
    token_data = {
        "access_token": "token3",
        "refresh_token": "refresh3",
        "expires_at": "2099-01-01T00:00:00Z",
        "region": "us-east-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:token", json.dumps(token_data))
    )
    registration_data = {
        "client_id": "client_id_3",
        "client_secret": "client_secret_3",
        "region": "us-east-1"
    }
    cursor.execute(
        "INSERT INTO auth_kv (key, value) VALUES (?, ?)",
        ("codewhisperer:odic:device-registration", json.dumps(registration_data))
    )
    conn.commit()
    conn.close()
    files["account3"] = str(account3)
    
    return files
