# Модуль для работы с VK Video API
import aiohttp
import asyncio
import json


def video_iframe(url):
    """
    Формирует iframe из URL видео VK Video.

    Args:
        url: URL видео вида https://vkvideo.ru/video-{owner_id}_{video_id}
             или https://vk.com/video{owner_id}_{video_id}

    Returns:
        str: HTML код iframe для встраивания видео
    """
    prep = url.split("video")[-1].split("_")
    if len(prep) < 2:
        raise ValueError(f"Неверный формат URL видео: {url}")

    oid, vid = prep[0].lstrip("-"), prep[1]

    return f'<iframe src="https://vkvideo.ru/video_ext.php?oid=-{oid}&id={vid}&autoplay=0&loop=1" width="100%" style="aspect-ratio: 16 / 9;" allow="autoplay; encrypted-media; fullscreen; picture-in-picture; screen-wake-lock;" frameborder="0" allowfullscreen></iframe>'


async def get_user_groups(access_token):
    """
    Получает список групп пользователя (каналов) через VK API.

    Args:
        access_token: Токен доступа VK API

    Returns:
        list: Список словарей с информацией о группах [{'id': int, 'name': str, 'owner_id': int}, ...]
              owner_id будет отрицательным числом для групп
    """
    url = "https://api.vk.com/method/groups.get"
    params = {
        "access_token": access_token,
        "extended": 1,
        "filter": "admin,editor",  # Только группы, где пользователь админ или редактор
        "v": "5.131",
    }

    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(url, params=params) as response:
                response.raise_for_status()
                data = await response.json()

                if "error" in data:
                    raise Exception(f"VK API Error: {data['error']['error_msg']}")

                groups = []
                for group in data.get("response", {}).get("items", []):
                    groups.append(
                        {
                            "id": group["id"],
                            "name": group["name"],
                            "owner_id": -group[
                                "id"
                            ],  # Для групп owner_id отрицательный
                        }
                    )

                return groups
    except aiohttp.ClientError as e:
        raise Exception(f"Ошибка при запросе к VK API: {str(e)}")


async def get_video_albums(access_token, owner_id):
    """
    Получает список альбомов/плейлистов группы через VK API.

    Args:
        access_token: Токен доступа VK API
        owner_id: ID владельца (группы, отрицательное число)

    Returns:
        list: Список словарей с информацией об альбомах [{'id': int, 'title': str}, ...]
    """
    url = "https://api.vk.com/method/video.getAlbums"
    params = {"access_token": access_token, "owner_id": owner_id, "v": "5.131"}

    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(url, params=params) as response:
                response.raise_for_status()
                data = await response.json()

                if "error" in data:
                    raise Exception(f"VK API Error: {data['error']['error_msg']}")

                albums = []
                for album in data.get("response", {}).get("items", []):
                    albums.append({"id": album["id"], "title": album["title"]})

                # Добавляем опцию "Без альбома" (album_id = 0)
                albums.insert(0, {"id": 0, "title": "Без альбома"})

                return albums
    except aiohttp.ClientError as e:
        raise Exception(f"Ошибка при запросе к VK API: {str(e)}")


async def upload_video_to_vk(
    access_token, video_path, owner_id, album_id, title, description=""
):
    """
    Загружает видео в VK Video через API и опрашивает статус создания видео.

    Args:
        access_token: Токен доступа VK API
        video_path: Путь к файлу видео на диске
        owner_id: ID владельца (группы, отрицательное число)
        album_id: ID альбома (0 для загрузки без альбома)
        title: Название видео
        description: Описание видео (может быть пустым)

    Returns:
        str: URL видео для формирования iframe
    """
    import os
    import time

    # Проверяем существование файла
    if not os.path.exists(video_path):
        raise FileNotFoundError(f"Файл видео не найден: {video_path}")

    # Проверяем размер файла (VK ограничивает размер до 2GB, но лучше предупредить о больших файлах)
    file_size = os.path.getsize(video_path)
    max_size = 2 * 1024 * 1024 * 1024  # 2GB
    if file_size > max_size:
        raise ValueError(
            f"Файл слишком большой ({file_size / (1024 * 1024 * 1024):.2f} GB). Максимальный размер: 2 GB"
        )

    # Шаг 1: Получаем upload_url через video.save
    url = "https://api.vk.com/method/video.save"
    params = {
        "access_token": access_token,
        "name": title,
        "description": description,
        "group_id": abs(owner_id),  # Для групп передаем положительное число
        "album_id": album_id if album_id != 0 else None,
        "v": "5.131",
    }

    # Убираем None значения
    params = {k: v for k, v in params.items() if v is not None}

    try:
        async with aiohttp.ClientSession() as session:
            # Получаем upload_url
            async with session.get(
                url, params=params, timeout=aiohttp.ClientTimeout(total=30)
            ) as response:
                response.raise_for_status()
                data = await response.json()

                if "error" in data:
                    error_msg = data["error"].get("error_msg", "Неизвестная ошибка")
                    error_code = data["error"].get("error_code", "")
                    raise Exception(f"VK API Error ({error_code}): {error_msg}")

                if "response" not in data or "upload_url" not in data["response"]:
                    raise Exception("Неверный ответ от VK API: отсутствует upload_url")

                upload_url = data["response"]["upload_url"]
                video_id = data["response"]["video_id"]

            # Шаг 2: Загружаем файл на сервер VK (без таймаута или с очень большим таймаутом)
            # Для больших файлов может потребоваться много времени
            file_size_mb = file_size / (1024 * 1024)
            # Таймаут: минимум 3 минуты, плюс 1 минута на каждые 10MB
            upload_timeout = max(180, int(file_size_mb / 10 * 60))

            # Читаем файл в память для асинхронной загрузки
            with open(video_path, "rb") as video_file:
                video_data = video_file.read()

            data_form = aiohttp.FormData()
            # VK API обычно ожидает поле "file", а не "video_file"
            # Не указываем content_type явно, пусть aiohttp определит его автоматически
            data_form.add_field(
                "file",
                video_data,
                filename=os.path.basename(video_path),
            )

            async with session.post(
                upload_url,
                data=data_form,
                timeout=aiohttp.ClientTimeout(total=upload_timeout),
            ) as upload_response:
                # Читаем ответ перед проверкой статуса, чтобы увидеть детали ошибки
                response_text = await upload_response.text()
                
                if upload_response.status != 200:
                    # Пытаемся распарсить JSON ответ, если есть
                    try:
                        error_data = json.loads(response_text)
                        error_msg = str(error_data)
                    except (json.JSONDecodeError, ValueError):
                        error_msg = response_text[:500]  # Ограничиваем длину
                    
                    raise Exception(
                        f"Ошибка при загрузке видео в VK: {upload_response.status}, "
                        f"message='{error_msg}', url='{upload_url}'"
                    )
                
                # Если статус 200, проверяем ответ (может быть пустым или содержать JSON)
                # VK может вернуть результат загрузки, но обычно это не обязательно
                try:
                    json.loads(response_text)
                except (json.JSONDecodeError, ValueError):
                    # Если ответ не JSON, это нормально для успешной загрузки
                    pass

            # Шаг 3: Опрашиваем VK API раз в минуту, пока видео не создастся
            # Максимальное время ожидания: 30 минут
            max_wait_time = 30 * 60  # 30 минут в секундах
            poll_interval = 60  # Опрашиваем раз в минуту
            start_time = time.time()

            check_url = "https://api.vk.com/method/video.get"
            check_params = {
                "access_token": access_token,
                "videos": f"{owner_id}_{video_id}",
                "v": "5.131",
            }

            while True:
                # Проверяем, не превысили ли максимальное время ожидания
                elapsed_time = time.time() - start_time
                if elapsed_time > max_wait_time:
                    raise Exception(
                        f"Превышено максимальное время ожидания ({max_wait_time // 60} минут). "
                        f"Видео еще не создано в VK. Попробуйте проверить позже."
                    )

                # Опрашиваем VK API
                try:
                    async with session.get(
                        check_url,
                        params=check_params,
                        timeout=aiohttp.ClientTimeout(total=30),
                    ) as check_response:
                        check_response.raise_for_status()
                        check_data = await check_response.json()

                        if "error" in check_data:
                            # Если ошибка не критическая (например, видео еще не создано), продолжаем ждать
                            error_code = check_data["error"].get("error_code", 0)
                            if (
                                error_code == 203
                            ):  # Видео не найдено - еще обрабатывается
                                await asyncio.sleep(poll_interval)
                                continue
                            else:
                                error_msg = check_data["error"].get(
                                    "error_msg", "Неизвестная ошибка"
                                )
                                raise Exception(
                                    f"VK API Error ({error_code}): {error_msg}"
                                )

                        # Если видео найдено, возвращаем URL
                        if (
                            "response" in check_data
                            and "items" in check_data["response"]
                        ):
                            items = check_data["response"]["items"]
                            if items and len(items) > 0:
                                # Видео создано!
                                video_url = (
                                    f"https://vkvideo.ru/video{owner_id}_{video_id}"
                                )
                                return video_url

                        # Видео еще не создано, ждем и опрашиваем снова
                        await asyncio.sleep(poll_interval)

                except asyncio.TimeoutError:
                    # При таймауте проверки просто продолжаем ждать
                    await asyncio.sleep(poll_interval)
                    continue
                except aiohttp.ClientError:
                    # При других ошибках запроса тоже продолжаем ждать
                    await asyncio.sleep(poll_interval)
                    continue

    except FileNotFoundError:
        raise
    except asyncio.TimeoutError:
        raise Exception("Превышено время ожидания при загрузке файла на сервер VK.")
    except aiohttp.ClientError as e:
        raise Exception(f"Ошибка при загрузке видео в VK: {str(e)}")
