"""
Server add/edit dialog — modal window with all server fields.
"""

import customtkinter as ctk
from core.server_store import SERVER_TYPES, DEFAULT_PORTS
from core.i18n import t


class ServerDialog(ctk.CTkToplevel):
    def __init__(self, master, store, server: dict | None = None):
        super().__init__(master)
        self.store = store
        self.editing = server
        self.result = None

        self.title(t("edit_server") if server else t("add_server"))
        self.geometry("450x580")
        self.resizable(False, False)
        self.grab_set()

        # Center on parent
        self.transient(master)

        self._build_ui(server)

    def _build_ui(self, server: dict | None):
        pad = {"padx": 20, "pady": (5, 0)}
        entry_pad = {"padx": 20, "pady": (2, 5)}

        # Alias
        ctk.CTkLabel(self, text=t("alias"), anchor="w").pack(fill="x", **pad)
        self.alias_entry = ctk.CTkEntry(self, placeholder_text=t("placeholder_alias"))
        self.alias_entry.pack(fill="x", **entry_pad)

        # IP
        ctk.CTkLabel(self, text=t("ip"), anchor="w").pack(fill="x", **pad)
        self.ip_entry = ctk.CTkEntry(self, placeholder_text=t("placeholder_ip"))
        self.ip_entry.pack(fill="x", **entry_pad)

        # Type + Port row
        row = ctk.CTkFrame(self, fg_color="transparent")
        row.pack(fill="x", padx=20, pady=(5, 5))

        type_frame = ctk.CTkFrame(row, fg_color="transparent")
        type_frame.pack(side="left", fill="x", expand=True, padx=(0, 5))
        ctk.CTkLabel(type_frame, text=t("type"), anchor="w").pack(fill="x")
        self.type_var = ctk.StringVar(value="ssh")
        self.type_menu = ctk.CTkOptionMenu(
            type_frame, values=SERVER_TYPES, variable=self.type_var,
            command=self._on_type_change
        )
        self.type_menu.pack(fill="x")

        port_frame = ctk.CTkFrame(row, fg_color="transparent")
        port_frame.pack(side="left", fill="x", expand=True, padx=(5, 0))
        ctk.CTkLabel(port_frame, text=t("port"), anchor="w").pack(fill="x")
        self.port_entry = ctk.CTkEntry(port_frame, placeholder_text=t("placeholder_port"))
        self.port_entry.pack(fill="x")

        # User
        ctk.CTkLabel(self, text=t("username"), anchor="w").pack(fill="x", **pad)
        self.user_entry = ctk.CTkEntry(self, placeholder_text=t("placeholder_user"))
        self.user_entry.pack(fill="x", **entry_pad)

        # Password
        ctk.CTkLabel(self, text=t("password"), anchor="w").pack(fill="x", **pad)
        pass_frame = ctk.CTkFrame(self, fg_color="transparent")
        pass_frame.pack(fill="x", padx=20, pady=(2, 5))
        self.password_entry = ctk.CTkEntry(pass_frame, show="*", placeholder_text=t("placeholder_password"))
        self.password_entry.pack(side="left", fill="x", expand=True, padx=(0, 5))
        self.show_pass = ctk.CTkButton(pass_frame, text=t("show"), width=60, command=self._toggle_password)
        self.show_pass.pack(side="right")
        self._pass_visible = False

        # TOTP Secret
        ctk.CTkLabel(self, text=t("totp_secret_dialog"), anchor="w").pack(fill="x", **pad)
        self.totp_entry = ctk.CTkEntry(self, placeholder_text=t("placeholder_totp_secret"),
                                        font=ctk.CTkFont(family="Consolas", size=12))
        self.totp_entry.pack(fill="x", **entry_pad)

        # Notes
        ctk.CTkLabel(self, text=t("notes"), anchor="w").pack(fill="x", **pad)
        self.notes_entry = ctk.CTkEntry(self, placeholder_text=t("placeholder_notes"))
        self.notes_entry.pack(fill="x", **entry_pad)

        # Buttons
        btn_frame = ctk.CTkFrame(self, fg_color="transparent")
        btn_frame.pack(fill="x", padx=20, pady=(15, 20))
        ctk.CTkButton(btn_frame, text=t("cancel"), fg_color="#6b7280", command=self.destroy).pack(side="left", expand=True, padx=(0, 5))
        ctk.CTkButton(btn_frame, text=t("save"), command=self._save).pack(side="right", expand=True, padx=(5, 0))

        # Fill values if editing
        if server:
            self.alias_entry.insert(0, server.get("alias", ""))
            self.alias_entry.configure(state="disabled")
            self.ip_entry.insert(0, server.get("ip", ""))
            self.type_var.set(server.get("type", "ssh"))
            self.port_entry.insert(0, str(server.get("port", 22)))
            self.user_entry.insert(0, server.get("user", ""))
            self.password_entry.insert(0, server.get("password", ""))
            self.totp_entry.insert(0, server.get("totp_secret", ""))
            self.notes_entry.insert(0, server.get("notes", ""))

    def _on_type_change(self, value):
        default_port = DEFAULT_PORTS.get(value, 22)
        self.port_entry.delete(0, "end")
        self.port_entry.insert(0, str(default_port))

    def _toggle_password(self):
        self._pass_visible = not self._pass_visible
        self.password_entry.configure(show="" if self._pass_visible else "*")
        self.show_pass.configure(text=t("hide") if self._pass_visible else t("show"))

    def _save(self):
        alias = self.alias_entry.get().strip()
        ip = self.ip_entry.get().strip()
        port_str = self.port_entry.get().strip()
        user = self.user_entry.get().strip()
        password = self.password_entry.get()
        server_type = self.type_var.get()
        totp_secret = self.totp_entry.get().strip()
        notes = self.notes_entry.get().strip()

        # Validation
        if not alias:
            self._show_error(t("alias_required"))
            return
        if not ip:
            self._show_error(t("ip_required"))
            return
        try:
            port = int(port_str) if port_str else DEFAULT_PORTS.get(server_type, 22)
        except ValueError:
            self._show_error(t("port_must_be_number"))
            return
        if port < 1 or port > 65535:
            self._show_error(t("port_out_of_range"))
            return

        server_data = {
            "alias": alias,
            "ip": ip,
            "port": port,
            "user": user or "root",
            "password": password,
            "type": server_type,
            "notes": notes,
        }
        if totp_secret:
            server_data["totp_secret"] = totp_secret

        try:
            if self.editing:
                self.store.update_server(alias, server_data)
            else:
                self.store.add_server(server_data)
            self.result = server_data
            self.destroy()
        except ValueError as e:
            self._show_error(str(e))

    def _show_error(self, message: str):
        # Simple error via title flash
        self.title(t("error_prefix").format(msg=message))
        self.after(2000, lambda: self.title(t("edit_server") if self.editing else t("add_server")))
