Загрузка данных


# -*- coding: utf-8 -*-
# Файл: modules/project_list.py
import os
import tkinter as tk
from tkinter import Toplevel, messagebox, ttk

from modules.database_module import Session, get_all_indicators_by_group, list_groups


class ProjectListWindow:
    """
    Окно для выбора проекта, группы и показателя.
    Не содержит логики работы с событиями.
    """

    def __init__(self, manager, root_window=None):
        self.manager = manager
        self.root_window = root_window
        self.window = Toplevel(root_window)
        self.window.title("Выбор параметров проекта")
        self.window.geometry("500x250")
        self.window.resizable(False, False)

        self.session = Session()
        self.group_names_to_codes = {}
        self.name_to_code_map = {}

        self._create_widgets()
        self.update_project_list()

        # Если проекты есть, загружаем данные для первого из них
        if self.project_combobox["values"]:
            self.project_combobox.current(0)
            self._load_data()

    def _create_widgets(self):
        main_frame = tk.Frame(self.window)
        main_frame.pack(padx=10, pady=10, fill="both", expand=True)

        # Выбор проекта
        tk.Label(main_frame, text="Проект:").pack(anchor="w", pady=(0, 2))
        self.project_combobox = ttk.Combobox(main_frame, state="readonly")
        self.project_combobox.pack(fill="x", padx=15, pady=5)
        self.project_combobox.bind("<<ComboboxSelected>>", self._load_data)

        # Выбор Группы
        tk.Label(main_frame, text="Группа:").pack(anchor="w")
        self.group_combobox = ttk.Combobox(main_frame, state="readonly")
        self.group_combobox.bind("<<ComboboxSelected>>", self.update_indicators_list)
        self.group_combobox.pack(fill="x", padx=15, pady=5)

        # Выбор Показателя
        tk.Label(main_frame, text="Показатель:").pack(anchor="w")
        self.indicator_combobox = ttk.Combobox(main_frame, state="readonly")
        self.indicator_combobox.pack(fill="x", padx=15, pady=5)

    def update_project_list(self):
        """Обновляет список проектов."""
        projects = self.manager.list_projects()

        try:
            display_names = []
            self.name_to_code_map = {}

            for p in projects:
                display_names.append(p.name)
                self.name_to_code_map[p.name] = p.id

            self.project_combobox["values"] = display_names

            if display_names:
                self.project_combobox.set(display_names[0])
                self.window.after(0, self._load_data)

            return bool(display_names)

        except Exception as e:
            print(f"Ошибка загрузки проектов: {e}")
            return False

    def _on_project_select(self, event):
        """
        Этот метод вызывается, когда пользователь выбирает элемент в Combobox.
        Он нужен, чтобы принудительно перерисовать текст в поле.
        """
        # Получаем выбранный объект Project
        selected_object = self.project_combobox.get()

        # Если выбранный объект существует и у него есть атрибут 'name'
        if hasattr(selected_object, "name"):
            self.project_combobox.set(selected_object.name)

        try:
            # Создаем карту "Имя -> Объект Project" для быстрого доступа
            self.project_objects_map = {}
            project_objects = []

            for p in projects:
                # Ключ - имя, значение - объект
                self.project_objects_map[p.name] = p
                project_objects.append(p)

            self.project_combobox.bind("<<ComboboxSelected>>", self._on_project_select)

            # Если список не пуст, выбираем первый элемент
            if project_objects:
                self.project_combobox.set(project_objects[0])
                self._load_data()

            return bool(project_objects)
        except Exception as e:
            print(f"Ошибка загрузки проектов: {e}")
            return False

    def _load_data(self, event=None):
        """Загружает данные (группы и показатели)."""
        # Получаем выбранное ИМЯ из списка
        selected_human_name = self.project_combobox.get()

        if not selected_human_name:
            # Очистка списков, если ничего не выбрано
            self.group_combobox.set("")
            self.indicator_combobox.set("")
            self.group_combobox["values"] = []
            self.indicator_combobox["values"] = []
            self.group_names_to_codes.clear()
            return

        # print(
        # f"[ДИАГНОСТИКА] Пользователь выбрал проект: '{selected_human_name}'. Загружаем данные..."
        # )

        try:
            # --- 1. ИЩЕМ КОД ПО ИМЕНИ ---
            # Используем карту, которую мы создали в update_project_list
            project_code = self.name_to_code_map.get(selected_human_name)

            if not project_code:
                print(
                    f"[ОШИБКА] Код для имени '{selected_human_name}' не найден в карте."
                )
                return

            # print(f"[ДИАГНОСТИКА] Данные для кода: {project_code}")

            # --- 2. ЛОГИКА ЗАГРУЗКИ ГРУПП И ПОКАЗАТЕЛЕЙ ---
            groups = list_groups(session=self.session)
            if groups:
                group_names = [group.name for group in groups]
                self.group_combobox["values"] = group_names

                if group_names:
                    first_group_name = group_names[0]
                    self.group_combobox.set(first_group_name)
                    self.group_names_to_codes.clear()
                    for group in groups:
                        self.group_names_to_codes[group.name] = group.code

                    first_group_code = self.group_names_to_codes[first_group_name]
                    indicators = get_all_indicators_by_group(
                        first_group_code, session=self.session
                    )
                    if indicators:
                        indicator_names = [i.name for i in indicators]
                        self.indicator_combobox["values"] = indicator_names
                        if indicator_names:
                            self.indicator_combobox.set(indicator_names[0])

        except Exception as e:
            print(f"[ОШИБКА] Не удалось загрузить данные: {e}")

    def update_indicators_list(self, event=None):
        """Обновляет список показателей при выборе новой группы."""
        selected_group_name = self.group_combobox.get()

        if (
            not selected_group_name
            or selected_group_name not in self.group_names_to_codes
        ):
            self.indicator_combobox.set("")
            self.indicator_combobox["values"] = []
            return

        try:
            selected_group_code = self.group_names_to_codes.get(selected_group_name)
            if selected_group_code:
                indicators = get_all_indicators_by_group(
                    selected_group_code, session=self.session
                )
                if indicators and len(indicators) > 0:
                    indicator_names = [i.name for i in indicators]
                    self.indicator_combobox["values"] = indicator_names
                    # Устанавливаем первый показатель по умолчанию
                    if indicator_names and (
                        not self.indicator_combobox.get()
                        or self.indicator_combobox.get() not in indicator_names
                    ):
                        self.indicator_combobox.set(indicator_names[0])
                else:
                    self.indicator_combobox["values"] = []
                    self.indicator_combobox.set("")

        except Exception as e:
            print(f"[ОШИБКА] Не удалось загрузить показатели: {e}")

    def get_selected_data(self):
        """
        Возвращает словарь с выбранными данными.
        Теперь гарантированно возвращает 'indicator_code'.
        """
        # Получаем выбранные имена из интерфейса
        project_display_name = self.project_combobox.get()
        group_name = self.group_combobox.get()
        indicator_name = self.indicator_combobox.get()

        # Получаем коды для проекта и группы из наших карт
        project_code = self.name_to_code_map.get(project_display_name)
        group_code = self.group_names_to_codes.get(group_name)

        # --- НОВАЯ ЛОГИКА: Поиск КОДА показателя ---
        indicator_code = None

        # 1. Проверяем, что мы смогли получить код группы.
        if group_code:
            # 2. Запрашиваем список ВСЕХ показателей для этой группы из БД.
            # Используем уже существующий метод, который работает с SQLAlchemy
            indicators = get_all_indicators_by_group(group_code, session=self.session)

            # 3. Ищем в этом списке тот показатель, имя которого совпадает с
            # выбранным в combobox.
            if indicators:
                for indicator in indicators:
                    # Сравниваем имя из базы с именем, которое выбрал
                    # пользователь
                    if indicator.name == indicator_name:
                        # Нашли совпадение! Берем КОД из объекта.
                        indicator_code = indicator.code
                        break  # Выходим из цикла, так как нашли нужное.

        # --- ВОЗВРАЩАЕМ РЕЗУЛЬТАТ ---
        return {
            "project_name": project_display_name,
            "project_code": project_code,
            "group_name": group_name,
            "group_code": group_code,
            "indicator_name": indicator_name,
            "indicator_code": indicator_code,  # <-- Теперь этот ключ будет в словаре!
        }