import sys
from tkinter import Frame, Label, Button, Entry, Toplevel, Canvas, BOTH, X, Y, LEFT, RIGHT, END, FLAT, RIDGE
from tkinter import ttk

# Color palette
BG_COLOR = "#f1f5f9"
SIDEBAR_COLOR = "#1e293b"
SIDEBAR_BTN = "#334155"
SIDEBAR_BTN_ACTIVE = "#475569"
CARD_COLOR = "#ffffff"
BORDER_COLOR = "#cbd5e1"
TEXT_PRIMARY = "#0f172a"
TEXT_SECONDARY = "#475569"
TEXT_MUTED = "#64748b"
TEXT_ON_DARK = "#ffffff"
ACCENT = "#2563eb"
ACCENT_HOVER = "#1d4ed8"
SUCCESS = "#16a34a"
WARNING = "#d97706"
DANGER = "#dc2626"

FONT_TITLE = ("Helvetica Neue", 22, "bold")
FONT_SUBTITLE = ("Helvetica Neue", 13)
FONT_NORMAL = ("Helvetica Neue", 11)
FONT_SMALL = ("Helvetica Neue", 10)
FONT_SIDEBAR = ("Helvetica Neue", 12, "bold")


def maximize_window(root):
    """Maximize the window on Windows, macOS, and Linux."""
    try:
        if sys.platform == "win32":
            root.state("zoomed")
        elif sys.platform == "darwin":
            root.state("zoomed")
        else:
            root.attributes("-zoomed", True)
    except Exception:
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        root.geometry(f"{screen_width}x{screen_height}+0+0")


def setup_app_style(root):
    """Apply a consistent theme that works on macOS, Windows, and Linux."""
    root.configure(bg=BG_COLOR)
    style = ttk.Style(root)
    style.theme_use("clam")

    style.configure(
        "Treeview",
        background=CARD_COLOR,
        foreground=TEXT_PRIMARY,
        rowheight=30,
        fieldbackground=CARD_COLOR,
        font=FONT_NORMAL,
        borderwidth=1,
        relief="flat",
    )
    style.configure(
        "Treeview.Heading",
        background=SIDEBAR_COLOR,
        foreground=TEXT_ON_DARK,
        font=("Helvetica Neue", 11, "bold"),
        relief="flat",
        padding=8,
    )
    style.map(
        "Treeview",
        background=[("selected", "#dbeafe")],
        foreground=[("selected", TEXT_PRIMARY)],
    )
    style.map("Treeview.Heading", background=[("active", SIDEBAR_BTN)])

    style.configure(
        "Sidebar.TButton",
        background=SIDEBAR_BTN,
        foreground=TEXT_ON_DARK,
        borderwidth=0,
        focuscolor=SIDEBAR_BTN,
        font=FONT_NORMAL,
        padding=(12, 10),
    )
    style.map(
        "Sidebar.TButton",
        background=[("active", SIDEBAR_BTN_ACTIVE), ("pressed", "#1e293b")],
        foreground=[("active", TEXT_ON_DARK)],
    )

    style.configure(
        "Primary.TButton",
        background=ACCENT,
        foreground=TEXT_ON_DARK,
        borderwidth=0,
        font=("Helvetica Neue", 11, "bold"),
        padding=(14, 8),
    )
    style.map(
        "Primary.TButton",
        background=[("active", ACCENT_HOVER), ("pressed", "#1e40af")],
    )

    style.configure(
        "Success.TButton",
        background=SUCCESS,
        foreground=TEXT_ON_DARK,
        borderwidth=0,
        font=FONT_NORMAL,
        padding=(12, 8),
    )
    style.map("Success.TButton", background=[("active", "#15803d")])

    style.configure(
        "Warning.TButton",
        background=WARNING,
        foreground=TEXT_ON_DARK,
        borderwidth=0,
        font=FONT_NORMAL,
        padding=(12, 8),
    )
    style.map("Warning.TButton", background=[("active", "#b45309")])

    style.configure(
        "Danger.TButton",
        background=DANGER,
        foreground=TEXT_ON_DARK,
        borderwidth=0,
        font=FONT_NORMAL,
        padding=(12, 8),
    )
    style.map("Danger.TButton", background=[("active", "#b91c1c")])

    return style


def make_page_header(parent, title, subtitle=None):
    header = Frame(parent, bg=BG_COLOR)
    header.pack(fill=X, padx=28, pady=(24, 12))

    title_row = Frame(header, bg=BG_COLOR)
    title_row.pack(fill=X)

    Label(
        title_row,
        text=title,
        font=FONT_TITLE,
        fg=TEXT_PRIMARY,
        bg=BG_COLOR,
        anchor="w",
    ).pack(fill=X)

    if subtitle:
        Label(
            header,
            text=subtitle,
            font=FONT_SUBTITLE,
            fg=TEXT_MUTED,
            bg=BG_COLOR,
            anchor="w",
        ).pack(fill=X, pady=(4, 0))

    Frame(parent, bg=BORDER_COLOR, height=1).pack(fill=X, padx=28, pady=(0, 8))
    return header


def setup_page_navigation(parent, home_page_fn):
    """
    Top toolbar with Back + Refresh; returns a SCROLLABLE content frame and navigation helpers.

    FIX: content is now placed inside a Canvas + Scrollbar so that pages taller than the
    window (like Email Overdue Students, with its Step 1 box + student list + form area)
    can be scrolled into view instead of being cut off with no way to reach buttons
    further down the page (e.g. the "Send Email to Student" button).
    """
    toolbar = Frame(parent, bg=BG_COLOR)
    toolbar.pack(fill=X, padx=28, pady=(14, 0))

    # --- Scrollable container setup ---
    outer = Frame(parent, bg=BG_COLOR)
    outer.pack(fill=BOTH, expand=True)

    canvas = Canvas(outer, bg=BG_COLOR, highlightthickness=0)
    v_scroll = ttk.Scrollbar(outer, orient="vertical", command=canvas.yview)
    canvas.configure(yscrollcommand=v_scroll.set)

    canvas.pack(side=LEFT, fill=BOTH, expand=True)
    v_scroll.pack(side=RIGHT, fill=Y)

    content = Frame(canvas, bg=BG_COLOR)
    content_window = canvas.create_window((0, 0), window=content, anchor="nw")

    def on_content_configure(_event=None):
        canvas.configure(scrollregion=canvas.bbox("all"))

    def on_canvas_configure(event):
        # Keep the inner frame the same width as the visible canvas
        canvas.itemconfig(content_window, width=event.width)

    content.bind("<Configure>", on_content_configure)
    canvas.bind("<Configure>", on_canvas_configure)

    def on_mousewheel(event):
        canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

    def bind_mousewheel(_event=None):
        canvas.bind_all("<MouseWheel>", on_mousewheel)

    def unbind_mousewheel(_event=None):
        canvas.unbind_all("<MouseWheel>")

    canvas.bind("<Enter>", bind_mousewheel)
    canvas.bind("<Leave>", unbind_mousewheel)
    # --- end scrollable container setup ---

    state = {"current": home_page_fn}
    buttons = {}

    def clear_content():
        for widget in content.winfo_children():
            widget.destroy()
        canvas.yview_moveto(0)  # reset scroll position when switching pages

    def refresh_current():
        if state["current"]:
            state["current"]()

    def go_back():
        open_page(home_page_fn, is_home=True)

    def open_page(page_fn, is_home=False):
        state["current"] = page_fn
        if is_home:
            buttons["back"].pack_forget()
        else:
            buttons["back"].pack(side=LEFT, padx=(0, 8))
        page_fn()

    buttons["back"] = ttk.Button(toolbar, text="← Back", command=go_back)
    buttons["refresh"] = ttk.Button(
        toolbar, text="↻ Refresh", command=refresh_current, style="Primary.TButton",
    )
    buttons["refresh"].pack(side=RIGHT)

    return content, open_page, refresh_current, clear_content


def make_card(parent, **pack_kwargs):
    wrapper = Frame(parent, bg=BG_COLOR)
    wrapper.pack(fill=BOTH, expand=True, padx=28, pady=12, **pack_kwargs)

    card = Frame(
        wrapper,
        bg=CARD_COLOR,
        highlightbackground=BORDER_COLOR,
        highlightthickness=1,
        padx=20,
        pady=20,
    )
    card.pack(fill=BOTH, expand=True)
    return card


def make_label(parent, text, variant="normal", **kwargs):
    fonts = {
        "title": FONT_TITLE,
        "subtitle": FONT_SUBTITLE,
        "normal": FONT_NORMAL,
        "small": FONT_SMALL,
        "stat": ("Helvetica Neue", 28, "bold"),
    }
    colors = {
        "title": TEXT_PRIMARY,
        "subtitle": TEXT_SECONDARY,
        "normal": TEXT_PRIMARY,
        "small": TEXT_MUTED,
        "stat": ACCENT,
        "success": SUCCESS,
        "danger": DANGER,
        "link": ACCENT,
    }
    return Label(
        parent,
        text=text,
        font=fonts.get(variant, FONT_NORMAL),
        fg=colors.get(variant, TEXT_PRIMARY),
        bg=kwargs.pop("bg", CARD_COLOR),
        **kwargs,
    )


def make_entry(parent, width=40, show=None, **kwargs):
    entry = Entry(
        parent,
        width=width,
        font=FONT_NORMAL,
        fg=TEXT_PRIMARY,
        bg=CARD_COLOR,
        relief=FLAT,
        highlightthickness=1,
        highlightbackground=BORDER_COLOR,
        highlightcolor=ACCENT,
        insertbackground=TEXT_PRIMARY,
        **kwargs,
    )
    if show:
        entry.config(show=show)
    return entry


def make_form_field(parent, label_text, show=None, width=40):
    make_label(parent, label_text, variant="small", anchor="w").pack(fill=X, pady=(8, 2))
    entry = make_entry(parent, width=width, show=show)
    entry.pack(fill=X, pady=(0, 4))
    return entry


def make_sidebar(parent, title):
    sidebar = Frame(parent, bg=SIDEBAR_COLOR, width=240)
    sidebar.pack(side=LEFT, fill=Y)
    sidebar.pack_propagate(False)

    Label(
        sidebar,
        text=title,
        fg=TEXT_ON_DARK,
        bg=SIDEBAR_COLOR,
        font=FONT_SIDEBAR,
    ).pack(pady=(28, 20), padx=20, anchor="w")

    Label(sidebar, text="MENU", fg="#94a3b8", bg=SIDEBAR_COLOR, font=FONT_SMALL).pack(
        padx=20, anchor="w", pady=(0, 8)
    )
    return sidebar


def sidebar_button(parent, text, command):
    btn = ttk.Button(parent, text=text, style="Sidebar.TButton", command=command)
    btn.pack(fill=X, padx=16, pady=4)
    return btn


def sidebar_logout(parent, command):
    Frame(parent, bg=SIDEBAR_COLOR, height=20).pack(side="bottom", fill=X)
    btn = ttk.Button(parent, text="Logout", style="Danger.TButton", command=command)
    btn.pack(side="bottom", fill=X, padx=16, pady=16)
    return btn


def make_treeview(parent, columns, height=12):
    container = Frame(parent, bg=BG_COLOR)
    container.pack(fill=BOTH, expand=True, padx=28, pady=12)

    tree_frame = Frame(
        container,
        bg=CARD_COLOR,
        highlightbackground=BORDER_COLOR,
        highlightthickness=1,
    )
    tree_frame.pack(fill=BOTH, expand=True)

    tree = ttk.Treeview(
        tree_frame, columns=columns, show="headings", style="Treeview", height=height,
    )
    scrollbar = ttk.Scrollbar(tree_frame, orient="vertical", command=tree.yview)
    tree.configure(yscrollcommand=scrollbar.set)

    for col in columns:
        tree.heading(col, text=col)
        tree.column(col, minwidth=100, width=140, anchor="center")

    tree.pack(side=LEFT, fill=BOTH, expand=True)
    scrollbar.pack(side=RIGHT, fill=Y)
    return tree


def make_stat_card(parent, title, value, accent=ACCENT):
    card = Frame(
        parent,
        bg=CARD_COLOR,
        highlightbackground=BORDER_COLOR,
        highlightthickness=1,
        padx=36,
        pady=28,
    )
    make_label(card, title, variant="small", bg=CARD_COLOR).pack(anchor="w")
    Label(
        card,
        text=str(value),
        font=("Helvetica Neue", 32, "bold"),
        fg=accent,
        bg=CARD_COLOR,
    ).pack(anchor="w", pady=(8, 0))
    return card


def open_detail_popup(root, title, lines, buttons=None):
    popup = Toplevel(root)
    popup.title(title)
    popup.geometry("460x380")
    popup.configure(bg=CARD_COLOR)
    popup.resizable(False, False)

    make_label(popup, title, variant="title", bg=CARD_COLOR).pack(pady=(20, 12), padx=24, anchor="w")
    for line in lines:
        make_label(popup, line, variant="normal", bg=CARD_COLOR).pack(anchor="w", padx=24, pady=2)

    if buttons:
        btn_row = Frame(popup, bg=CARD_COLOR)
        btn_row.pack(side="bottom", fill=X, padx=24, pady=20)
        for btn in buttons:
            btn.pack(in_=btn_row, side=LEFT if btn.get("side") == "left" else RIGHT, padx=6)

    return popup