#!/usr/bin/python3
import os
import shutil
import sys
import tempfile
import zipfile

from PyQt6.QtGui import QIcon, QAction
from PyQt6.QtWidgets import QMainWindow, QApplication, QWidget, QTabWidget, QVBoxLayout, QStatusBar, QMenu, QFileDialog
from python3_mos_pyqt_dialogs.pyqt6_dialogs_functions import alert, question

from mos_attestat_print_modules.attestat_attachment import AttestatAttachment
from mos_attestat_print_modules.attestat_face import AttestatFace
from mos_attestat_print_modules.attestat_marks import AttestatMarks
from mos_attestat_print_modules.config import version, face_sizes_file, honour_face_sizes_file, \
    attachment_sizes_file, marks_sizes_file
from mos_attestat_print_modules.design import WindowForIssuingBook
from mos_attestat_print_modules.fis_frdo import create_fis_frdo_workbook
from mos_attestat_print_modules.settings_window import SettingsWindow
from mos_attestat_print_modules.system_functions import create_sizes_files


class App(QMainWindow):
    def __init__(self):
        super().__init__()
        create_sizes_files()
        self.initUI()

    def open_settings(self):
        self.settings_window = SettingsWindow()

    def save_template(self):
        """Сохранить все текущие настройки как шаблон в ZIP архив"""
        # Выбираем куда сохранить
        file_path, _ = QFileDialog.getSaveFileName(
            parent=self,
            caption='Сохранить шаблон габаритов',
            directory=os.path.join(os.path.expanduser('~'), 'Документы', 'template.zip'),
            filter='ZIP архивы (*.zip)'
        )
        if not file_path:
            return

        # Проверяем, не существует ли уже файл
        if os.path.exists(file_path):
            if not question(f'Файл "{os.path.basename(file_path)}" уже существует. Перезаписать?'):
                return

        try:
            # Создаём временную папку
            with tempfile.TemporaryDirectory() as tmpdir:
                # Сохраняем все файлы настроек во временную папку
                files_to_copy = [
                    (face_sizes_file, 'face_sizes.ini'),
                    (attachment_sizes_file, 'attachment_sizes.ini'),
                    (marks_sizes_file, 'marks_sizes.ini'),
                ]

                # Добавляем файл для аттестата с отличием, если он существует
                if os.path.exists(honour_face_sizes_file):
                    files_to_copy.append((honour_face_sizes_file, 'honour_face_sizes.ini'))

                for src, dst in files_to_copy:
                    if os.path.exists(src):
                        shutil.copy2(src, os.path.join(tmpdir, dst))

                # Создаём ZIP архив
                with zipfile.ZipFile(file_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                    for file in os.listdir(tmpdir):
                        file_path_full = os.path.join(tmpdir, file)
                        zipf.write(file_path_full, file)

            alert(f'Шаблон успешно сохранён в файл:\n{file_path}')

        except Exception as e:
            alert(f'Не удалось сохранить шаблон. Ошибка: {e}')

    def load_template(self):
        """Загрузить шаблон из ZIP архива и применить все настройки"""
        file_path, _ = QFileDialog.getOpenFileName(
            parent=self,
            caption='Выберите файл шаблона',
            directory=os.path.join(os.path.expanduser('~'), 'Документы'),
            filter='ZIP архивы (*.zip)'
        )
        if not file_path or not os.path.exists(file_path):
            return

        if not question('Загрузить шаблон? Текущие настройки всех габаритов будут перезаписаны.'):
            return

        try:
            # Распаковываем архив во временную папку
            with tempfile.TemporaryDirectory() as tmpdir:
                with zipfile.ZipFile(file_path, 'r') as zipf:
                    zipf.extractall(tmpdir)

                # Проверяем наличие необходимых файлов
                extracted_files = os.listdir(tmpdir)
                required_files = ['face_sizes.ini', 'attachment_sizes.ini', 'marks_sizes.ini']
                missing = [f for f in required_files if f not in extracted_files]

                if missing:
                    alert(f'Некорректный шаблон. Отсутствуют файлы:\n{", ".join(missing)}')
                    return

                # Применяем настройки - копируем файлы
                # face_sizes.ini
                src = os.path.join(tmpdir, 'face_sizes.ini')
                shutil.copy2(src, face_sizes_file)

                # attachment_sizes.ini
                src = os.path.join(tmpdir, 'attachment_sizes.ini')
                shutil.copy2(src, attachment_sizes_file)

                # marks_sizes.ini
                src = os.path.join(tmpdir, 'marks_sizes.ini')
                shutil.copy2(src, marks_sizes_file)

                # honour_face_sizes.ini, если есть в шаблоне
                if 'honour_face_sizes.ini' in extracted_files:
                    src = os.path.join(tmpdir, 'honour_face_sizes.ini')
                    shutil.copy2(src, honour_face_sizes_file)

            alert(f'Шаблон успешно загружен из файла:\n{file_path}\n\nВсе настройки обновлены.')

            # Обновляем значения в открытых вкладках
            self.update_all_tabs_settings()

        except Exception as e:
            alert(f'Не удалось загрузить шаблон. Ошибка: {e}')

    def update_all_tabs_settings(self):
        """Обновить настройки во всех открытых вкладках после загрузки шаблона"""
        if hasattr(self, 'tab_widget') and hasattr(self.tab_widget, 'tabs'):
            # Перебираем все вкладки
            for i in range(self.tab_widget.tabs.count()):
                widget = self.tab_widget.tabs.widget(i)
                if hasattr(widget, 'load_settings'):
                    widget.load_settings()
            # alert('Все вкладки обновлены согласно новым настройкам.')

    def generate_issue_book(self):
        self.window_for_issuing = WindowForIssuingBook()

    def initUI(self):
        self.title = f'МОС печать аттестатов {version}'
        self.setWindowTitle(self.title)
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage("Выберите действие")
        self.tab_widget = MyTabWidget(self, self.statusBar)
        self.setCentralWidget(self.tab_widget)
        self.setMinimumWidth(600)

        self.tab_widget.statusBar = self.statusBar

        menubar = self.menuBar()

        # Меню "Файл"
        file_menu = QMenu('Файл', self)

        settings_action = QAction("Настройки", self)
        settings_action.triggered.connect(self.open_settings)
        file_menu.addAction(settings_action)

        file_menu.addSeparator()

        # Действия для шаблонов
        save_template_action = QAction("Сохранить шаблон габаритов...", self)
        save_template_action.triggered.connect(self.save_template)
        file_menu.addAction(save_template_action)

        load_template_action = QAction("Загрузить шаблон габаритов...", self)
        load_template_action.triggered.connect(self.load_template)
        file_menu.addAction(load_template_action)

        file_menu.addSeparator()

        issue_book_action = QAction("Сформировать книгу выдачи", self)
        issue_book_action.triggered.connect(self.generate_issue_book)
        file_menu.addAction(issue_book_action)

        fis_frdo_action = QAction("Сформировать выгрузку в ФИС ФРДО", self)
        fis_frdo_action.triggered.connect(create_fis_frdo_workbook)
        file_menu.addAction(fis_frdo_action)

        file_menu.addSeparator()

        exit_action = QAction("Выход", self)
        exit_action.triggered.connect(lambda: self.close())
        file_menu.addAction(exit_action)

        menubar.addMenu(file_menu)

        self.setWindowIcon(QIcon.fromTheme('mos-attestat-print'))
        self.show()
        self.setMinimumHeight(self.height())


class MyTabWidget(QWidget):
    def __init__(self, parent, statusBar):
        super(QWidget, self).__init__(parent)
        # Имя текущего файла общее для всех трёх вкладок
        self.excel_file_with_students = None
        self.students = None
        self.statusBar = statusBar
        self.initUI()

    def update_students_index_on_all_tabs(self):
        for tab in (
                self.tab1, self.tab2, self.tab3
        ):
            tab.switch_current_student()

    def initUI(self):
        self.layout = QVBoxLayout(self)
        self.tabs = QTabWidget()
        self.tab1 = AttestatFace(self.statusBar)
        # для изменения общих параметров, таких как имя файла с оценками
        self.tab1.parent = self
        self.tab2 = AttestatAttachment(self.statusBar)
        self.tab2.parent = self
        self.tab3 = AttestatMarks(self.statusBar)
        self.tab3.parent = self
        self.tabs.resize(300, 200)
        self.tabs.currentChanged.connect(lambda: self.statusBar.showMessage('Выберите действие'))
        self.tabs.currentChanged.connect(self.update_students_index_on_all_tabs)

        # Add tabs
        self.tabs.addTab(self.tab1, "Основной аттестат")
        self.tabs.addTab(self.tab2, "Приложение - информация")
        self.tabs.addTab(self.tab3, "Приложение - оценки")
        self.layout.addWidget(self.tabs)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setDesktopFileName('mos-attestat-print')
    ex = App()
    sys.exit(app.exec())
