"""
ATS SDK - HTTP Client
"""

import time
import requests
from typing import Any, Dict, Optional
from .config import ATSConfig
from .exceptions import (
    ATSError, AuthenticationError, AuthorizationError,
    NotFoundError, ValidationError, RateLimitError, NetworkError
)


class HTTPClient:
    def __init__(self, config: ATSConfig):
        self.config = config
        self.session = requests.Session()
        self.session.headers.update(self._build_headers())

    def _build_headers(self) -> Dict[str, str]:
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "User-Agent": "ats-python-sdk/1.0.0",
        }
        if self.config.api_key:
            headers["X-API-Key"] = self.config.api_key
        elif self.config.access_token:
            headers["Authorization"] = f"Bearer {self.config.access_token}"
        return headers

    def _url(self, path: str) -> str:
        base = self.config.base_url.rstrip("/")
        return f"{base}/{path.lstrip('/')}"

    def _handle_response(self, response: requests.Response) -> Any:
        if response.status_code == 204:
            return None
        try:
            data = response.json()
        except Exception:
            data = {"message": response.text}

        if response.status_code == 401:
            raise AuthenticationError(data.get("error", {}).get("message", "Authentication required"))
        if response.status_code == 403:
            raise AuthorizationError(data.get("error", {}).get("message", "Forbidden"))
        if response.status_code == 404:
            raise NotFoundError(data.get("error", {}).get("message", "Not found"))
        if response.status_code == 422:
            raise ValidationError(data.get("error", {}).get("message", "Validation error"))
        if response.status_code == 429:
            raise RateLimitError(data.get("error", {}).get("message", "Rate limit exceeded"))
        if response.status_code >= 400:
            raise ATSError(data.get("error", {}).get("message", f"HTTP {response.status_code}"))
        return data

    def _request(self, method: str, path: str, **kwargs) -> Any:
        url = self._url(path)
        last_error = None
        for attempt in range(self.config.max_retries):
            try:
                resp = self.session.request(
                    method, url,
                    timeout=self.config.timeout,
                    **kwargs
                )
                return self._handle_response(resp)
            except (AuthenticationError, AuthorizationError, NotFoundError, ValidationError):
                raise
            except ATSError as e:
                last_error = e
                if attempt < self.config.max_retries - 1:
                    time.sleep(self.config.retry_delay * (2 ** attempt))
            except requests.RequestException as e:
                last_error = NetworkError(str(e))
                if attempt < self.config.max_retries - 1:
                    time.sleep(self.config.retry_delay * (2 ** attempt))
        raise last_error

    def get(self, path: str, params: Optional[Dict] = None) -> Any:
        return self._request("GET", path, params=params)

    def post(self, path: str, json: Optional[Dict] = None) -> Any:
        return self._request("POST", path, json=json)

    def put(self, path: str, json: Optional[Dict] = None) -> Any:
        return self._request("PUT", path, json=json)

    def patch(self, path: str, json: Optional[Dict] = None) -> Any:
        return self._request("PATCH", path, json=json)

    def delete(self, path: str) -> Any:
        return self._request("DELETE", path)
