# src/content_understanding_client/client.py

import json
import time
import logging
import requests


class ContentUnderstandingClient:
    def __init__(self, endpoint: str, api_key: str, api_version: str):
        logging.info("Initializing ContentUnderstandingClient")

        if not endpoint or not api_key or not api_version:
            raise ValueError("endpoint, api_key, and api_version are required")

        self.endpoint = endpoint.rstrip("/")
        self.api_key = api_key
        self.api_version = api_version

        self.base_headers = {
            "Ocp-Apim-Subscription-Key": api_key,
        }

        # ✅ CRITICAL — Connection Reuse
        self.session = requests.Session()

        # Retry configuration
        self.max_retries = 4
        self.timeout_seconds = 15

    # ---------------------------------------------------------
    # GENERIC RESILIENT REQUEST (Core Stability Mechanism)
    # ---------------------------------------------------------
    def _request_with_retry(self, method, url, **kwargs):

        for attempt in range(self.max_retries):
            try:
                response = self.session.request(
                    method,
                    url,
                    timeout=self.timeout_seconds,
                    **kwargs,
                )

                response.raise_for_status()
                return response

            except requests.exceptions.RequestException as e:

                if attempt == self.max_retries - 1:
                    logging.error(f"HTTP request failed permanently: {e}")
                    raise

                sleep_time = 2 ** attempt
                logging.warning(
                    f"Transient HTTP failure (attempt {attempt+1}): {e}"
                )
                logging.info(f"Retrying in {sleep_time}s...")

                time.sleep(sleep_time)

    # ---------------------------------------------------------
    # BEGIN ANALYZE
    # ---------------------------------------------------------
    def begin_analyze(self, analyzer_id: str, file_bytes: bytes):

        analyze_url = (
            f"{self.endpoint}/contentunderstanding/analyzers/"
            f"{analyzer_id}:analyze?api-version={self.api_version}"
        )

        headers = {
            "Content-Type": "application/octet-stream",
            **self.base_headers,
        }

        response = self._request_with_retry(
            "POST",
            analyze_url,
            headers=headers,
            data=file_bytes,
        )

        operation_location = response.headers.get("operation-location")
        if not operation_location:
            raise RuntimeError("operation-location header missing")

        return operation_location

    # ---------------------------------------------------------
    # POLL RESULT
    # ---------------------------------------------------------
    def poll_result(
        self,
        operation_location: str,
        polling_interval_seconds: int = 2,
    ):

        consecutive_failures = 0
        MAX_CONSECUTIVE_FAILURES = 8   # ✅ CRITICAL SAFETY

        while True:

            try:
                response = self._request_with_retry(
                    "GET",
                    operation_location,
                    headers=self.base_headers,
                )

                consecutive_failures = 0   # ✅ RESET on success

                result = response.json()
                status = result.get("status", "").lower()

                if status == "succeeded":
                    logging.info("CU analysis succeeded")
                    return result

                if status == "failed":
                    raise RuntimeError(
                        f"Analysis failed: {json.dumps(result, indent=2)}"
                    )

            except Exception as e:

                consecutive_failures += 1

                logging.warning(
                    f"Polling failure ({consecutive_failures}): {e}"
                )

                if consecutive_failures >= MAX_CONSECUTIVE_FAILURES:
                    logging.error("Polling failed permanently")
                    raise RuntimeError(
                        "Polling aborted due to persistent failure"
                    )

            time.sleep(polling_interval_seconds)

