import requests
import random
import tkinter as tk
from tkinter import messagebox, ttk
import webbrowser
from PIL import Image, ImageTk
import io
import threading
import os
import json

# Directory for cached posters
POSTER_CACHE_DIR = 'poster_cache'
os.makedirs(POSTER_CACHE_DIR, exist_ok=True)

# File to store API credentials
API_CREDENTIALS_FILE = 'api_credentials.json'

# Function to load API credentials
def load_api_credentials():
    if os.path.exists(API_CREDENTIALS_FILE):
        with open(API_CREDENTIALS_FILE, 'r') as f:
            return json.load(f)
    return {}

# Function to save API credentials
def save_api_credentials(credentials):
    with open(API_CREDENTIALS_FILE, 'w') as f:
        json.dump(credentials, f)

# Function to ask for API credentials
def ask_for_api_credentials():
    credentials = {}

    def on_submit():
        credentials['TRAKT_CLIENT_ID'] = trakt_client_id_entry.get()
        credentials['TRAKT_ACCESS_TOKEN'] = trakt_access_token_entry.get()
        credentials['TMDB_API_KEY'] = tmdb_api_key_entry.get()
        save_api_credentials(credentials)
        credentials_window.destroy()

    credentials_window = tk.Toplevel(root)
    credentials_window.title("Enter API Credentials")

    tk.Label(credentials_window, text="Trakt Client ID:").pack()
    trakt_client_id_entry = tk.Entry(credentials_window)
    trakt_client_id_entry.pack()

    tk.Label(credentials_window, text="Trakt Access Token:").pack()
    trakt_access_token_entry = tk.Entry(credentials_window)
    trakt_access_token_entry.pack()

    tk.Label(credentials_window, text="TMDB API Key:").pack()
    tmdb_api_key_entry = tk.Entry(credentials_window)
    tmdb_api_key_entry.pack()

    submit_button = tk.Button(credentials_window, text="Submit", command=on_submit)
    submit_button.pack(pady=10)

    credentials_window.transient(root)
    credentials_window.grab_set()
    root.wait_window(credentials_window)

    return credentials

# Create GUI
root = tk.Tk()
root.title("Trakt Watchlist")
root.geometry("1438x875")  # Set the initial size of the window
root.resizable(True, True)

# Load or ask for API credentials
credentials = load_api_credentials()
if not credentials:
    credentials = ask_for_api_credentials()

# Trakt and TMDB API credentials
TRAKT_CLIENT_ID = credentials['TRAKT_CLIENT_ID']
TRAKT_ACCESS_TOKEN = credentials['TRAKT_ACCESS_TOKEN']
TMDB_API_KEY = credentials['TMDB_API_KEY']

selected_label = None  # Track the currently selected label
genres_dict = {}  # Store genres for each movie
posters_dict = {}  # Store posters for each movie
languages_dict = {}  # Store languages for each movie
runtimes_dict = {}  # Store runtimes for each movie
ratings_dict = {}  # Store ratings for each movie
current_index = 0  # Define current_index

# Variable definitions for filters
decade_var = tk.StringVar(value="All")
genre_var = tk.StringVar(value="All")
language_var = tk.StringVar(value="All")
runtime_var = tk.StringVar(value="All")
letter_var = tk.StringVar(value="All")
sort_order_var = tk.StringVar(value="By Date Added to My List (Newest to Oldest)")
search_var = tk.StringVar(value="")

# Function to get watchlist from Trakt
def get_watchlist():
    url = "https://api.trakt.tv/users/me/watchlist/movies"
    headers = {
        "Content-Type": "application/json",
        "trakt-api-version": "2",
        "trakt-api-key": TRAKT_CLIENT_ID,
        "Authorization": f"Bearer {TRAKT_ACCESS_TOKEN}"
    }
    response = requests.get(url, headers=headers)
    if response.status_code == 403:
        messagebox.showerror("Error", "Access forbidden: Check your API credentials.")
        return []
    response.raise_for_status()
    return response.json()

# Function to get movie details from TMDB
def get_tmdb_movie_details(tmdb_id):
    url = f"https://api.themoviedb.org/3/movie/{tmdb_id}"
    params = {
        "api_key": TMDB_API_KEY,
        "append_to_response": "credits"
    }
    response = requests.get(url, params=params)
    response.raise_for_status()
    return response.json()

# Function to get movie poster from TMDB
def get_movie_poster(tmdb_id):
    poster_path = os.path.join(POSTER_CACHE_DIR, f'{tmdb_id}.jpg')
    if os.path.exists(poster_path):
        return poster_path
    url = f"https://api.themoviedb.org/3/movie/{tmdb_id}/images"
    params = {
        "api_key": TMDB_API_KEY
    }
    response = requests.get(url, params=params)
    response.raise_for_status()
    images = response.json().get("posters", [])
    if images:
        poster_url = f"https://image.tmdb.org/t/p/w200{images[0]['file_path']}"
        poster_image = requests.get(poster_url).content
        with open(poster_path, 'wb') as f:
            f.write(poster_image)
        return poster_path
    return None

# Function to get movie trailer from TMDB
def get_movie_trailer(tmdb_id):
    url = f"https://api.themoviedb.org/3/movie/{tmdb_id}/videos"
    params = {
        "api_key": TMDB_API_KEY
    }
    response = requests.get(url, params=params)
    response.raise_for_status()
    videos = response.json().get("results", [])
    for video in videos:
        if video["type"] == "Trailer" and video["site"] == "YouTube":
            return f"https://www.youtube.com/watch?v={video['key']}"
    return None

# Function to display movie details
def show_movie_details(title, year, slug, tmdb_id, detail_frame):
    for widget in detail_frame.winfo_children():
        widget.destroy()
        
    movie_details = get_tmdb_movie_details(tmdb_id)

    # Movie title and year
    label_title = tk.Label(detail_frame, text=f"{title} ({year})", font=("Helvetica", 16, "bold"))
    label_title.pack(pady=10)

    # Poster
    poster_url = get_movie_poster(tmdb_id)
    if poster_url:
        poster_image = Image.open(poster_url)
        poster_image = poster_image.resize((100, 150), Image.LANCZOS)
        poster_photo = ImageTk.PhotoImage(poster_image)
        poster_label = tk.Label(detail_frame, image=poster_photo)
        poster_label.image = poster_photo
        poster_label.pack(pady=10)
    else:
        poster_label = tk.Label(detail_frame, text="Poster not available")
        poster_label.pack(pady=10)

    # Director
    directors = [person['name'] for person in movie_details.get('credits', {}).get('crew', []) if person['job'] == 'Director']
    label_director = tk.Label(detail_frame, text=f"Director: {', '.join(directors) if directors else 'Unknown'}")
    label_director.pack(pady=5)

    # Cast
    cast = [person['name'] for person in movie_details.get('credits', {}).get('cast', [])[:5]]
    label_cast = tk.Label(detail_frame, text=f"Cast: {', '.join(cast) if cast else 'Unknown'}")
    label_cast.pack(pady=5)

    # Language
    language = languages_dict.get(tmdb_id, "Unknown")
    label_language = tk.Label(detail_frame, text=f"Language: {language}")
    label_language.pack(pady=5)

    # Runtime
    runtime = runtimes_dict.get(tmdb_id, "Unknown")
    label_runtime = tk.Label(detail_frame, text=f"Runtime: {runtime} minutes")
    label_runtime.pack(pady=5)

    # Genre
    genres = genres_dict.get(tmdb_id, [])
    label_genre = tk.Label(detail_frame, text=f"Genre: {', '.join(genres).title() if genres else 'Unknown'}")
    label_genre.pack(pady=5)

    # Rating
    rating = movie_details.get("vote_average", "N/A")
    if isinstance(rating, (float, int)):
        rating = f"{rating:.1f}"
    label_rating = tk.Label(detail_frame, text=f"Rating: {rating}")
    label_rating.pack(pady=5)

    # Synopsis
    synopsis = movie_details.get("overview", "Synopsis not available.")
    label_synopsis = tk.Label(detail_frame, text=synopsis, wraplength=400, justify="left")
    label_synopsis.pack(pady=5)

    # Buttons frame
    buttons_frame = tk.Frame(detail_frame)
    buttons_frame.pack(pady=10)

    # Trakt URL button
    trakt_url = f"https://trakt.tv/movies/{slug}"
    open_link_button = tk.Button(buttons_frame, text="View on Trakt", command=lambda: webbrowser.open(trakt_url))
    open_link_button.pack(side=tk.LEFT, padx=10)

    # Trailer button
    trailer_url = get_movie_trailer(tmdb_id)
    if trailer_url:
        trailer_button = tk.Button(buttons_frame, text="Watch Trailer", command=lambda: webbrowser.open(trailer_url))
        trailer_button.pack(side=tk.LEFT, padx=10)
    else:
        trailer_button = tk.Button(buttons_frame, text="No Trailer Available", state=tk.DISABLED)
        trailer_button.pack(side=tk.LEFT, padx=10)

# Function to filter movies based on selected decade, genre, language, runtime, starting letter, and search query
def filter_movies():
    selected_decade = decade_var.get()
    selected_genre = genre_var.get().lower()
    selected_language = language_var.get().lower()
    selected_runtime = runtime_var.get()
    selected_letter = letter_var.get().lower()
    sort_order = sort_order_var.get()
    search_query = search_var.get().lower()

    filtered_movies = []
    for movie in movies:
        movie_title = movie['movie']['title']
        movie_year = movie['movie']['year']
        tmdb_id = movie['movie']['ids'].get('tmdb')
        movie_genres = genres_dict.get(tmdb_id, [])
        movie_language = languages_dict.get(tmdb_id, 'unknown').lower()
        movie_runtime = runtimes_dict.get(tmdb_id, 0)
        movie_rating = ratings_dict.get(tmdb_id, 0)

        if selected_decade != "All":
            start_year = int(selected_decade)
            if not (start_year <= movie_year < start_year + 10):
                continue

        if selected_genre != "all":
            if not any(selected_genre in genre for genre in movie_genres):
                continue

        if selected_language != "all":
            if selected_language != movie_language:
                continue

        if selected_runtime != "All":
            if selected_runtime == "Less than 60 minutes" and movie_runtime >= 60:
                continue
            elif selected_runtime == "60 to 90 minutes" and not (60 <= movie_runtime <= 90):
                continue
            elif selected_runtime == "90 to 120 minutes" and not (90 <= movie_runtime <= 120):
                continue
            elif selected_runtime == "More than 120 minutes" and movie_runtime <= 120:
                continue

        if selected_letter != "all":
            if not movie_title.lower().startswith(selected_letter):
                continue

        if search_query and search_query not in movie_title.lower():
            continue

        filtered_movies.append(movie)

    # Sorting the filtered movies based on the selected sort order
    if sort_order == "Alphabetically (A-Z)":
        filtered_movies.sort(key=lambda x: x['movie']['title'])
    elif sort_order == "Alphabetically (Z-A)":
        filtered_movies.sort(key=lambda x: x['movie']['title'], reverse=True)
    elif sort_order == "By Date Released (Newest to Oldest)":
        filtered_movies.sort(key=lambda x: x['movie']['year'], reverse=True)
    elif sort_order == "By Date Released (Oldest to Newest)":
        filtered_movies.sort(key=lambda x: x['movie']['year'])
    elif sort_order == "By Date Added to My List (Newest to Oldest)":
        filtered_movies.sort(key=lambda x: x['listed_at'], reverse=True)
    elif sort_order == "By Date Added to My List (Oldest to Newest)":
        filtered_movies.sort(key=lambda x: x['listed_at'])
    elif sort_order == "Ranking (Highest to Lowest)":
        filtered_movies.sort(key=lambda x: ratings_dict.get(x['movie']['ids']['tmdb'], 0), reverse=True)
    elif sort_order == "Ranking (Lowest to Highest)":
        filtered_movies.sort(key=lambda x: ratings_dict.get(x['movie']['ids']['tmdb'], 0))

    return filtered_movies

# Function to pick a random movie from the watchlist
def pick_random_movie():
    filtered_movies = filter_movies()
    if filtered_movies:
        random_movie = random.choice(filtered_movies)
        movie_title = random_movie['movie']['title']
        movie_year = random_movie['movie']['year']
        movie_slug = random_movie['movie']['ids']['slug']
        tmdb_id = random_movie['movie']['ids'].get('tmdb')
        show_movie_details(movie_title, movie_year, movie_slug, tmdb_id, detail_frame)
        set_open_link_button(f"https://trakt.tv/movies/{movie_slug}")
    else:
        messagebox.showwarning("Warning", "No movies match the selected filters.")

# Function to update displayed movies
def update_displayed_movies(*args):
    global current_index
    current_index = 0  # Reset to the first page whenever filters are changed
    display_movies()

def display_movies():
    for widget in watchlist_frame.winfo_children():
        widget.destroy()

    start_index = current_index * 5
    end_index = start_index + 5
    filtered_movies = filter_movies()

    for movie in filtered_movies[start_index:end_index]:
        movie_title = movie['movie']['title']
        movie_year = movie['movie']['year']
        movie_slug = movie['movie']['ids'].get('slug')
        tmdb_id = movie['movie']['ids'].get('tmdb')
        movie_url = f"https://trakt.tv/movies/{movie_slug}"
        
        frame = tk.Frame(watchlist_frame)
        frame.pack(fill=tk.X, pady=5)

        # Poster
        poster_url = posters_dict.get(tmdb_id)
        if poster_url:
            poster_image = Image.open(poster_url)
            poster_image = poster_image.resize((50, 75), Image.LANCZOS)
            poster_photo = ImageTk.PhotoImage(poster_image)
            poster_label = tk.Label(frame, image=poster_photo)
            poster_label.image = poster_photo
            poster_label.pack(side=tk.TOP)
        else:
            poster_label = tk.Label(frame, text="No Poster", width=10)
            poster_label.pack()

        label = tk.Label(frame, text=f"{movie_title} ({movie_year})", fg="blue", cursor="hand2", bg=root.cget("bg"))
        label.bind("<Button-1>", lambda e, url=movie_url, lbl=label: toggle_selection(lbl, url))
        label.bind("<Double-Button-1>", lambda e, title=movie_title, year=movie_year, slug=movie_slug, tmdb_id=tmdb_id: show_movie_details(title, year, slug, tmdb_id, detail_frame))
        label.pack()

    update_page_navigation(len(filtered_movies))

# Function to toggle selection of a movie label
def toggle_selection(label, url):
    global selected_label
    if selected_label is label:
        # Unselect the label
        label.config(bg=root.cget("bg"))
        selected_label = None
        open_link_button.config(state=tk.DISABLED)
    else:
        # Unselect the previous label
        if selected_label:
            selected_label.config(bg=root.cget("bg"))
        # Select the new label
        label.config(bg="yellow")
        selected_label = label
        set_open_link_button(url)

# Function to show next set of movies
def show_next():
    global current_index, selected_label
    selected_label = None
    open_link_button.config(state=tk.DISABLED)
    filtered_movies = filter_movies()
    if (current_index + 1) * 5 < len(filtered_movies):
        current_index += 1
        display_movies()

# Function to show previous set of movies
def show_previous():
    global current_index, selected_label
    selected_label = None
    open_link_button.config(state=tk.DISABLED)
    if current_index > 0:
        current_index -= 1
        display_movies()

# Function to show the first set of movies
def show_first():
    global current_index, selected_label
    selected_label = None
    open_link_button.config(state=tk.DISABLED)
    current_index = 0
    display_movies()

# Function to show the last set of movies
def show_last():
    global current_index, selected_label
    selected_label = None
    open_link_button.config(state=tk.DISABLED)
    filtered_movies = filter_movies()
    total_pages = (len(filtered_movies) + 4) // 5
    current_index = total_pages - 1
    display_movies()

# Function to set the link for the open link button
def set_open_link_button(url):
    open_link_button.config(command=lambda: webbrowser.open(url))
    open_link_button.pack(pady=10)
    open_link_button.config(state=tk.NORMAL)

# Function to reset filters
def reset_filters():
    decade_var.set("All")
    genre_var.set("All")
    language_var.set("All")
    runtime_var.set("All")
    letter_var.set("All")
    sort_order_var.set("By Date Added to My List (Newest to Oldest)")
    search_var.set("")
    update_displayed_movies()

# Function to confirm reset of API credentials
def confirm_reset_api_credentials():
    confirm_window = tk.Toplevel(root)
    confirm_window.title("Confirm Reset")

    tk.Label(confirm_window, text="This will reset all API keys. Click Yes to proceed or No to cancel.").pack(pady=10)

    def reset_keys():
        confirm_window.destroy()
        if os.path.exists(API_CREDENTIALS_FILE):
            os.remove(API_CREDENTIALS_FILE)
        credentials = ask_for_api_credentials()
        global TRAKT_CLIENT_ID, TRAKT_ACCESS_TOKEN, TMDB_API_KEY
        TRAKT_CLIENT_ID = credentials['TRAKT_CLIENT_ID']
        TRAKT_ACCESS_TOKEN = credentials['TRAKT_ACCESS_TOKEN']
        TMDB_API_KEY = credentials['TMDB_API_KEY']
        update_displayed_movies()

    def cancel():
        confirm_window.destroy()

    button_frame = tk.Frame(confirm_window)
    button_frame.pack(pady=10)

    yes_button = tk.Button(button_frame, text="Yes", command=reset_keys)
    yes_button.pack(side=tk.LEFT, padx=5)

    no_button = tk.Button(button_frame, text="No", command=cancel)
    no_button.pack(side=tk.LEFT, padx=5)

# Function to update the page navigation display
def update_page_navigation(total_movies):
    for widget in page_nav_frame.winfo_children():
        widget.destroy()
    
    total_pages = (total_movies + 4) // 5
    if total_pages > 1:
        first_btn = tk.Button(page_nav_frame, text="<<", command=show_first)
        first_btn.pack(side=tk.LEFT, padx=2)

        if current_index > 0:
            prev_btn = tk.Button(page_nav_frame, text="<", command=show_previous)
            prev_btn.pack(side=tk.LEFT, padx=2)
        
        page_label = tk.Label(page_nav_frame, text=f"Page {current_index + 1} of {total_pages}")
        page_label.pack(side=tk.LEFT, padx=2)
        
        if (current_index + 1) < total_pages:
            next_btn = tk.Button(page_nav_frame, text=">", command=show_next)
            next_btn.pack(side=tk.LEFT, padx=2)

        last_btn = tk.Button(page_nav_frame, text=">>", command=show_last)
        last_btn.pack(side=tk.LEFT, padx=2)

# Function to preload cached posters
def preload_cached_posters():
    for movie in movies:
        tmdb_id = movie['movie']['ids'].get('tmdb')
        if tmdb_id:
            poster_path = os.path.join(POSTER_CACHE_DIR, f'{tmdb_id}.jpg')
            if os.path.exists(poster_path):
                posters_dict[tmdb_id] = poster_path

# Function to fetch genres, posters, languages, runtimes, and ratings in the background
def fetch_additional_movie_data():
    for movie in movies:
        tmdb_id = movie['movie']['ids'].get('tmdb')
        if tmdb_id:
            movie_details = get_tmdb_movie_details(tmdb_id)
            genres_dict[tmdb_id] = [genre['name'].lower() for genre in movie_details.get('genres', [])]
            poster_url = get_movie_poster(tmdb_id)
            if poster_url:
                posters_dict[tmdb_id] = poster_url
            languages_dict[tmdb_id] = movie_details.get('original_language', 'unknown').lower()
            runtimes_dict[tmdb_id] = movie_details.get('runtime', 0)
            ratings_dict[tmdb_id] = movie_details.get('vote_average', 0)
        loading_label.config(text=f"Loading {movie['movie']['title']}...")
    display_movies()
    loading_label.pack_forget()

# Fetch watchlist
movies = get_watchlist()

# Preload cached posters
preload_cached_posters()

# Create a frame for movie list and detail
main_frame = tk.Frame(root)
main_frame.pack(fill=tk.BOTH, expand=True)

# Create watchlist frame
watchlist_frame = tk.Frame(main_frame)
watchlist_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10)

# Create a frame for movie details
detail_frame = tk.Frame(main_frame)
detail_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10)

# Add a divider line between movie list and details
divider = tk.Frame(main_frame, width=2, bg="black")
divider.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))

# Page navigation frame
page_nav_frame = tk.Frame(root)
page_nav_frame.pack(pady=10)

# Display initial set of movies
display_movies()

# Add filters for decade, genre, language, runtime, letter
filter_frame = tk.Frame(root)
filter_frame.pack(pady=10, fill=tk.X)

# Decade filter
decade_frame = tk.Frame(filter_frame)
decade_frame.pack(side=tk.LEFT, padx=10)
tk.Label(decade_frame, text="Decade:").pack(side=tk.LEFT)
decades = ["All"] + [str(year) for year in range(1900, 2021, 10)]
decade_menu = ttk.Combobox(decade_frame, textvariable=decade_var, values=decades)
decade_menu.pack(side=tk.LEFT)
decade_menu.bind("<<ComboboxSelected>>", update_displayed_movies)

# Genre filter
genre_frame = tk.Frame(filter_frame)
genre_frame.pack(side=tk.LEFT, padx=10)
tk.Label(genre_frame, text="Genre:").pack(side=tk.LEFT)
genres = ["All", "Action", "Adventure", "Animation", "Comedy", "Crime", "Documentary", "Drama", "Family", "Fantasy", "History", "Horror", "Music", "Mystery", "Romance", "Science Fiction", "TV Movie", "Thriller", "War", "Western"]
genre_menu = ttk.Combobox(genre_frame, textvariable=genre_var, values=genres)
genre_menu.pack(side=tk.LEFT)
genre_menu.bind("<<ComboboxSelected>>", update_displayed_movies)

# Language filter
language_frame = tk.Frame(filter_frame)
language_frame.pack(side=tk.LEFT, padx=10)
tk.Label(language_frame, text="Language:").pack(side=tk.LEFT)
languages = ["All", "en", "fr", "es", "de", "it", "ja", "ko", "zh"]
language_menu = ttk.Combobox(language_frame, textvariable=language_var, values=languages)
language_menu.pack(side=tk.LEFT)
language_menu.bind("<<ComboboxSelected>>", update_displayed_movies)

# Runtime filter
runtime_frame = tk.Frame(filter_frame)
runtime_frame.pack(side=tk.LEFT, padx=10)
tk.Label(runtime_frame, text="Runtime:").pack(side=tk.LEFT)
runtimes = ["All", "Less than 60 minutes", "60 to 90 minutes", "90 to 120 minutes", "More than 120 minutes"]
runtime_menu = ttk.Combobox(runtime_frame, textvariable=runtime_var, values=runtimes)
runtime_menu.pack(side=tk.LEFT)
runtime_menu.bind("<<ComboboxSelected>>", update_displayed_movies)

# Letter filter
letter_frame = tk.Frame(filter_frame)
letter_frame.pack(side=tk.LEFT, padx=10)
tk.Label(letter_frame, text="Letter:").pack(side=tk.LEFT)
letters = ["All"] + [chr(i) for i in range(65, 91)]
letter_menu = ttk.Combobox(letter_frame, textvariable=letter_var, values=letters)
letter_menu.pack(side=tk.LEFT)
letter_menu.bind("<<ComboboxSelected>>", update_displayed_movies)

# Search box
search_label = tk.Label(root, text="Search:")
search_label.place(relx=1.0, x=-10, y=10, anchor='ne')
search_entry = ttk.Entry(root, textvariable=search_var)
search_entry.place(relx=1.0, x=-10, y=30, anchor='ne')
search_var.trace_add('write', update_displayed_movies)

# Sort order filter
sort_order_frame = tk.Frame(root)
sort_order_frame.pack(pady=10)
tk.Label(sort_order_frame, text="Sort Order:").pack(side=tk.LEFT)
sort_orders = ["Alphabetically (A-Z)", "Alphabetically (Z-A)", "By Date Released (Newest to Oldest)", "By Date Released (Oldest to Newest)", "By Date Added to My List (Newest to Oldest)", "By Date Added to My List (Oldest to Newest)", "Ranking (Highest to Lowest)", "Ranking (Lowest to Highest)"]
sort_order_menu = ttk.Combobox(sort_order_frame, textvariable=sort_order_var, values=sort_orders, width=40)
sort_order_menu.pack(side=tk.LEFT)
sort_order_menu.bind("<<ComboboxSelected>>", update_displayed_movies)

# Add button to pick random movie, open link, reset filters, and reset API credentials
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
random_button = tk.Button(button_frame, text="Pick a Random Movie", command=pick_random_movie)
random_button.pack(side=tk.LEFT, padx=5)

open_link_button = tk.Button(button_frame, text="Open Movie Link", state=tk.DISABLED)
open_link_button.pack(side=tk.LEFT, padx=5)

reset_button = tk.Button(button_frame, text="Reset Filters", command=reset_filters)
reset_button.pack(side=tk.LEFT, padx=5)

reset_api_button = tk.Button(button_frame, text="Reset API Keys", command=confirm_reset_api_credentials)
reset_api_button.pack(side=tk.LEFT, padx=5)

# Loading indicator
loading_label = tk.Label(root, text="Loading...")
loading_label.pack(pady=20)

# Start background thread to fetch additional movie data
thread = threading.Thread(target=fetch_additional_movie_data)
thread.start()

# Run the GUI loop
root.mainloop()
