import logging
import requests
from typing import Dict, Any, Optional, List
from .exceptions import (
    RecommerceConnectionError,
    RecommerceAuthError,
    RecommerceAPIError
)

logger = logging.getLogger(__name__)


class RecommerceClient:
    """
    Низкоуровневый клиент для работы с Recommerce API.
    Отвечает только за HTTP запросы и обработку ошибок.
    """

    def __init__(self, store_url: str, api_token: str, timeout: int = 15):
        self.store_url = store_url.rstrip('/')
        self.api_token = api_token
        self.timeout = timeout
        self.base_url = f"{self.store_url}/api/v1"

    def _get_headers(self) -> Dict[str, str]:
        """Заголовки для API запросов"""
        # HTTP заголовки должны быть ASCII-совместимыми
        try:
            token = self.api_token.encode('ascii', 'ignore').decode('ascii')
        except (AttributeError, ValueError):
            token = ''

        return {
            'x-auth-token': token,
            'Accept': 'application/json',
            # НЕ указываем Content-Type - requests сам поставит правильный:
            # - application/x-www-form-urlencoded для data=...
            # - application/json для json=...
        }

    def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
        """
        Выполнение HTTP запроса.
        
        Args:
            method: HTTP метод (GET, POST, DELETE, etc)
            endpoint: Путь относительно /api/v1/ (напр. 'catalog/products')
            **kwargs: Аргументы для requests (params, json, data, etc)
            
        Returns:
            Dict: Ответ API (JSON)
            
        Raises:
            RecommerceConnectionError: Ошибка сети
            RecommerceAuthError: Ошибка авторизации (401, 403)
            RecommerceAPIError: Другие ошибки API (4xx, 5xx)
        """
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        headers = self._get_headers()
        
        # Если переданы headers в kwargs, обновляем их, а не перезаписываем
        if 'headers' in kwargs:
            headers.update(kwargs.pop('headers'))

        try:
            response = requests.request(
                method,
                url,
                headers=headers,
                timeout=self.timeout,
                **kwargs
            )
            
            if response.status_code in [200, 201, 204]:
                if not response.content:
                    return {}
                try:
                    return response.json()
                except ValueError:
                    return {}
            
            # Обработка ошибок
            if response.status_code in [401, 403]:
                raise RecommerceAuthError(f"Auth Error: {response.status_code}")
            
            logger.error(f"Recommerce API error {response.status_code}: {response.text}")
            raise RecommerceAPIError(
                status_code=response.status_code,
                message=f"API Request failed: {url}",
                response_body=response.text
            )

        except requests.exceptions.Timeout:
            raise RecommerceConnectionError("Connection timeout")
        except requests.exceptions.ConnectionError:
            raise RecommerceConnectionError("Connection failed")
        except requests.exceptions.RequestException as e:
            raise RecommerceConnectionError(f"Network error: {str(e)}")

    def get_product(self, sku: str) -> Dict[str, Any]:
        """Получить товар по SKU"""
        return self._request('GET', f'catalog/products/{sku}')

    def update_product(self, sku: str, data: Dict[str, Any]) -> Dict[str, Any]:
        """Обновить товар (использует form-data как указано в документации)"""
        # Recommerce API требует form-data для POST запросов
        # data должен быть плоским словарём с ключами вида price[amount], price[currency]
        logger.info(f"Recommerce update_product {sku}: {data}")
        logger.debug(f"Data types in update_product: {[(k, type(v).__name__) for k, v in data.items()]}")
        return self._request('POST', f'catalog/products/{sku}', data=data)

    def create_product(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """Создать товар (использует form-data как указано в документации)"""
        # Recommerce API требует form-data для POST запросов
        return self._request('POST', 'catalog/products', data=data)

    def get_orders(self, updated_after: Optional[str] = None) -> List[Dict[str, Any]]:
        """
        Получить список заказов.
        
        Args:
            updated_after: Дата в формате 'Y-m-d-H-i-s'
        """
        params = {'page': 1}
        if updated_after:
            params['updated_after'] = updated_after
            
        # Recommerce возвращает пагинацию. 
        # Для простоты пока берем первую страницу, но в идеале нужно итерироваться.
        # В рамках "простой" интеграции пока оставим 1 страницу (последние 50-100 заказов).
        response = self._request('GET', 'orders', params=params)
        return response.get('data', [])

    def get_order(self, order_id: int) -> Dict[str, Any]:
        """Получить заказ по ID"""
        # В документации нет отдельного эндпоинта для одного заказа, 
        # но обычно в REST API он есть. Если нет - этот метод упадет с 404.
        # Предположим что он есть для полноты клиента.
        return self._request('GET', f'orders/{order_id}')