"""
Клиент для работы с VK API
"""

import requests
import logging
import time
import os
from typing import Dict, Any, Optional, List
from .config import VKConfig, AppConfig

# Настраиваем логирование
logging.basicConfig(
    level=logging.DEBUG if AppConfig.DEBUG else logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(f'{AppConfig.LOG_DIR}/vk_client.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

class VKClient:
    """
    Клиент для работы с VK API
    """
    
    def __init__(self, token: Optional[str] = None, group_id: Optional[int] = None):
        """
        Инициализация клиента VK API
        
        Args:
            token: Токен доступа (если не указан, берется из конфигурации)
            group_id: ID группы (если не указан, берется из конфигурации)
        """
        self.token = token or VKConfig.TOKEN
        self.group_id = group_id or VKConfig.GROUP_ID
        self.owner_id = VKConfig.OWNER_ID
        self.api_version = VKConfig.API_VERSION
        self.session = requests.Session()
        
        # Настройка сессии
        self.session.headers.update({
            'User-Agent': 'BotyVK/1.0'
        })
        
        logger.info(f"VKClient инициализирован для группы {self.group_id}")
    
    def _make_request(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        Выполнение запроса к VK API
        
        Args:
            method: Метод API
            params: Параметры запроса
        
        Returns:
            Ответ от API
        
        Raises:
            Exception: При ошибках запроса
        """
        # Добавляем общие параметры
        params.update({
            'access_token': self.token,
            'v': self.api_version
        })
        
        url = f"{VKConfig.API_URL}/{method}"
        
        logger.debug(f"Запрос к API: {method} с параметрами {params}")
        
        for attempt in range(5):  # Повторяем попытку до 5 раз
            try:
                response = self.session.post(url, data=params, timeout=30)
                response.raise_for_status()
                
                data = response.json()
                
                if 'error' in data:
                    error = data['error']
                    error_code = error.get('error_code', 0)
                    error_msg = error.get('error_msg', 'Unknown error')
                    
                    # Обработка специфичных ошибок
                    if error_code == 6:  # Too many requests per second
                        wait_time = 1 * (2 ** attempt)  # Экспоненциальная задержка
                        logger.warning(f"Слишком много запросов. Ожидание {wait_time} секунд")
                        time.sleep(wait_time)
                        continue
                    elif error_code == 9:  # Flood control
                        logger.error("Flood control. Остановка выполнения")
                        raise Exception(f"Flood control: {error_msg}")
                    elif error_code == 14:  # Captcha needed
                        captcha_sid = error.get('captcha_sid')
                        captcha_img = error.get('captcha_img')
                        logger.error(f"Требуется CAPTCHA: {captcha_img}")
                        raise Exception(f"Требуется CAPTCHA: {error_msg}")
                    elif error_code == 10:  # Internal server error
                        logger.warning(f"Внутренняя ошибка сервера VK (код: {error_code}). Повторная попытка... (попытка {attempt + 1}/5)")
                        time.sleep(3 * (attempt + 1))  # Задержка с экспоненциальным ростом
                        continue
                    else:
                        logger.error(f"Ошибка API: {error_code} - {error_msg}")
                        raise Exception(f"{error_msg} (код: {error_code})")
                
                logger.debug(f"Успешный ответ от API: {data}")
                return data.get('response', {})
                
            except requests.exceptions.RequestException as e:
                logger.error(f"Ошибка запроса к API: {e}")
                if attempt < 2:  # Не делаем задержку на последней попытке
                    time.sleep(1)
                else:
                    raise Exception(f"Ошибка подключения к API VK: {e}")
            
        raise Exception("Превышено количество попыток запроса к API")
    
    def get_group_info(self) -> Dict[str, Any]:
        """
        Получение информации о группе
        
        Returns:
            Информация о группе
        """
        params = {
            'group_id': abs(self.group_id),
            'fields': 'name,screen_name,description,members_count,links,activity'
        }
        
        return self._make_request('groups.getById', params)
    
    def get_wall_posts(self, count: int = 10) -> Dict[str, Any]:
        """
        Получение записей со стены
        
        Args:
            count: Количество записей
        
        Returns:
            Записи со стены
        """
        params = {
            'owner_id': self.owner_id,
            'count': count,
            'filter': 'owner'
        }
        
        return self._make_request('wall.get', params)
    
    def upload_photo_to_album(self, photo_path: str, album_id: int) -> Dict[str, Any]:
        """
        Загрузка фотографии в альбом
        
        Args:
            photo_path: Путь к фотографии
            album_id: ID альбома
        
        Returns:
            Информация о загруженной фотографии
        """
        # Получаем сервер для загрузки
        params = {
            'group_id': abs(self.group_id),
            'album_id': album_id
        }
        
        response = self._make_request('photos.getUploadServer', params)
        upload_url = response['upload_url']
        
        # Загружаем фотографию
        with open(photo_path, 'rb') as f:
            files = {'file': f}
            upload_response = requests.post(upload_url, files=files)
            upload_data = upload_response.json()
        
        # Сохраняем фотографию
        save_params = {
            'group_id': abs(self.group_id),
            'album_id': album_id,
            'server': upload_data['server'],
            'photos_list': upload_data['photos_list'],
            'hash': upload_data['hash']
        }
        
        return self._make_request('photos.save', save_params)
    
    def upload_photo_to_wall(self, photo_path: str) -> Dict[str, Any]:
        """
        Загрузка фотографии для публикации на стене
        
        Args:
            photo_path: Путь к фотографии
        
        Returns:
            Информация о загруженной фотографии
        """
        # Получаем сервер для загрузки
        params = {
            'group_id': abs(self.group_id)
        }
        
        response = self._make_request('photos.getWallUploadServer', params)
        upload_url = response['upload_url']
        
        # Загружаем фотографию
        with open(photo_path, 'rb') as f:
            files = {'photo': f}
            upload_response = requests.post(upload_url, files=files)
            upload_data = upload_response.json()
        
        # Сохраняем фотографию
        save_params = {
            'group_id': abs(self.group_id),
            'photo': upload_data['photo'],
            'server': upload_data['server'],
            'hash': upload_data['hash']
        }
        
        return self._make_request('photos.saveWallPhoto', save_params)
    
    def publish_post(self, **kwargs) -> Dict[str, Any]:
        """
        Публикация записи на стене
        
        Args:
            **kwargs: Параметры публикации
                owner_id: ID владельца стены
                message: Текст записи
                attachments: Вложения
                from_group: Публиковать от имени группы
                signed: Подписывать запись
                publish_date: Дата публикации (timestamp)
                lat: Географическая широта
                long: Географическая долгота
                place_id: ID места
                post_id: ID записи (для редактирования)
                friends_only: Только для друзей
                copyright: Источник материала
                close_comments: Закрыть комментарии
                poster_bkg_id: ID фона обложки
                poster_bkg_owner_id: ID владельца фона обложки
                poster_bkg_access_hash: Хэш доступа к фону обложки
                marked_users: Отметка пользователей
        
        Returns:
            Результат публикации
        """
        # Устанавливаем owner_id по умолчанию
        if 'owner_id' not in kwargs:
            kwargs['owner_id'] = self.owner_id
        
        return self._make_request('wall.post', kwargs)
    
    def schedule_post(self, **kwargs) -> Dict[str, Any]:
        """
        Планирование публикации
        
        Args:
            **kwargs: Параметры публикации (те же, что и для publish_post)
        
        Returns:
            Результат планирования
        """
        # Устанавливаем owner_id по умолчанию
        if 'owner_id' not in kwargs:
            kwargs['owner_id'] = self.owner_id
        
        # Добавляем флаг запланированной публикации
        kwargs['publish_date'] = kwargs.get('publish_date', int(time.time()) + 3600)  # Через час по умолчанию
        
        return self._make_request('wall.post', kwargs)
    
    def get_scheduled_posts(self) -> Dict[str, Any]:
        """
        Получение запланированных публикаций
        
        Returns:
            Запланированные публикации
        """
        params = {
            'owner_id': self.owner_id
        }
        
        return self._make_request('wall.get', params)
    
    def edit_post(self, post_id: int, **kwargs) -> Dict[str, Any]:
        """
        Редактирование публикации
        
        Args:
            post_id: ID публикации
            **kwargs: Новые параметры публикации
        
        Returns:
            Результат редактирования
        """
        kwargs['post_id'] = post_id
        if 'owner_id' not in kwargs:
            kwargs['owner_id'] = self.owner_id
        
        return self._make_request('wall.edit', kwargs)
    
    def delete_post(self, post_id: int) -> Dict[str, Any]:
        """
        Удаление публикации
        
        Args:
            post_id: ID публикации
        
        Returns:
            Результат удаления
        """
        params = {
            'owner_id': self.owner_id,
            'post_id': post_id
        }
        
        return self._make_request('wall.delete', params)
    
    def get_comments(self, post_id: int, count: int = 100) -> Dict[str, Any]:
        """
        Получение комментариев к публикации
        
        Args:
            post_id: ID публикации
            count: Количество комментариев
        
        Returns:
            Комментарии к публикации
        """
        params = {
            'owner_id': self.owner_id,
            'post_id': post_id,
            'count': count
        }
        
        return self._make_request('wall.getComments', params)
    
    def add_comment(self, post_id: int, message: str, **kwargs) -> Dict[str, Any]:
        """
        Добавление комментария к публикации
        
        Args:
            post_id: ID публикации
            message: Текст комментария
            **kwargs: Дополнительные параметры
        
        Returns:
            Результат добавления комментария
        """
        kwargs.update({
            'owner_id': self.owner_id,
            'post_id': post_id,
            'message': message
        })
        
        return self._make_request('wall.createComment', kwargs)
    
    def get_likes(self, post_id: int) -> Dict[str, Any]:
        """
        Получение лайков публикации
        
        Args:
            post_id: ID публикации
        
        Returns:
            Лайки публикации
        """
        params = {
            'type': 'post',
            'owner_id': self.owner_id,
            'item_id': post_id
        }
        
        return self._make_request('likes.getList', params)
    
    def add_like(self, post_id: int) -> Dict[str, Any]:
        """
        Добавление лайка публикации
        
        Args:
            post_id: ID публикации
        
        Returns:
            Результат добавления лайка
        """
        params = {
            'type': 'post',
            'owner_id': self.owner_id,
            'item_id': post_id
        }
        
        return self._make_request('likes.add', params)
    
    def remove_like(self, post_id: int) -> Dict[str, Any]:
        """
        Удаление лайка с публикации
        
        Args:
            post_id: ID публикации
        
        Returns:
            Результат удаления лайка
        """
        params = {
            'type': 'post',
            'owner_id': self.owner_id,
            'item_id': post_id
        }
        
        return self._make_request('likes.delete', params)