"""
TOTP tab — Google Authenticator compatible 2FA codes.
Live countdown, one-click copy, per-server secrets.
"""

import threading
import customtkinter as ctk
from core.i18n import t


class TOTPTab(ctk.CTkFrame):
    def __init__(self, master, store):
        super().__init__(master, fg_color="transparent")
        self.store = store
        self._current_alias: str | None = None
        self._timer_id = None

        # Title
        self.title_label = ctk.CTkLabel(
            self, text=t("totp_title"),
            font=ctk.CTkFont(size=16, weight="bold"), anchor="w"
        )
        self.title_label.pack(fill="x", padx=15, pady=(15, 5))

        # Description
        self.desc_label = ctk.CTkLabel(
            self, text=t("totp_desc"),
            anchor="w", text_color="#9ca3af", wraplength=600, justify="left"
        )
        self.desc_label.pack(fill="x", padx=15, pady=(0, 10))

        # Server name
        self.server_label = ctk.CTkLabel(
            self, text=t("no_server_selected"),
            font=ctk.CTkFont(size=13), anchor="w", text_color="#6b7280"
        )
        self.server_label.pack(fill="x", padx=15, pady=(0, 10))

        # Code display frame
        code_frame = ctk.CTkFrame(self, fg_color="#1e1e2e", corner_radius=12)
        code_frame.pack(fill="x", padx=15, pady=(0, 10))

        self.code_label = ctk.CTkLabel(
            code_frame, text="------",
            font=ctk.CTkFont(family="Consolas", size=42, weight="bold"),
            text_color="#22c55e"
        )
        self.code_label.pack(pady=(20, 5))

        self.timer_label = ctk.CTkLabel(
            code_frame, text="",
            font=ctk.CTkFont(size=12), text_color="#9ca3af"
        )
        self.timer_label.pack(pady=(0, 5))

        self.progress_bar = ctk.CTkProgressBar(code_frame, width=300, height=6)
        self.progress_bar.pack(pady=(0, 15))
        self.progress_bar.set(1.0)

        # Copy button
        self.copy_btn = ctk.CTkButton(
            self, text=t("totp_copy"), width=200, height=40,
            font=ctk.CTkFont(size=14),
            fg_color="#22c55e", hover_color="#16a34a",
            command=self._copy_code
        )
        self.copy_btn.pack(pady=(5, 15))

        # Secret management section
        secret_frame = ctk.CTkFrame(self, fg_color="transparent")
        secret_frame.pack(fill="x", padx=15, pady=(10, 5))

        ctk.CTkLabel(
            secret_frame, text=t("totp_secret_label"),
            font=ctk.CTkFont(size=13, weight="bold"), anchor="w"
        ).pack(fill="x")

        entry_row = ctk.CTkFrame(secret_frame, fg_color="transparent")
        entry_row.pack(fill="x", pady=(5, 0))

        self.secret_entry = ctk.CTkEntry(
            entry_row, show="*",
            placeholder_text=t("totp_secret_placeholder"),
            font=ctk.CTkFont(family="Consolas", size=12)
        )
        self.secret_entry.pack(side="left", fill="x", expand=True, padx=(0, 5))

        self.show_secret_btn = ctk.CTkButton(
            entry_row, text=t("show"), width=70,
            fg_color="#6b7280", hover_color="#4b5563",
            command=self._toggle_secret
        )
        self.show_secret_btn.pack(side="left", padx=(0, 5))
        self._secret_visible = False

        self.save_secret_btn = ctk.CTkButton(
            entry_row, text=t("totp_save_secret"), width=100,
            command=self._save_secret
        )
        self.save_secret_btn.pack(side="left", padx=(0, 5))

        self.remove_secret_btn = ctk.CTkButton(
            entry_row, text=t("totp_remove_secret"), width=100,
            fg_color="#ef4444", hover_color="#dc2626",
            command=self._remove_secret
        )
        self.remove_secret_btn.pack(side="left")

        # Generate random secret button
        self.gen_secret_btn = ctk.CTkButton(
            secret_frame, text=t("totp_generate_secret"), width=180,
            fg_color="#6b7280", hover_color="#4b5563",
            command=self._generate_secret
        )
        self.gen_secret_btn.pack(anchor="w", pady=(8, 0))

        # Status log
        self.status_label = ctk.CTkLabel(
            self, text="", anchor="w", text_color="#9ca3af"
        )
        self.status_label.pack(fill="x", padx=15, pady=(5, 10))

    def set_server(self, alias: str | None):
        self._current_alias = alias
        self._stop_timer()

        if not alias:
            self.server_label.configure(text=t("no_server_selected"))
            self.code_label.configure(text="------")
            self.timer_label.configure(text="")
            self.progress_bar.set(1.0)
            self.secret_entry.delete(0, "end")
            self.status_label.configure(text="")
            return

        self.server_label.configure(text=f"🖥 {alias}")
        server = self.store.get_server(alias)
        if not server:
            return

        secret = server.get("totp_secret", "")
        self.secret_entry.delete(0, "end")
        if secret:
            self.secret_entry.insert(0, secret)
            self._start_timer()
        else:
            self.code_label.configure(text="------")
            self.timer_label.configure(text=t("totp_no_secret"))
            self.progress_bar.set(1.0)

    def _start_timer(self):
        self._stop_timer()
        self._update_code()

    def _stop_timer(self):
        if self._timer_id:
            self.after_cancel(self._timer_id)
            self._timer_id = None

    def _update_code(self):
        if not self._current_alias:
            return

        server = self.store.get_server(self._current_alias)
        if not server:
            return

        secret = server.get("totp_secret", "")
        if not secret:
            self.code_label.configure(text="------")
            self.timer_label.configure(text=t("totp_no_secret"))
            self.progress_bar.set(1.0)
            return

        try:
            from core.totp import get_code_with_timer
            data = get_code_with_timer(secret)
            code = data["code"]
            remaining = data["remaining"]
            progress = data["progress"]

            # Format code with space in middle: "123 456"
            formatted = f"{code[:3]} {code[3:]}"
            self.code_label.configure(text=formatted)
            self.timer_label.configure(text=t("totp_remaining").format(sec=remaining))
            self.progress_bar.set(progress)

            # Color based on time remaining
            if remaining <= 5:
                self.code_label.configure(text_color="#ef4444")
            elif remaining <= 10:
                self.code_label.configure(text_color="#f59e0b")
            else:
                self.code_label.configure(text_color="#22c55e")

        except Exception as e:
            self.code_label.configure(text="ERROR")
            self.timer_label.configure(text=str(e))

        # Schedule next update in 1 second
        self._timer_id = self.after(1000, self._update_code)

    def _copy_code(self):
        code_text = self.code_label.cget("text").replace(" ", "")
        if code_text and code_text != "------" and code_text != "ERROR":
            self.clipboard_clear()
            self.clipboard_append(code_text)
            self.status_label.configure(text=t("totp_copied"), text_color="#22c55e")
            self.after(2000, lambda: self.status_label.configure(text=""))
        else:
            self.status_label.configure(text=t("totp_no_code"), text_color="#ef4444")
            self.after(2000, lambda: self.status_label.configure(text=""))

    def _toggle_secret(self):
        self._secret_visible = not self._secret_visible
        self.secret_entry.configure(show="" if self._secret_visible else "*")
        self.show_secret_btn.configure(text=t("hide") if self._secret_visible else t("show"))

    def _save_secret(self):
        if not self._current_alias:
            self.status_label.configure(text=t("no_server_selected"), text_color="#ef4444")
            return

        secret = self.secret_entry.get().strip()
        if not secret:
            self.status_label.configure(text=t("totp_secret_empty"), text_color="#ef4444")
            self.after(2000, lambda: self.status_label.configure(text=""))
            return

        # Validate secret
        try:
            from core.totp import get_code
            get_code(secret)
        except Exception:
            self.status_label.configure(text=t("totp_secret_invalid"), text_color="#ef4444")
            self.after(2000, lambda: self.status_label.configure(text=""))
            return

        server = self.store.get_server(self._current_alias)
        if server:
            server["totp_secret"] = secret
            self.store.update_server(self._current_alias, server)
            self.status_label.configure(text=t("totp_secret_saved"), text_color="#22c55e")
            self.after(2000, lambda: self.status_label.configure(text=""))
            self._start_timer()

    def _remove_secret(self):
        if not self._current_alias:
            return

        server = self.store.get_server(self._current_alias)
        if server and "totp_secret" in server:
            del server["totp_secret"]
            self.store.update_server(self._current_alias, server)
            self.secret_entry.delete(0, "end")
            self._stop_timer()
            self.code_label.configure(text="------", text_color="#22c55e")
            self.timer_label.configure(text="")
            self.progress_bar.set(1.0)
            self.status_label.configure(text=t("totp_secret_removed"), text_color="#9ca3af")
            self.after(2000, lambda: self.status_label.configure(text=""))

    def _generate_secret(self):
        try:
            from core.totp import generate_secret
            secret = generate_secret()
            self.secret_entry.delete(0, "end")
            self.secret_entry.insert(0, secret)
            self.status_label.configure(text=t("totp_secret_generated"), text_color="#22c55e")
            self.after(2000, lambda: self.status_label.configure(text=""))
        except Exception as e:
            self.status_label.configure(text=f"Error: {e}", text_color="#ef4444")

    def update_language(self):
        self.title_label.configure(text=t("totp_title"))
        self.desc_label.configure(text=t("totp_desc"))
        self.copy_btn.configure(text=t("totp_copy"))
        self.save_secret_btn.configure(text=t("totp_save_secret"))
        self.remove_secret_btn.configure(text=t("totp_remove_secret"))
        self.gen_secret_btn.configure(text=t("totp_generate_secret"))
        self.show_secret_btn.configure(
            text=t("hide") if self._secret_visible else t("show")
        )
        if not self._current_alias:
            self.server_label.configure(text=t("no_server_selected"))
