import asyncio
import aiohttp
import os
import io
from PIL import Image

# =========================
# Настройки
# =========================

url_template = input(
    "Введите шаблон ссылки (например https://site.com/img/{}.webp):\n"
).strip()

start_input = input("Начальный номер (Enter = 1): ").strip()
start = int(start_input) if start_input else 1

end_input = input("Конечный номер (Enter = автоопределение): ").strip()
end = int(end_input) if end_input else None

folder_name = input("Название папки (Enter = images): ").strip()
if not folder_name:
    folder_name = "images"

os.makedirs(folder_name, exist_ok=True)

CONCURRENT_DOWNLOADS = 20

# =========================
# Конвертация в JPEG
# =========================

def convert_to_jpg(raw_bytes):
    img = Image.open(io.BytesIO(raw_bytes))

    # Сохраняем прозрачность если есть
    # Сохраняем прозрачность WebP на белом фоне
    if img.mode in ("RGBA", "PA", "P"):
        bg = Image.new("RGB", img.size, (255, 255, 255))
        if img.mode == "P":
            img = img.convert("RGBA")
        if img.mode in ("RGBA", "PA"):
            bg.paste(img, mask=img.split()[-1])
        img = bg
    elif img.mode != "RGB":
        img = img.convert("RGB")

    buf = io.BytesIO()
    img.save(buf, format="JPEG", quality=95, optimize=True)
    return buf.getvalue()

# =========================
# Асинхронное скачивание
# =========================

async def download_image(session, number):
    url = url_template.format(number)

    try:
        async with session.get(url) as response:
            if response.status == 200:
                raw = await response.read()

                try:
                    jpg_bytes = convert_to_jpg(raw)
                    filename = os.path.join(folder_name, f"{number}.jpg")
                    with open(filename, "wb") as f:
                        f.write(jpg_bytes)
                    print(f"[OK] {number} -> {number}.jpg")
                except Exception as e:
                    print(f"[CONV ERROR] {number} -> {e}, сохраняю оригинал")
                    ext = url.rsplit(".", 1)[-1].split("?")[0] or "bin"
                    filename = os.path.join(folder_name, f"{number}.{ext}")
                    with open(filename, "wb") as f:
                        f.write(raw)

                return True

            else:
                print(f"[MISS] {number} -> HTTP {response.status}")
                return False

    except Exception as e:
        print(f"[ERROR] {number} -> {e}")
        return False

# =========================
# Автоопределение конца
# =========================

async def find_last_image(session, start_number):
    print("Автоопределение последней картинки...")
    current = start_number
    while True:
        url = url_template.format(current)
        try:
            async with session.get(url) as response:
                if response.status != 200:
                    return current - 1
        except:
            return current - 1
        current += 1

# =========================
# Основная логика
# =========================

async def main():
    connector = aiohttp.TCPConnector(limit=CONCURRENT_DOWNLOADS)

    async with aiohttp.ClientSession(connector=connector) as session:
        global end

        if end is None:
            end = await find_last_image(session, start)

        print(f"\nДиапазон: {start} -> {end}\n")

        tasks = [
            asyncio.create_task(download_image(session, number))
            for number in range(start, end + 1)
        ]

        await asyncio.gather(*tasks)

    print("\nГотово.")


asyncio.run(main())