#!/usr/bin/env python3
import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import threading
from PIL import Image, ImageTk, ImageFilter

# --- Constants & Styling ---
BG_COLOR = "#0D1117"
CARD_COLOR = "#21262D"
ACCENT_COLOR = "#2F81F7"
TEXT_COLOR = "#C9D1D9"
TEXT_DIM = "#8B949E"
SUCCESS_COLOR = "#238636"

class SquareIconGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("Standard - Square Icon Studio")
        self.root.geometry("1000x700")
        self.root.configure(bg=BG_COLOR)
        
        self.source_paths = []
        self.output_dir = "src-tauri/icons"
        self.tk_orig: ImageTk.PhotoImage | None = None
        self.tk_after: ImageTk.PhotoImage | None = None
        self.is_processing = False

        self.setup_styles()
        self.setup_ui()

    def setup_styles(self):
        style = ttk.Style()
        style.theme_use("clam")
        
        style.configure("TFrame", background=BG_COLOR)
        style.configure("Card.TFrame", background=CARD_COLOR)
        style.configure("TLabel", background=BG_COLOR, foreground=TEXT_COLOR, font=("Segoe UI", 10))
        style.configure("Header.TLabel", background=BG_COLOR, foreground=TEXT_COLOR, font=("Segoe UI Bold", 20))
        style.configure("Sub.TLabel", background=BG_COLOR, foreground=TEXT_DIM, font=("Segoe UI", 11))
        
        style.configure("Config.TLabelframe", background=BG_COLOR, foreground=TEXT_COLOR)
        style.configure("Config.TLabelframe.Label", background=BG_COLOR, foreground=TEXT_COLOR, font=("Segoe UI Bold", 10))

    def setup_ui(self):
        # Sidebar for controls
        sidebar = ttk.Frame(self.root, padding=20)
        sidebar.pack(side="left", fill="y", padx=(0, 2))
        
        ttk.Label(sidebar, text="Square Icon", style="Header.TLabel").pack(anchor="w")
        ttk.Label(sidebar, text="Studio Utility", style="Sub.TLabel").pack(anchor="w", pady=(0, 40))

        # Main actions
        self.create_action_btn(sidebar, "Select Images", "Batch or single image", self.pick_images, ACCENT_COLOR)
        self.create_action_btn(sidebar, "Output Folder", f"Target: {self.output_dir}", self.pick_output, CARD_COLOR)

        # Config section
        config_frame = ttk.LabelFrame(sidebar, text=" Resolution ", padding=20, style="Config.TLabelframe")
        config_frame.pack(fill="x", pady=30)
        
        ttk.Label(config_frame, text="Target Size (px)").pack(anchor="w")
        self.size_var = tk.StringVar(value="1024")
        self.size_entry = tk.Entry(config_frame, textvariable=self.size_var, bg="#010409", fg=TEXT_COLOR, 
                                 insertbackground=TEXT_COLOR, relief="flat", font=("Segoe UI", 11))
        self.size_entry.pack(fill="x", pady=(5, 0), ipady=5)

        # Status
        self.status_var = tk.StringVar(value="Ready to process...")
        self.status_label = ttk.Label(sidebar, textvariable=self.status_var, style="Sub.TLabel", wraplength=250)
        self.status_label.pack(side="bottom", fill="x", pady=20)

        self.process_btn = tk.Button(sidebar, text="Generate Icons", font=("Segoe UI Bold", 12),
                                   bg=SUCCESS_COLOR, fg="white", relief="flat", cursor="hand2",
                                   command=self.start_processing, padx=20, pady=12)
        self.process_btn.pack(side="bottom", fill="x")

        # Preview Area
        preview_container = ttk.Frame(self.root, style="TFrame", padding=30)
        preview_container.pack(side="right", fill="both", expand=True)

        title_frame = ttk.Frame(preview_container)
        title_frame.pack(fill="x", pady=(0, 20))
        ttk.Label(title_frame, text="Before vs After", font=("Segoe UI Bold", 16)).pack(side="left")

        # Preview Boxes
        self.preview_grid = ttk.Frame(preview_container)
        self.preview_grid.pack(fill="both", expand=True)

        # Before
        before_frame = tk.Frame(self.preview_grid, bg="#161b22", highlightbackground="#30363d", highlightthickness=1)
        before_frame.place(relx=0.05, rely=0.05, relwidth=0.42, relheight=0.8)
        self.before_img_lbl = tk.Label(before_frame, text="Original", bg="#161b22", fg=TEXT_DIM)
        self.before_img_lbl.pack(fill="both", expand=True)

        # After
        after_frame = tk.Frame(self.preview_grid, bg="#161b22", highlightbackground="#30363d", highlightthickness=1)
        after_frame.place(relx=0.53, rely=0.05, relwidth=0.42, relheight=0.8)
        self.after_img_lbl = tk.Label(after_frame, text="Result", bg="#161b22", fg=TEXT_DIM)
        self.after_img_lbl.pack(fill="both", expand=True)

    def create_action_btn(self, parent, text, sub, cmd, color):
        f = tk.Frame(parent, bg=BG_COLOR)
        f.pack(fill="x", pady=(0, 20))
        
        b = tk.Button(f, text=text, command=cmd, bg=color, fg="white", 
                    font=("Segoe UI Bold", 11), relief="flat", cursor="hand2", pady=8)
        b.pack(fill="x")
        l = ttk.Label(f, text=sub, style="Sub.TLabel")
        l.pack(anchor="w", pady=(2, 0))

    def pick_images(self):
        paths = filedialog.askopenfilenames(title="Select Source Images")
        if paths:
            self.source_paths = list(paths)
            self.status_var.set(f"Loaded {len(self.source_paths)} file(s)")
            self.update_preview(self.source_paths[0])

    def pick_output(self):
        path = filedialog.askdirectory(title="Select Output Folder")
        if path:
            self.output_dir = path
            self.status_var.set(f"Output: {os.path.basename(path)}")

    def update_preview(self, path):
        try:
            img = Image.open(path).convert("RGBA")
            
            # Squared preview
            w, h = img.size
            s = max(w, h)
            square = Image.new("RGBA", (s, s), (0, 0, 0, 0))
            square.paste(img, ((s-w)//2, (s-h)//2))
            
            # Constraints
            max_p = 350
            
            # Thumbnails using compatible Resampling
            resample = getattr(Image, 'Resampling', Image).LANCZOS
            img.thumbnail((max_p, max_p), resample=resample)
            self.tk_orig = ImageTk.PhotoImage(img)
            self.before_img_lbl.config(image=self.tk_orig, text="")

            square.thumbnail((max_p, max_p), resample=resample)
            self.tk_after = ImageTk.PhotoImage(square)
            self.after_img_lbl.config(image=self.tk_after, text="")
            
        except Exception as e:
            self.status_var.set(f"Preview fail: {e}")

    def start_processing(self):
        if not self.source_paths: return
        self.is_processing = True
        self.process_btn.config(state="disabled", text="Working...")
        threading.Thread(target=self.run_logic, daemon=True).start()

    def run_logic(self):
        try:
            size = int(self.size_var.get())
            if not os.path.exists(self.output_dir): os.makedirs(self.output_dir)
            
            for i, p in enumerate(self.source_paths):
                self.status_var.set(f"Saving {i+1}/{len(self.source_paths)}...")
                make_square_icon(p, self.output_dir, size)
            
            self.root.after(0, lambda: messagebox.showinfo("Done", f"Processed {len(self.source_paths)} icons!"))
        except Exception as e:
            self.root.after(0, lambda: messagebox.showerror("Error", str(e)))
        finally:
            self.root.after(0, self.reset)

    def reset(self):
        self.is_processing = False
        self.process_btn.config(state="normal", text="Generate Icons")
        self.status_var.set("Ready for more.")

def make_square_icon(source_path, output_dir="src-tauri/icons", target_size=1024):
    """
    Core logic: Takes any image and turns it into a perfectly centered, 
    transparent square icon (PNG and multi-res ICO).
    """
    if not os.path.exists(source_path): return

    img = Image.open(source_path).convert("RGBA")
    width, height = img.size
    size = max(width, height)
    
    square = Image.new("RGBA", (size, size), (0, 0, 0, 0))
    offset = ((size - width) // 2, (size - height) // 2)
    square.paste(img, offset)

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # Standardize naming
    base = os.path.splitext(os.path.basename(source_path))[0]
    
    # 1. Detect Content Bounding Box (Auto-Zoom logic)
    # This ensures small icons are recognizable by removing empty transparent space
    bbox = img.getbbox()
    if bbox:
        # Crop to the actual icon content
        content = img.crop(bbox)
        c_w, c_h = content.size
        # Make content square with padding
        c_size = max(c_w, c_h)
        square = Image.new("RGBA", (c_size, c_size), (0, 0, 0, 0))
        square.paste(content, ((c_size - c_w) // 2, (c_size - c_h) // 2))

    # 2. Resampling Constants
    resample_high = getattr(Image, 'Resampling', Image).LANCZOS
    
    # 3. Save Primary (High-Res) PNG
    icon_png = square.resize((target_size, target_size), resample_high)
    png_path = os.path.join(output_dir, f"{base}_icon.png" if "app-icon" not in base else "icon.png")
    icon_png.save(png_path)

    # 4. Generate High-Quality Multi-Res for .ico (Manually Sharpened)
    icon_sizes = [256, 128, 64, 48, 32, 16]
    icon_layers = []
    
    for s in icon_sizes:
        # For small sizes, apply extra sharpening to ensure legibility
        layer = square.resize((s, s), resample_high)
        if s <= 32:
            # Apply subtle sharpening for small icons
            layer = layer.filter(ImageFilter.SHARPEN)
            # Boost contrast slightly if very small (improves legibility on dark/light bars)
            if s <= 16:
                layer = layer.filter(ImageFilter.EDGE_ENHANCE_MORE)
        icon_layers.append(layer)

    ico_path = os.path.join(output_dir, f"{base}_icon.ico" if "app-icon" not in base else "icon.ico")
    icon_layers[0].save(ico_path, sizes=[(l.width, l.height) for l in icon_layers], append_images=icon_layers[1:])

if __name__ == "__main__":
    if len(sys.argv) > 1:
        # CLI Mode
        make_square_icon(sys.argv[1])
    else:
        # GUI Mode
        root = tk.Tk()
        app = SquareIconGUI(root)
        root.mainloop()
