#!/usr/bin/python3

"""Bot that uploads a random szurubooru image to an eink screen"""

import random
import requests
import os
import pyszuru
from PIL import Image, ImageSequence, UnidentifiedImageError


from epd.epd_config import palArr, epdArr, EPD_TYPES
from epd.image_processor import getErr, getNear, addVal, procImg
from epd.epd_uploader import upload_image


# get truly random post
try:
    szuru_url = os.environ["SZURU_URL"]
    szuru_user = os.environ["SZURU_USER"]
    szuru_token = os.environ["SZURU_TOKEN"]
except KeyError as e:
    raise ValueError(f"Missing required environment variable: {e}")

booru = pyszuru.API(szuru_url, username=szuru_user, token=szuru_token)
highest_post = next(booru.search_post("sort:id type:image", page_size=1))

post = None
while post is None:
    random_id = random.randint(0, highest_post.id_)
    temp_post = booru.getPost(random_id)
    if temp_post and temp_post.mime.startswith("image/") and temp_post.content:
        post = temp_post
        print(f"[DEBUG] Found image post with ID: {post.id_}, MIME: {post.mime}")
    else:
        print(
            f"[DEBUG] Skipping post ID: {random_id} (MIME: {temp_post.mime if temp_post else 'None'}, Content: {bool(temp_post.content) if temp_post else 'None'}) - not a valid image."
        )

# download image
image_downloaded = False
while not image_downloaded:
    try:
        r = requests.get(post.content, stream=True)
        print(f"[DEBUG] Downloading image from {post.content}")
        r.raise_for_status()
        with open("image.jpg", "wb") as f:
            for chunk in r.iter_content(chunk_size=8192):
                f.write(chunk)
        print("[DEBUG] Image downloaded and saved as image.jpg")

        # Attempt to open the image to verify
        img = Image.open("image.jpg")
        img.verify()  # Verify that it is an image
        img.close()
        image_downloaded = True
        print("[DEBUG] Image successfully verified.")
    except (UnidentifiedImageError, requests.exceptions.RequestException) as e:
        print(
            f"[ERROR] Failed to process downloaded file (Error: {e}). Retrying with a new post..."
        )
        # Clean up the invalid file
        if os.path.exists("image.jpg"):
            os.remove("image.jpg")
        # Find a new post
        post = None
        while post is None:
            random_id = random.randint(0, highest_post.id_)
            temp_post = booru.getPost(random_id)
            if temp_post and temp_post.mime.startswith("image/") and temp_post.content:
                post = temp_post
                print(
                    f"[DEBUG] Found new image post with ID: {post.id_}, MIME: {post.mime}"
                )
            else:
                print(
                    f"[DEBUG] Skipping post ID: {random_id} (MIME: {temp_post.mime if temp_post else 'None'}, Content: {bool(temp_post.content) if temp_post else 'None'}) - not a valid image."
                )

    # Process and upload
    img = Image.open("image.jpg")
    if post.mime == "image/gif":
        # Seek to a random frame
        random_frame_index = random.randint(0, img.n_frames - 1)
        print(f"[DEBUG] Detected GIF, selecting frame: {random_frame_index}")
        img.seek(random_frame_index)
        # Convert the frame to an RGB image to discard GIF palette and alpha for processing
        img = img.convert("RGB")

# Get configuration from environment variables
try:
    epd_type_str = os.environ["EPD_TYPE"]
    ip_addr = os.environ["EINK_IP"]
    dithering_mode = os.environ["DITHERING_MODE"].lower()
except KeyError as e:
    raise ValueError(f"Missing required environment variable: {e}")

if epd_type_str not in EPD_TYPES:
    raise ValueError(
        f"Invalid EPD_TYPE: {epd_type_str}. Must be one of {list(EPD_TYPES.keys())}"
    )
epd_ind = EPD_TYPES[epd_type_str]

is_red = False
if dithering_mode == "color":
    # Check if the selected EPD type supports color based on scriptD.js logic
    # EPDs that are explicitly monochrome in scriptD.js despite palArr:
    monochrome_only_epds = [0, 3, 6, 7, 9, 12, 16, 19, 22, 26, 27, 28, 39, 40, 43]
    if epd_ind in monochrome_only_epds:
        print(
            f"[WARNING] Dithering mode is set to 'color', but EPD type '{epd_type_str}' (Index {epd_ind}) is treated as monochrome by the device's protocol. Color will not appear."
        )
        is_red = False  # Force monochrome for this EPD type
    else:
        is_red = True
elif dithering_mode != "mono":
    raise ValueError(
        f"Invalid DITHERING_MODE: {dithering_mode}. Must be 'mono' or 'color'."
    )

# Get display dimensions and palette from epdArr
dW, dH, pal_ind = epdArr[epd_ind]
target_size = (dW, dH)

# Resize image to fit display, preserving aspect ratio
img.thumbnail(target_size, Image.Resampling.LANCZOS)

# Create a new image with a white background
background = Image.new("RGB", target_size, (255, 255, 255))

# Calculate position and paste the thumbnail onto the background
paste_x = (target_size[0] - img.width) // 2
paste_y = (target_size[1] - img.height) // 2
background.paste(img, (paste_x, paste_y))
img = background

print(f"[DEBUG] Dithering Mode: {dithering_mode}")
print(f"[DEBUG] is_red: {is_red}")
print(f"[DEBUG] EPD Type String: {epd_type_str}")
print(f"[DEBUG] EPD Index: {epd_ind}")
print(f"[DEBUG] Palette Index: {pal_ind}")
# Process the final image with dithering
processed_img = procImg(
    img, dW, dH, 0, 0, pal_ind, isLvl=False, isRed=is_red, palArr=palArr
)

processed_img.save("processed.png")  # Save for debugging
print("[DEBUG] Imaged processed and saved as processed.png")

upload_image(processed_img, ip_addr, epd_ind, epdArr, palArr, getNear)
