from urllib.parse import urlencode
import webbrowser
import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.dialogs import Messagebox, QueryDialog
from ..controller import Controller
from ..geometry import geometry
from ..activation import valid_key
from ..license_info import license_info


class AttributionTab(ttk.Frame):
    def __init__(self, app):
        self.app = app
        self.c: Controller = self.app.c
        self.license_widgets = []
        self.attribution_buttons = []
        super().__init__(
            self.app.notebook,
            padding=(geometry.whp(4), geometry.whp(4))
        )
        self.create_widgets()

    def create_widgets(self):
        parent = self

        parent.columnconfigure(0, weight=0)
        parent.columnconfigure(1, weight=1)

        buttons_frame = ttk.Frame(parent)
        buttons_frame.grid(
            row=0,
            column=0,
            sticky="w",
            padx=(0, geometry.whp(4)),
            pady=10,
        )

        button_width = 5
        is_evaluation = license_info.is_evaluation()
        yes_button_state = "normal"
        no_button_state = "normal" if license_info.is_regular() else "disabled"

        if is_evaluation:
            self.c.include_attribution_var.set(True)

        yes_button = ttk.Radiobutton(
            buttons_frame,
            text="Yes",
            value=True,
            variable=self.c.include_attribution_var,
            command=self.on_include_attribution_changed,
            bootstyle="primary-outline-toolbutton",
            width=button_width,
            state=yes_button_state,
        )
        yes_button.grid(row=0, column=0, sticky="w")
        self.attribution_buttons.append(yes_button)

        no_button = ttk.Radiobutton(
            buttons_frame,
            text="No",
            value=False,
            variable=self.c.include_attribution_var,
            command=self.on_include_attribution_changed,
            bootstyle="primary-outline-toolbutton",
            width=button_width,
            state=no_button_state,
        )
        no_button.grid(row=0, column=1, sticky="w")
        self.attribution_buttons.append(no_button)

        ttk.Label(
            parent,
            text=(
                "Insert attribution message in generated speech"
                if is_evaluation
                else "Include attribution message in generated speech"
            ),
        ).grid(row=0, column=1, sticky="w", pady=10)

        if license_info.is_regular():
            return

        configurable_label = ttk.Label(
            parent,
            text="This setting is configurable in the regular version.",
            justify="left",
        )
        configurable_label.grid(
            row=1,
            column=0,
            columnspan=2,
            sticky="w",
            pady=(geometry.whp(3), 0),
        )
        self.license_widgets.append(configurable_label)

        upgrade_label = ttk.Label(
            parent,
            text=(
                "Upgrade to the regular version for $15.\n"
                "Simple one-time payment. No subscription."
            ),
            justify="left",
        )
        upgrade_label.grid(
            row=2,
            column=0,
            columnspan=2,
            sticky="w",
            pady=(geometry.whp(5), 0),
        )
        self.license_widgets.append(upgrade_label)

        action_frame = ttk.Frame(parent)
        action_frame.grid(
            row=3,
            column=0,
            columnspan=2,
            sticky="w",
            pady=(geometry.whp(4), 0),
        )
        self.license_widgets.append(action_frame)

        action_button_width = 10

        ttk.Button(
            action_frame,
            text="Upgrade",
            style="Action.TButton",
            width=action_button_width,
            padding=(0, geometry.whp(1)),
            command=self.on_upgrade_clicked,
        ).grid(row=0, column=0, padx=(0, geometry.whp(4)))

        ttk.Button(
            action_frame,
            text="Activate",
            width=action_button_width,
            padding=(0, geometry.whp(1)),
            bootstyle="outline",
            command=self.on_activate_clicked,
        ).grid(row=0, column=1)

    def on_include_attribution_changed(self):
        if license_info.is_evaluation():
            self.c.include_attribution_var.set(True)
            return

        self.c.save_attribution_settings()

    def on_upgrade_clicked(self):
        base_url = "https://jimlet.com/sales/upgrade.html"
        params = {
            "utm_source": "jimlet",
            "utm_medium": "app",
            "utm_content": "upgrade_button",
        }

        url = f"{base_url}?{urlencode(params)}"
        webbrowser.open(url)

    def on_license_activated(self, key: str) -> None:
        license_info.mark_regular(key)
        self.c.include_attribution_var.set(False)
        self.c.save_attribution_settings()

        for button in self.attribution_buttons:
            button.configure(state="normal")

        for widget in self.license_widgets:
            widget.grid_remove()

    def on_activate_clicked(self):
        dialog = LicenseKeyDialog(
            "Enter license key",
            title="Activate",
            parent=self.winfo_toplevel(),
        )
        dialog.show()
        key = dialog._result  # pylint: disable=protected-access

        if key is not None:
            key = key.strip()

            if not key:
                Messagebox.show_error(
                    "No license key entered",
                    title="Invalid license key",
                    parent=self.winfo_toplevel(),
                )
                return

            is_valid = valid_key(key)

            if not is_valid:
                Messagebox.show_error(
                    "The license key you entered is not valid",
                    title="Invalid license key",
                    parent=self.winfo_toplevel(),
                )
                return

            self.on_license_activated(key)

            Messagebox.show_info(
                title="License activated",
                message="Your license key was accepted.\nPlease restart the program.",
                parent=self.winfo_toplevel(),
            )


class LicenseKeyDialog(QueryDialog):
    def create_body(self, master):
        super().create_body(master)

        entry = self._initial_focus
        for sequence in (
            "<Control-v>",
            "<Control-V>",
            "<Command-v>",
            "<Command-V>",
            "<Shift-Insert>",
        ):
            entry.bind(sequence, self.on_paste)

    def on_paste(self, _event=None):
        try:
            text = self._initial_focus.clipboard_get()
        except tk.TclError:
            return "break"

        try:
            self._initial_focus.delete(tk.SEL_FIRST, tk.SEL_LAST)
        except tk.TclError:
            pass

        self._initial_focus.insert(tk.INSERT, text)
        return "break"
