import sys
import requests
import re
import os
import json
from PyQt6.QtWidgets import (
    QApplication, QWidget, QLabel, QLineEdit, QPushButton, QCheckBox,
    QListWidget, QVBoxLayout, QHBoxLayout, QSystemTrayIcon, QMenu, QMessageBox,
    QMenuBar, QRadioButton, QButtonGroup, QDialog, QSpacerItem, QSizePolicy
)
from PyQt6.QtGui import QIcon, QAction, QDesktopServices, QCursor
from PyQt6.QtCore import Qt, QUrl, QTimer

PROXY_FILE = 'D:\\ip_info\\settings\\proxies.json'
SETTINGS_FILE = 'D:\\ip_info\\settings\\settings.json'
ICON_PATH = 'D:\\ip_info\\icons\\app_ip.ico'

# Единый стиль для всех кнопок
BUTTON_STYLE = """
    QPushButton {
        border: none;
        background-color: #4CAF50;  /* Цвет кнопки */
        color: white;  /* Цвет текста */
        padding: 10px 20px;
        border-radius: 5px;  /* Закругленные углы */
    }
    QPushButton:hover {
        background-color: #45a049;  /* Цвет кнопки при наведении */
    }
"""

def get_ip_and_isp(proxy_data=None, use_proxy=False, service_url='https://ipinfo.io/json'):
    try:
        proxies = None
        if use_proxy and proxy_data:
            protocol = proxy_data.get('protocol', 'socks5')
            server_port = proxy_data['server_port']
            username = proxy_data.get('username')
            password = proxy_data.get('password')
            proxy_url = f"{protocol}://{server_port}"
            if username and password:
                proxy_url = f"{protocol}://{username}:{password}@{server_port}"
            proxies = {
                'http': proxy_url,
                'https': proxy_url,
            }
        response = requests.get(service_url, proxies=proxies, timeout=10)
        data = response.json()
        ip = data.get('ip', 'N/A')
        org = data.get('org', 'N/A')
        city = data.get('city', 'N/A')
        country = data.get('country', 'N/A')

        # Извлечение имени провайдера без AS-номера
        if org.startswith('AS'):
            isp = ' '.join(org.split(' ')[1:])
        else:
            isp = org

        # Удаление юридических форм (с учётом регистра и возможных кавычек)
        legal_forms = ['PJSC', 'LLC', 'JSC', 'OJSC', 'АО', 'ОАО', 'ЗАО', 'ООО', 'ПАО']
        pattern = r'\b(' + '|'.join(legal_forms) + r')\b'
        isp = re.sub(pattern, '', isp, flags=re.IGNORECASE).strip()

        # Удаление лишних символов, таких как кавычки или специальные символы
        isp = isp.replace('"', '').replace('«', '').replace('»', '').strip()

        # Удаление лишних пробелов
        isp = ' '.join(isp.split())

        return ip, isp, city, country
    except Exception as e:
        return 'Ошибка', 'Ошибка', 'Ошибка', 'Ошибка'

class AboutDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('О программе')
        self.setFixedSize(400, 200)
        self.setWindowIcon(parent.icon if parent and hasattr(parent, 'icon') else QIcon())

        layout = QVBoxLayout()

        # Заголовок
        title_label = QLabel("JustWoofIP")
        title_font = title_label.font()
        title_font.setPointSize(14)
        title_font.setBold(True)
        title_label.setFont(title_font)
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(title_label)

        # Версия
        version_label = QLabel("Версия: 1.0.0-20241101")
        version_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(version_label)

        # Сайт со ссылкой
        site_label = QLabel()
        site_label.setText(
            'Сайт: <a href="https://chat.mistral.ai" style="color: #1E90FF; font-weight: bold; text-decoration: none;">https://chat.mistral.ai</a>'
        )
        site_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        site_label.setOpenExternalLinks(False)  # Отключаем автоматическое открытие ссылок
        site_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextBrowserInteraction)
        site_label.linkActivated.connect(self.open_link)
        site_label.setStyleSheet("""
            QLabel {
                color: white;
                background-color: #1e1e1e;
            }
            a:hover {
                text-decoration: underline;
            }
        """)

        layout.addWidget(site_label)

        # Spacer для отступа
        spacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
        layout.addItem(spacer)

        # Кнопка закрытия
        close_button = QPushButton("Закрыть")
        close_button.clicked.connect(self.close)
        close_button.setStyleSheet(BUTTON_STYLE)
        close_button.setFixedWidth(100)
        close_button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        layout.addWidget(close_button, alignment=Qt.AlignmentFlag.AlignCenter)

        self.setLayout(layout)
        self.setStyleSheet("background-color: #1e1e1e; color: white;")

    def open_link(self, link):
        QDesktopServices.openUrl(QUrl(link))
        self.close()

class MyApp(QWidget):
    def __init__(self):
        super().__init__()

        self.minimize_to_tray = False  # Инициализация по умолчанию

        self.initUI()

    def initUI(self):
        self.setWindowTitle('JustWoofIP')
        self.setStyleSheet("background-color: #1e1e1e; color: white;")

        # Установка иконки
        if os.path.exists(ICON_PATH):
            self.icon = QIcon(ICON_PATH)
            self.setWindowIcon(self.icon)
        else:
            self.icon = QIcon()

        layout = QVBoxLayout()

        # Поле для IP с кнопкой "Копировать"
        hbox_ip = QHBoxLayout()
        ip_label = QLabel("Мой IP:")
        self.ip_text = QLineEdit()
        self.ip_text.setReadOnly(True)
        self.ip_text.setStyleSheet("background-color: #323232; color: white;")
        hbox_ip.addWidget(ip_label)
        hbox_ip.addWidget(self.ip_text)

        # Кнопка "Копировать" рядом с IP
        self.copy_ip_button = QPushButton("Копировать")
        self.copy_ip_button.clicked.connect(self.copy_ip)
        self.copy_ip_button.setStyleSheet(BUTTON_STYLE)
        self.copy_ip_button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        hbox_ip.addWidget(self.copy_ip_button)
        layout.addLayout(hbox_ip)

        # Поле для ISP, города и страны
        hbox_isp = QHBoxLayout()
        isp_label = QLabel("Мой ISP:")
        self.isp_text = QLineEdit()
        self.isp_text.setReadOnly(True)
        self.isp_text.setStyleSheet("background-color: #323232; color: white;")
        hbox_isp.addWidget(isp_label)
        hbox_isp.addWidget(self.isp_text)

        # Поле для города
        city_label = QLabel("Город:")
        self.city_text = QLineEdit()
        self.city_text.setReadOnly(True)
        self.city_text.setStyleSheet("background-color: #323232; color: white;")
        hbox_isp.addWidget(city_label)
        hbox_isp.addWidget(self.city_text)

        # Поле для страны
        country_label = QLabel("Страна:")
        self.country_text = QLineEdit()
        self.country_text.setReadOnly(True)
        self.country_text.setStyleSheet("background-color: #323232; color: white;")
        hbox_isp.addWidget(country_label)
        hbox_isp.addWidget(self.country_text)

        layout.addLayout(hbox_isp)

        # Флажок "Использовать прокси"
        self.use_proxy_checkbox = QCheckBox("Использовать прокси")
        self.use_proxy_checkbox.setChecked(False)  # По умолчанию прокси не используется
        layout.addWidget(self.use_proxy_checkbox)

        # Выбор сохранённого прокси
        hbox3 = QHBoxLayout()
        saved_proxy_label = QLabel("Сохранённые прокси:")
        self.saved_proxy_choice = QListWidget()
        self.saved_proxy_choice.setStyleSheet("background-color: #323232; color: white;")
        hbox3.addWidget(saved_proxy_label)
        hbox3.addWidget(self.saved_proxy_choice)
        layout.addLayout(hbox3)

        # Кнопки управления сохранёнными прокси (удалить и сохранить)
        hbox3_buttons = QHBoxLayout()
        
        # Кнопка "Удалить выбранный прокси"
        self.delete_proxy_button = QPushButton("Удалить выбранный прокси")
        self.delete_proxy_button.setStyleSheet(BUTTON_STYLE)
        self.delete_proxy_button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.delete_proxy_button.clicked.connect(self.on_delete_proxy)
        
        # Кнопка "Сохранить прокси"
        self.add_proxy_button = QPushButton("Сохранить прокси")
        self.add_proxy_button.setStyleSheet(BUTTON_STYLE)
        self.add_proxy_button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.add_proxy_button.clicked.connect(self.on_add_proxy)
        
        # Добавляем кнопки в горизонтальный layout с растягивающимися пробелами
        hbox3_buttons.addStretch()
        hbox3_buttons.addWidget(self.delete_proxy_button)
        hbox3_buttons.addWidget(self.add_proxy_button)
        hbox3_buttons.addStretch()
        layout.addLayout(hbox3_buttons)

        # Поле для ввода нового прокси
        hbox4 = QHBoxLayout()
        new_proxy_label = QLabel("Добавить прокси:")
        self.new_proxy_text = QLineEdit()
        self.new_proxy_text.setStyleSheet("background-color: #323232; color: white;")
        hbox4.addWidget(new_proxy_label)
        hbox4.addWidget(self.new_proxy_text)
        layout.addLayout(hbox4)

        # Переключатель для выбора сервиса
        hbox5 = QHBoxLayout()
        service_label = QLabel("Выбор сервиса:")
        self.service_group = QButtonGroup()
        self.ipinfo_radio = QRadioButton("ipinfo.io")
        self.ipapi_radio = QRadioButton("ipapi.co")
        self.service_group.addButton(self.ipinfo_radio)
        self.service_group.addButton(self.ipapi_radio)
        self.ipinfo_radio.setChecked(True)  # По умолчанию выбран ipinfo.io
        hbox5.addWidget(service_label)
        hbox5.addWidget(self.ipinfo_radio)
        hbox5.addWidget(self.ipapi_radio)
        layout.addLayout(hbox5)

        # Кнопка "Получить IP и ISP"
        self.get_button = QPushButton("Получить IP и ISP")
        self.get_button.setStyleSheet(BUTTON_STYLE)
        self.get_button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
        self.get_button.clicked.connect(self.on_get_button)
        
        # Центрируем кнопку "Получить IP и ISP"
        hbox_get = QHBoxLayout()
        hbox_get.addStretch()
        hbox_get.addWidget(self.get_button)
        hbox_get.addStretch()
        layout.addLayout(hbox_get)

        # Всплывающая подсказка (нотафикация)
        self.notification_label = QLabel("", self)
        self.notification_label.setStyleSheet("""
            QLabel {
                background-color: rgba(50, 50, 50, 200);
                color: white;
                padding: 5px 10px;
                border-radius: 5px;
                font-weight: bold;
            }
        """)
        self.notification_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.notification_label.hide()

        self.setLayout(layout)

        # Загрузка сохранённых прокси и настроек
        self.load_saved_proxies()
        self.load_settings()

        # Создание TaskBarIcon
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(self.icon)
        self.tray_icon.setToolTip('JustWoofIP')
        self.tray_icon.activated.connect(self.on_tray_icon_activated)
        self.create_tray_menu()
        self.tray_icon.show()

        # Создание меню "Файл", "Настройки" и "Справка"
        self.create_menu()

    def create_menu(self):
        menubar = QMenuBar(self)

        # Меню "Файл"
        file_menu = menubar.addMenu('Файл')
        exit_action = QAction('Выход', self)
        exit_action.triggered.connect(self.on_menu_exit)
        file_menu.addAction(exit_action)

        # Меню "Настройки"
        settings_menu = menubar.addMenu('Настройки')
        minimize_to_tray_action = QAction('Сворачивать в трей при закрытии', self, checkable=True)
        minimize_to_tray_action.setChecked(self.minimize_to_tray)
        minimize_to_tray_action.triggered.connect(self.on_minimize_to_tray_toggled)
        settings_menu.addAction(minimize_to_tray_action)

        # Меню "Справка"
        help_menu = menubar.addMenu('Справка')
        about_action = QAction('О программе', self)
        about_action.triggered.connect(self.show_about_dialog)
        help_menu.addAction(about_action)

        # Установка стилей для меню
        menubar.setStyleSheet("""
            QMenuBar {
                background-color: #323232;
                color: white;
            }
            QMenuBar::item:selected {
                background-color: #464646;
            }
            QMenu {
                background-color: #323232;
                color: white;
            }
            QMenu::item:selected {
                background-color: #464646;
            }
            QMenu::item:pressed {
                background-color: #5a5a5a;
            }
        """)

        layout = self.layout()
        layout.setMenuBar(menubar)

        # Замечание: Теперь используется кастомный AboutDialog вместо QMessageBox

    def create_tray_menu(self):
        menu = QMenu()
        show_action = QAction("Показать", self)
        exit_action = QAction("Выход", self)
        show_action.triggered.connect(self.on_tray_show)
        exit_action.triggered.connect(self.on_tray_exit)
        menu.addAction(show_action)
        menu.addAction(exit_action)
        self.tray_icon.setContextMenu(menu)

    def on_tray_icon_activated(self, reason):
        if reason == QSystemTrayIcon.ActivationReason.Trigger:
            self.on_tray_show()

    def on_tray_show(self):
        self.showNormal()
        self.activateWindow()

    def on_tray_exit(self):
        self.tray_icon.hide()
        self.close()

    def on_menu_exit(self):
        self.tray_icon.hide()
        self.close()

    def on_minimize_to_tray_toggled(self, checked):
        self.minimize_to_tray = checked

    def closeEvent(self, event):
        self.save_settings()
        if self.minimize_to_tray:
            self.hide()
            event.ignore()
        else:
            self.tray_icon.hide()
            event.accept()

    def load_saved_proxies(self):
        self.saved_proxies = []
        if os.path.exists(PROXY_FILE):
            with open(PROXY_FILE, 'r', encoding='utf-8') as f:
                self.saved_proxies = json.load(f)
                self.update_saved_proxy_list()

    def save_proxies(self):
        os.makedirs(os.path.dirname(PROXY_FILE), exist_ok=True)  # Убедиться, что папка существует
        with open(PROXY_FILE, 'w', encoding='utf-8') as f:
            json.dump(self.saved_proxies, f, ensure_ascii=False, indent=4)

    def update_saved_proxy_list(self):
        self.saved_proxy_choice.clear()
        for proxy in self.saved_proxies:
            display_text = f"{proxy['protocol']}://{proxy['server_port']}"
            if proxy.get('username') and proxy.get('password'):
                display_text += f" ({proxy['username']}:{proxy['password']})"
            self.saved_proxy_choice.addItem(display_text)

    def load_settings(self):
        if os.path.exists(SETTINGS_FILE):
            with open(SETTINGS_FILE, 'r', encoding='utf-8') as f:
                settings = json.load(f)
                use_proxy = settings.get('use_proxy', False)
                minimize_to_tray = settings.get('minimize_to_tray', False)
                selected_proxy_index = settings.get('selected_proxy_index', -1)
                selected_service = settings.get('selected_service', 'ipinfo.io')

                self.use_proxy_checkbox.setChecked(use_proxy)
                self.minimize_to_tray = minimize_to_tray
                if 0 <= selected_proxy_index < len(self.saved_proxies):
                    self.saved_proxy_choice.setCurrentRow(selected_proxy_index)
                if selected_service == 'ipinfo.io':
                    self.ipinfo_radio.setChecked(True)
                else:
                    self.ipapi_radio.setChecked(True)
        else:
            # Если файл настроек не существует, устанавливаем значения по умолчанию
            self.use_proxy_checkbox.setChecked(False)
            self.minimize_to_tray = False
            self.ipinfo_radio.setChecked(True)

    def save_settings(self):
        settings = {
            'use_proxy': self.use_proxy_checkbox.isChecked(),
            'minimize_to_tray': self.minimize_to_tray,
            'selected_proxy_index': self.saved_proxy_choice.currentRow(),
            'selected_service': 'ipinfo.io' if self.ipinfo_radio.isChecked() else 'ipapi.co'
        }
        os.makedirs(os.path.dirname(SETTINGS_FILE), exist_ok=True)  # Убедиться, что папка существует
        with open(SETTINGS_FILE, 'w', encoding='utf-8') as f:
            json.dump(settings, f, ensure_ascii=False, indent=4)

    def on_get_button(self):
        use_proxy = self.use_proxy_checkbox.isChecked()
        service_url = 'https://ipinfo.io/json' if self.ipinfo_radio.isChecked() else 'https://ipapi.co/json/'

        proxy_data = None
        if use_proxy:
            selected_index = self.saved_proxy_choice.currentRow()
            if selected_index != -1 and selected_index < len(self.saved_proxies):
                # Пользователь выбрал прокси вручную
                proxy_data = self.saved_proxies[selected_index]
            elif len(self.saved_proxies) > 0:
                # Пользователь не выбрал прокси вручную, применяем первый
                proxy_data = self.saved_proxies[0]

        ip, isp, city, country = get_ip_and_isp(proxy_data, use_proxy, service_url)
        self.ip_text.setText(ip)
        self.isp_text.setText(isp)
        self.city_text.setText(city)
        self.country_text.setText(country)

    def on_add_proxy(self):
        proxy_input = self.new_proxy_text.text().strip()
        if proxy_input:
            # Ожидаемый формат: protocol://server:port (username:password)
            parts = proxy_input.split()
            if len(parts) == 1 or len(parts) == 2:
                proxy_url = parts[0]
                auth = parts[1] if len(parts) == 2 else ''
                if '://' in proxy_url:
                    try:
                        protocol, server_port = proxy_url.split('://', 1)
                    except ValueError:
                        self.show_notification("Некорректный формат прокси", duration=1000)
                        return
                else:
                    protocol = 'socks5'  # По умолчанию
                    server_port = proxy_url

                proxy_data = {'protocol': protocol, 'server_port': server_port}
                if auth:
                    if ':' in auth:
                        username, password = auth.split(':', 1)
                        proxy_data['username'] = username
                        proxy_data['password'] = password
                    else:
                        proxy_data['username'] = auth
                        proxy_data['password'] = ''

                # Добавляем прокси в список и сохраняем
                self.saved_proxies.append(proxy_data)
                self.save_proxies()
                self.update_saved_proxy_list()
                self.new_proxy_text.clear()
                self.show_notification("Прокси сохранен", duration=1000)
            else:
                self.show_notification("Некорректный формат ввода прокси", duration=1000)
        else:
            self.show_notification("Поле для ввода прокси пустое", duration=1000)

    def on_delete_proxy(self):
        selected_index = self.saved_proxy_choice.currentRow()
        if selected_index != -1:
            del self.saved_proxies[selected_index]
            self.save_proxies()
            self.update_saved_proxy_list()
            self.show_notification("Прокси удален", duration=1000)
        else:
            self.show_notification("Не выбран прокси для удаления", duration=1000)

    def copy_ip(self):
        ip = self.ip_text.text().strip()
        if ip and ip != 'N/A' and ip != 'Ошибка':
            clipboard = QApplication.clipboard()
            clipboard.setText(ip)
            self.show_notification("IP-адрес скопирован", duration=1000)
        else:
            self.show_notification("Нечего копировать", duration=1000)

    def show_notification(self, message, duration=1000):
        self.notification_label.setText(message)
        self.notification_label.adjustSize()
        self.notification_label.setFixedHeight(30)
        # Центрируем подсказку в окне
        self.notification_label.move(
            (self.width() - self.notification_label.width()) // 2,
            self.height() - self.notification_label.height() - 10
        )
        self.notification_label.show()

        # Создаем таймер для скрытия подсказки
        QTimer.singleShot(duration, self.notification_label.hide)

    def show_about_dialog(self):
        dialog = AboutDialog(self)
        dialog.exec()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApp()
    ex.show()
    sys.exit(app.exec())

1. Поменять местами кнопки - "Удалить выбранный прокси" и "Сохранить прокси".
2.  Удалить текст "Сохранённые прокси:".
3. Растянуть поле списка прокси по ширине всего приложения.
4. Перемести всплывающее сообщение, появляющееся при нажатии на кнопку "Копировать" в один ряд с текстом "Использовать прокси" - использовать пустое пространство после этого текста, выводить на нём всплывающие сообщения; отцентровать появление всплывающих сообщений по пустому месту этого ряда.
5. Добавить сервис для проверки IP ip-api.com - https://ip-api.com/; сделать для него аналогичную радиокнопку.