import gzip
import json
import logging
from importlib.metadata import version
from typing import Any

import httpx

logger = logging.getLogger(__name__)

VERSION = version("earlyai-agent")


async def post_generate_prompt(
    api_base_url: str,
    jwt_token: str,
    payload: dict[str, Any],
    request_id: str,
    request_source: str = "cli",
) -> dict[str, Any]:
    body = json.dumps(payload).encode("utf-8")
    compressed = gzip.compress(body)
    headers = {
        "Content-Type": "application/json",
        "Content-Encoding": "gzip",
        "x-client-name": "py-agent",
        "x-client-version": VERSION,
        "x-request-id": request_id,
        "x-request-source": request_source,
        "authorization": f"Bearer {jwt_token}",
    }
    async with httpx.AsyncClient(timeout=120.0) as client:
        response = await client.post(
            f"{api_base_url}/api/v1/tests/generate-prompt",
            content=compressed,
            headers=headers,
        )
        if not response.is_success:
            logger.error(f"generate-prompt failed {response.status_code}: {response.text}")
        response.raise_for_status()
        result: dict[str, Any] = response.json()
        return result


async def post_update_operation_metrics(
    api_base_url: str,
    jwt_token: str,
    request_id: str,
    request_source: str = "CLI",
    *,
    final_green_tests_count: int = 0,
    final_test_counters: dict[str, int] | None = None,
    time_elapsed: int | None = None,
    metadata_collection_time: int | None = None,
    response_processing_time: int | None = None,
    git_url: str | None = None,
    final_test_result: dict[str, Any] | None = None,
    prompt: str | None = None,
    workflow_run_id: str | None = None,
    file_path: str | None = None,
    testable_name: str | None = None,
    class_name: str | None = None,
    language: str | None = None,
    test_framework: str | None = None,
    cost: float | None = None,
    request_tokens_count: int | None = None,
    response_tokens_count: int | None = None,
    cache_creation_input_tokens: int | None = None,
    cache_read_input_tokens: int | None = None,
    error_cause: str | None = None,
) -> None:
    """Report per-method operation metrics to the backend.

    Mirrors ts-agent's MetricReportService.saveTestMetrics() for the SDK path.
    Errors are logged but never raised — metrics reporting must not block generation.
    """
    if final_test_counters is None:
        final_test_counters = {
            "greenTestsCount": 0,
            "greyTestsCount": 0,
            "redTestsCount": 0,
            "naTestsCount": 0,
            "errorSuitsCount": 0,
            "lintErrorsCount": 0,
            "whiteTestsCount": 0,
        }

    payload: dict[str, Any] = {
        "finalGreenTestsCount": final_green_tests_count,
        "finalTestCounters": final_test_counters,
        "greenTestsCount": final_test_counters.get("greenTestsCount", 0),
        "greyTestsCount": final_test_counters.get("greyTestsCount", 0),
        "redTestsCount": final_test_counters.get("redTestsCount", 0),
        "naTestsCount": final_test_counters.get("naTestsCount", 0),
        "errorSuitsCount": final_test_counters.get("errorSuitsCount", 0),
        "whiteTestsCount": final_test_counters.get("whiteTestsCount", 0),
    }
    if time_elapsed is not None:
        payload["timeElapsed"] = time_elapsed
    if metadata_collection_time is not None:
        payload["metadataCollectionTime"] = metadata_collection_time
    if response_processing_time is not None:
        payload["responseProcessingTime"] = response_processing_time
    if git_url is not None:
        payload["gitUrl"] = git_url
    if final_test_result is not None:
        payload["finalTestResult"] = final_test_result
    if prompt is not None:
        payload["prompt"] = prompt
    if workflow_run_id is not None:
        payload["githubActionWorkflowRunId"] = workflow_run_id
    if file_path is not None:
        payload["filePath"] = file_path
    if testable_name is not None:
        payload["testableName"] = testable_name
    if class_name is not None:
        payload["className"] = class_name
    if language is not None:
        payload["language"] = language
    if test_framework is not None:
        payload["testFramework"] = test_framework
    if cost is not None:
        payload["cost"] = cost
    if request_tokens_count is not None:
        payload["requestTokensCount"] = request_tokens_count
    if response_tokens_count is not None:
        payload["responseTokensCount"] = response_tokens_count
    if cache_creation_input_tokens is not None:
        payload["cacheCreationInputTokens"] = cache_creation_input_tokens
    if cache_read_input_tokens is not None:
        payload["cacheReadInputTokens"] = cache_read_input_tokens
    if error_cause is not None:
        payload["errorCause"] = error_cause
    headers = {
        "Content-Type": "application/json",
        "x-client-name": "py-agent",
        "x-client-version": VERSION,
        "x-request-id": request_id,
        "x-request-source": request_source,
        "authorization": f"Bearer {jwt_token}",
    }
    try:
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{api_base_url}/api/v1/tests/update-operation-metrics",
                json=payload,
                headers=headers,
            )
            if not response.is_success:
                logger.warning(
                    f"update-operation-metrics failed {response.status_code}: {response.text}"
                )
    except Exception:
        logger.exception(f"Failed to report operation metrics for request {request_id}")
