"""Internal protobuf-to-model converters used by sync/async clients."""

from __future__ import annotations

from ._generated import kyrodb_pb2 as pb2
from .models import (
    BatchDeleteResult,
    BulkLoadResult,
    BulkQueryResult,
    ConfigResult,
    DeleteResult,
    FlushResult,
    HealthResult,
    InsertAck,
    MetricsResult,
    QueryResult,
    SearchHit,
    SearchResponse,
    SnapshotResult,
    UpdateMetadataResult,
)


def to_insert_ack(response: pb2.InsertResponse) -> InsertAck:
    return InsertAck(
        success=response.success,
        inserted_at=response.inserted_at,
        total_inserted=response.total_inserted,
        total_failed=response.total_failed,
        tier=pb2.InsertResponse.Tier.Name(response.tier),
        error=response.error,
    )


def to_bulk_load_result(response: pb2.BulkLoadResponse) -> BulkLoadResult:
    return BulkLoadResult(
        success=response.success,
        error=response.error,
        total_loaded=response.total_loaded,
        total_failed=response.total_failed,
        load_duration_ms=response.load_duration_ms,
        avg_insert_rate=response.avg_insert_rate,
        peak_memory_bytes=response.peak_memory_bytes,
    )


def to_delete_result(response: pb2.DeleteResponse) -> DeleteResult:
    return DeleteResult(success=response.success, error=response.error, existed=response.existed)


def to_update_metadata_result(response: pb2.UpdateMetadataResponse) -> UpdateMetadataResult:
    return UpdateMetadataResult(
        success=response.success,
        error=response.error,
        existed=response.existed,
    )


def to_query_result(response: pb2.QueryResponse) -> QueryResult:
    return QueryResult(
        found=response.found,
        doc_id=response.doc_id,
        metadata=dict(response.metadata),
        embedding=tuple(response.embedding) if response.embedding else None,
        served_from=pb2.QueryResponse.Tier.Name(response.served_from),
        error=response.error,
    )


def to_search_response(response: pb2.SearchResponse) -> SearchResponse:
    return SearchResponse(
        results=tuple(
            SearchHit(
                doc_id=result.doc_id,
                score=result.score,
                metadata=dict(result.metadata),
                embedding=tuple(result.embedding) if result.embedding else None,
            )
            for result in response.results
        ),
        total_found=response.total_found,
        search_latency_ms=response.search_latency_ms,
        search_path=pb2.SearchResponse.SearchPath.Name(response.search_path),
        error=response.error,
    )


def to_bulk_query_result(response: pb2.BulkQueryResponse) -> BulkQueryResult:
    return BulkQueryResult(
        results=tuple(to_query_result(item) for item in response.results),
        total_found=response.total_found,
        total_requested=response.total_requested,
        error=response.error,
    )


def to_batch_delete_result(response: pb2.BatchDeleteResponse) -> BatchDeleteResult:
    return BatchDeleteResult(
        success=response.success,
        deleted_count=response.deleted_count,
        error=response.error,
    )


def to_health_result(response: pb2.HealthResponse) -> HealthResult:
    return HealthResult(
        status=pb2.HealthResponse.Status.Name(response.status),
        version=response.version,
        components=dict(response.components),
        uptime_seconds=response.uptime_seconds,
        git_commit=response.git_commit,
    )


def to_metrics_result(response: pb2.MetricsResponse) -> MetricsResult:
    return MetricsResult(
        cache_hits=response.cache_hits,
        cache_misses=response.cache_misses,
        cache_hit_rate=response.cache_hit_rate,
        cache_size=response.cache_size,
        hot_tier_hits=response.hot_tier_hits,
        hot_tier_misses=response.hot_tier_misses,
        hot_tier_hit_rate=response.hot_tier_hit_rate,
        hot_tier_size=response.hot_tier_size,
        hot_tier_flushes=response.hot_tier_flushes,
        cold_tier_searches=response.cold_tier_searches,
        cold_tier_size=response.cold_tier_size,
        p50_latency_ms=response.p50_latency_ms,
        p95_latency_ms=response.p95_latency_ms,
        p99_latency_ms=response.p99_latency_ms,
        total_queries=response.total_queries,
        total_inserts=response.total_inserts,
        queries_per_second=response.queries_per_second,
        inserts_per_second=response.inserts_per_second,
        memory_usage_bytes=response.memory_usage_bytes,
        disk_usage_bytes=response.disk_usage_bytes,
        cpu_usage_percent=response.cpu_usage_percent,
        overall_hit_rate=response.overall_hit_rate,
        collected_at=response.collected_at,
    )


def to_flush_result(response: pb2.FlushResponse) -> FlushResult:
    return FlushResult(
        success=response.success,
        error=response.error,
        documents_flushed=response.documents_flushed,
        flush_duration_ms=response.flush_duration_ms,
    )


def to_snapshot_result(response: pb2.SnapshotResponse) -> SnapshotResult:
    return SnapshotResult(
        success=response.success,
        error=response.error,
        snapshot_path=response.snapshot_path,
        documents_snapshotted=response.documents_snapshotted,
        snapshot_size_bytes=response.snapshot_size_bytes,
    )


def to_config_result(response: pb2.ConfigResponse) -> ConfigResult:
    return ConfigResult(
        hot_tier_max_size=response.hot_tier_max_size,
        hot_tier_max_age_seconds=response.hot_tier_max_age_seconds,
        hnsw_max_elements=response.hnsw_max_elements,
        data_dir=response.data_dir,
        fsync_policy=response.fsync_policy,
        snapshot_interval=response.snapshot_interval,
        flush_interval_seconds=response.flush_interval_seconds,
        embedding_dimension=response.embedding_dimension,
        version=response.version,
        hnsw_m=response.hnsw_m,
        hnsw_ef_construction=response.hnsw_ef_construction,
        hnsw_ef_search=response.hnsw_ef_search,
        hnsw_distance=response.hnsw_distance,
        hnsw_disable_normalization_check=response.hnsw_disable_normalization_check,
    )
