import secrets
import string
import random
import tkinter as tk
from tkinter import ttk, messagebox

class PasswordGeneratorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Генератор паролей")
        self.root.resizable(False, False)

        self.length_var = tk.IntVar(value=12)
        self.upper_var = tk.BooleanVar(value=True)
        self.lower_var = tk.BooleanVar(value=True)
        self.digit_var = tk.BooleanVar(value=True)
        self.special_var = tk.BooleanVar(value=True)
        self.password_var = tk.StringVar()
        self.copy_status_var = tk.StringVar()

        self.create_widgets()
        self.update_strength_bar("none")

    def create_widgets(self):
        main_frame = ttk.Frame(self.root, padding="10 10 10 10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        length_frame = ttk.Frame(main_frame)
        length_frame.grid(row=0, column=0, sticky=tk.W, pady=(0, 5))
        ttk.Label(length_frame, text="Длина:").pack(side=tk.LEFT)
        length_spinbox = ttk.Spinbox(
            length_frame,
            from_=6,
            to=32,
            textvariable=self.length_var,
            width=5,
            justify=tk.CENTER
        )
        length_spinbox.pack(side=tk.LEFT, padx=(5, 0))

        check_frame = ttk.Frame(main_frame)
        check_frame.grid(row=1, column=0, sticky=tk.W, pady=(0, 10))
        ttk.Checkbutton(check_frame, text="Заглавные буквы", variable=self.upper_var).grid(row=0, column=0, sticky=tk.W)
        ttk.Checkbutton(check_frame, text="Строчные буквы", variable=self.lower_var).grid(row=0, column=1, sticky=tk.W, padx=(10, 0))
        ttk.Checkbutton(check_frame, text="Цифры", variable=self.digit_var).grid(row=1, column=0, sticky=tk.W)
        ttk.Checkbutton(check_frame, text="Спецсимволы", variable=self.special_var).grid(row=1, column=1, sticky=tk.W, padx=(10, 0))

        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=2, column=0, pady=(0, 10))
        ttk.Button(button_frame, text="Создать", command=self.generate_password).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(button_frame, text="Копировать", command=self.copy_password).pack(side=tk.LEFT)

        password_entry = ttk.Entry(
            main_frame,
            textvariable=self.password_var,
            font=("Courier", 16),
            justify=tk.CENTER,
            state="readonly"
        )
        password_entry.grid(row=3, column=0, sticky=tk.EW, pady=(0, 5))

        self.copy_status_label = ttk.Label(main_frame, textvariable=self.copy_status_var)
        self.copy_status_label.grid(row=4, column=0, sticky=tk.W, pady=(0, 5))

        self.strength_canvas = tk.Canvas(main_frame, width=250, height=20, bg="lightgray", highlightthickness=0)
        self.strength_canvas.grid(row=5, column=0, sticky=tk.W)

    def generate_password(self):
        length = self.length_var.get()
        if not (6 <= length <= 32):
            messagebox.showerror("Ошибка", "Длина должна быть от 6 до 32")
            return

        selected_sets = []
        if self.upper_var.get():
            selected_sets.append(string.ascii_uppercase)
        if self.lower_var.get():
            selected_sets.append(string.ascii_lowercase)
        if self.digit_var.get():
            selected_sets.append(string.digits)
        if self.special_var.get():
            selected_sets.append(string.punctuation)

        if not selected_sets:
            messagebox.showerror("Ошибка", "Выберите хотя бы один вид символов")
            self.update_strength_bar("none")
            return

        all_chars = ''.join(selected_sets)
        password_chars = [secrets.choice(s) for s in selected_sets]
        remaining = length - len(password_chars)
        if remaining > 0:
            password_chars.extend(secrets.choice(all_chars) for _ in range(remaining))

        rng = random.SystemRandom()
        rng.shuffle(password_chars)
        password = ''.join(password_chars)
        self.password_var.set(password)
        self.copy_status_var.set("")

        types_count = len(selected_sets)
        strength = self.compute_strength(length, types_count)
        self.update_strength_bar(strength)

    def compute_strength(self, length, types_count):
        if length >= 12 and types_count >= 3:
            return "strong"
        elif length >= 8 and types_count >= 2:
            return "medium"
        else:
            return "weak"

    def update_strength_bar(self, strength):
        self.strength_canvas.delete("all")
        colors = {
            "weak": "red",
            "medium": "#FFD700",
            "strong": "green",
            "none": "lightgray"
        }
        color = colors.get(strength, "lightgray")
        self.strength_canvas.create_rectangle(0, 0, 250, 20, fill=color, outline="")

    def copy_password(self):
        password = self.password_var.get()
        if password:
            self.root.clipboard_clear()
            self.root.clipboard_append(password)
            self.root.update()
            self.copy_status_var.set("Скопировано")
        else:
            messagebox.showwarning("Предупреждение", "Нет пароля для копирования")

if __name__ == "__main__":
    root = tk.Tk()
    app = PasswordGeneratorApp(root)
    root.mainloop()