import tkinter as tk
from tkinter import ttk, font
from datetime import datetime
from socketio import Client


class ModernChatApp:
    def __init__(self, root):
        self.root = root
        self.sio = Client()
        self.setup_ui()
        self.setup_socket_events()
        self.configure_styles()

    def configure_styles(self):
        self.root.option_add("*Font", "Helvetica 10")
        style = ttk.Style()
        style.theme_use('clam')

        # Настройка цветов
        style.configure("TFrame", background="#2D2D2D")
        style.configure("TLabel", background="#2D2D2D", foreground="#FFFFFF")
        style.configure("TButton",
                        background="#552b2b",
                        foreground="#FFFFFF",
                        bordercolor="#404040",
                        lightcolor="#404040",
                        darkcolor="#404040",
                        padding=5)
        style.map("TButton",
                  background=[('active', '#5e2222'), ('pressed', '#606060')])

        # Создание стилей для кнопок с эффектом наведения
        style.configure("Hover.TButton", background="#505050")
        style.configure("Pressed.TButton", background="#606060")

    def setup_ui(self):
        self.root.title("Modern Chat")
        self.root.geometry("800x600")
        self.root.configure(bg="#2D2D2D")

        # Основные фреймы
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # Панель подключения
        connection_frame = ttk.Frame(main_frame)
        connection_frame.pack(fill=tk.X, pady=5)

        self.nick_entry = ttk.Entry(connection_frame, width=30)
        self.nick_entry.pack(side=tk.LEFT, padx=5)
        self.connect_btn = ttk.Button(connection_frame, text="Подключиться", command=self.connect, style="TButton")
        self.connect_btn.pack(side=tk.LEFT)

        # Основная область чата
        chat_frame = ttk.Frame(main_frame)
        chat_frame.pack(fill=tk.BOTH, expand=True)

        # История сообщений
        self.chat_history = tk.Text(chat_frame, wrap=tk.WORD, state=tk.DISABLED,
                                    bg="#1E1E1E", fg="#FFFFFF", insertbackground="#FFFFFF",
                                    padx=10, pady=10, font="Helvetica 11")
        scrollbar = ttk.Scrollbar(chat_frame, command=self.chat_history.yview)
        self.chat_history.configure(yscrollcommand=scrollbar.set)

        self.chat_history.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # Список пользователей
        user_list_frame = ttk.Frame(main_frame, width=150)
        user_list_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=5)

        self.user_list = tk.Listbox(user_list_frame, bg="#1E1E1E", fg="#FFFFFF",
                                    selectbackground="#552b2b", selectforeground="#FFFFFF",
                                    relief=tk.FLAT, font="Helvetica 10")
        self.user_list.pack(fill=tk.BOTH, expand=True)

        # Поле ввода сообщения
        input_frame = ttk.Frame(main_frame)
        input_frame.pack(fill=tk.X, pady=10)

        self.msg_entry = ttk.Entry(input_frame)
        self.msg_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.msg_entry.bind("<Return>", lambda event: self.send_message())
        self.send_btn = ttk.Button(input_frame, text="➤", width=3, command=self.send_message, style="TButton")
        self.send_btn.pack(side=tk.RIGHT)

        # Добавление эффектов наведения
        self.add_hover_effect(self.connect_btn)
        self.add_hover_effect(self.send_btn)

        self.connected = False

    def add_hover_effect(self, button):
        button.bind("<Enter>", lambda e: button.config(style="Hover.TButton"))
        button.bind("<Leave>", lambda e: button.config(style="TButton"))

    def setup_socket_events(self):
        self.sio.on('connect', lambda: self.add_message("Соединение установлено", system=True))
        self.sio.on('disconnect', lambda: self.add_message("Соединение разорвано", system=True))
        self.sio.on('registration_success', self.on_registration_success)
        self.sio.on('registration_failed', lambda: self.add_message("Ник занят!", system=True))
        self.sio.on('update_users', self.update_user_list)
        self.sio.on('message', self.handle_message)

    def connect(self):
        if not self.connected:
            nickname = self.nick_entry.get()
            if nickname:
                try:
                    self.sio.connect('http://localhost:5000')
                    self.sio.emit('register', nickname)
                except Exception as e:
                    self.add_message(f"Ошибка: {str(e)}", system=True)
        else:
            self.sio.disconnect()
            self.connected = False
            self.connect_btn.config(text="Подключиться")
            self.nick_entry.config(state=tk.NORMAL)

    def on_registration_success(self):
        self.connected = True
        self.connect_btn.config(text="Отключиться")
        self.nick_entry.config(state=tk.DISABLED)
        self.add_message("Вы успешно подключились!", system=True)

    def update_user_list(self, users):
        self.user_list.delete(0, tk.END)
        for user in users:
            self.user_list.insert(tk.END, user)

    def handle_message(self, data):
        is_own = data['sender'] == self.nick_entry.get()
        self.add_message(f"{data['message']}", sender=data['sender'], is_own=is_own)

    def send_message(self):
        if self.connected and self.msg_entry.get():
            receiver = self.get_selected_user() or 'all'
            self.sio.emit('message', {
                'to': receiver,
                'message': self.msg_entry.get(),
                'sender': self.nick_entry.get()
            })
            self.msg_entry.delete(0, tk.END)

    def get_selected_user(self):
        try:
            return self.user_list.get(self.user_list.curselection())
        except:
            return None

    def add_message(self, text, sender=None, system=False, is_own=False):
        self.chat_history.config(state=tk.NORMAL)
        timestamp = datetime.now().strftime("%H:%M")

        if system:
            self.chat_history.tag_config("system", foreground="#808080")
            self.chat_history.insert(tk.END, f"[{timestamp}] {text}\n", "system")
        else:
            tag_name = "own" if is_own else "other"
            self.chat_history.tag_config(tag_name, foreground="#569CD6" if is_own else "#D4D4D4")
            prefix = f"[{timestamp}] {sender}:\n" if sender else ""
            self.chat_history.insert(tk.END, f"{prefix}{text}\n\n", tag_name)

        self.chat_history.config(state=tk.DISABLED)
        self.chat_history.see(tk.END)


if __name__ == '__main__':
    root = tk.Tk()
    app = ModernChatApp(root)
    root.mainloop()

Как сделать поле для ввода сообщения потолще и поуже, чтобы немного увеличить кнопку отправки