import tkinter as tk
from tkinter import ttk, messagebox
import json
from typing import List, Dict, Any
import webbrowser

class ExpertSystem:
    def __init__(self, config_file: str):
        with open(config_file, 'r', encoding='utf-8') as f:
            config = json.load(f)
        self.questions_novice: List[str] = config['questions_novice']
        self.questions_expert: List[str] = config['questions_expert']
        self.initial_question: str = config['initial_question']
        self.rules: List[Dict[str, Any]] = config['rules']
        self.plant_descriptions: Dict[str, str] = config['plant_descriptions']
        self.plant_care_links: Dict[str, str] = config['plant_care_links']

    def get_recommendations(self, user_data: Dict[str, str]) -> List[str]:
        recommendations = []
        for rule in self.rules:
            if all(user_data.get(key) == value for key, value in rule['conditions'].items()):
                recommendations.extend(rule['recommendations'])
        return recommendations

class Application(tk.Tk):
    def __init__(self, expert_system: ExpertSystem):
        super().__init__()
        self.expert_system = expert_system
        self.title("Экспертная система для выбора комнатных растений")
        self.geometry("800x600")
        self.configure(bg="#f0f5f5")
        self.resizable(False, False)

        self.user_data: Dict[str, str] = {}
        self.current_question = 0
        self.is_novice: bool = None
        self.history: List[Dict[str, Any]] = []

        self.create_widgets()
        self.show_question()

    def create_widgets(self):
        # Стилизация
        self.style = ttk.Style()
        self.style.theme_use('clam')
        self.style.configure('TButton', font=('Helvetica', 12), padding=6)
        self.style.configure('TLabel', background='#f0f5f5')

        # Заголовок
        self.title_label = tk.Label(self, text="Добро пожаловать в экспертную систему по выбору комнатных растений!",
                                    font=("Helvetica", 16, "bold"), bg="#f0f5f5", fg="#2f4f4f", wraplength=750)
        self.title_label.pack(pady=20)

        # Создаем фрейм для вопросов
        self.question_frame = tk.Frame(self, bg="#f0f5f5")
        self.question_frame.pack()

        # Вопрос
        self.question_label = tk.Label(self.question_frame, text="", font=("Helvetica", 14),
                                       wraplength=750, justify="center", bg="#f0f5f5")
        self.question_label.pack(pady=10)

        # Прогресс-бар
        self.progress_bar = ttk.Progressbar(self.question_frame, orient="horizontal", length=500, mode="determinate")
        self.progress_bar.pack(pady=10)

        # Фрейм для ответов
        self.answer_frame = tk.Frame(self.question_frame, bg="#f0f5f5")
        self.answer_frame.pack(pady=20)

        # Фрейм для кнопок
        self.button_frame = tk.Frame(self.question_frame, bg="#f0f5f5")
        self.button_frame.pack(pady=10)

        self.back_button = ttk.Button(self.button_frame, text="⟵ Назад", command=self.go_back)
        self.back_button.pack(side="left", padx=10)

        # Фрейм результатов
        self.result_frame = tk.Frame(self, bg="#f0f5f5")
        # Пока не пакуем фрейм результатов

        self.result_label = tk.Label(self.result_frame, text="", font=("Helvetica", 14),
                                     wraplength=750, justify="left", bg="#f0f5f5")
        self.result_label.pack(pady=20)

        self.restart_button = ttk.Button(self.result_frame, text="Начать заново", command=self.restart)
        self.restart_button.pack(pady=5)

        self.save_button = ttk.Button(self.result_frame, text="Сохранить результаты", command=self.save_results)
        self.save_button.pack(pady=5)

        # Добавим фрейм для ссылок
        self.link_frame = tk.Frame(self.result_frame, bg="#f0f5f5")
        self.link_frame.pack(pady=10)

    def show_question(self):
        for widget in self.answer_frame.winfo_children():
            widget.destroy()

        total_questions = len(self.expert_system.questions_novice if self.is_novice else self.expert_system.questions_expert) + 1
        progress = (self.current_question / total_questions) * 100
        self.progress_bar["value"] = progress

        if self.current_question == 0:
            self.question_label.config(text=self.expert_system.initial_question)
            options = ["Новичок", "Опытный"]
        else:
            questions = self.expert_system.questions_novice if self.is_novice else self.expert_system.questions_expert
            if self.current_question - 1 < len(questions):
                self.question_label.config(text=questions[self.current_question - 1])
                if self.current_question - 1 == 0:
                    options = ["Минимум времени", "Нормально времени", "Много времени"] if self.is_novice else ["Из семян или черенков", "Готовое растение"]
                elif self.current_question - 1 == 1:
                    options = ["Тень/полутень", "Умеренное освещение", "Много света"] if self.is_novice else ["Маленькое", "Среднее", "Большое"]
                else:
                    options = ["Да", "Нет"]
            else:
                self.get_recommendation()
                return

        for option in options:
            button = ttk.Button(self.answer_frame, text=option, command=lambda opt=option: self.submit_answer(opt))
            button.pack(pady=5)

        self.back_button["state"] = "normal" if self.current_question > 0 else "disabled"

    def submit_answer(self, answer: str):
        if self.current_question == 0:
            self.user_data['Опыт'] = answer
            self.is_novice = (answer == "Новичок")
        elif self.is_novice:
            if self.current_question == 1:
                self.user_data['Время'] = answer
            elif self.current_question == 2:
                self.user_data['Освещенность'] = answer
        else:
            if self.current_question == 1:
                self.user_data['Способ выращивания'] = answer
            elif self.current_question == 2:
                self.user_data['Размер'] = answer
            elif self.current_question == 3:
                self.user_data['Экзотичность'] = answer

        self.history.append({"question": self.current_question, "answer": answer})
        self.current_question += 1
        self.show_question()

    def go_back(self):
        if self.current_question > 0:
            self.current_question -= 1
            last_answer = self.history.pop()
            key = list(self.user_data.keys())[-1]
            del self.user_data[key]
            self.show_question()

    def get_recommendation(self):
        recommendations = self.expert_system.get_recommendations(self.user_data)

        # Скрываем фрейм вопросов и показываем фрейм результатов
        self.question_frame.pack_forget()
        self.title_label.pack_forget()
        self.result_frame.pack()

        if recommendations:
            result_text = "Рекомендуемые растения:\n\n"
            for plant in recommendations:
                result_text += f"🌿 {plant}:\n{self.expert_system.plant_descriptions.get(plant, 'Описание отсутствует.')}\n\n"

            self.result_label.config(text=result_text)

            # Добавим кнопки ссылок
            for widget in self.link_frame.winfo_children():
                widget.destroy()

            for plant in recommendations:
                care_link = self.expert_system.plant_care_links.get(plant)
                if care_link:
                    link_button = ttk.Button(self.link_frame, text=f"Подробнее об уходе за {plant}",
                                             command=lambda url=care_link: webbrowser.open(url))
                    link_button.pack(pady=2)
        else:
            # Если нет рекомендаций
            self.result_label.config(text="К сожалению, по выбранным параметрам нет подходящих растений.")
            # Убираем кнопки ссылок, если они есть
            for widget in self.link_frame.winfo_children():
                widget.destroy()

    def restart(self):
        self.user_data.clear()
        self.current_question = 0
        self.is_novice = None
        self.history.clear()
        self.result_frame.pack_forget()
        self.title_label.pack(pady=20)
        self.question_frame.pack()
        self.show_question()

    def save_results(self):
        with open("results.txt", "w", encoding="utf-8") as f:
            f.write(self.result_label.cget("text"))
        messagebox.showinfo("Сохранение", "Результаты сохранены в файл results.txt")

if __name__ == "__main__":
    expert_system = ExpertSystem("config.json")
    app = Application(expert_system)
    app.mainloop()


{
  "questions_novice": [
    "Сколько времени готовы уделять уходу?",
    "Какой уровень освещенности в помещении?"
  ],
  "questions_expert": [
    "Предпочитаемый способ выращивания:",
    "Желаемый размер растения:",
    "Хотите ли вы экзотическое растение?"
  ],
  "initial_question": "Вы новичок или опытный цветовод?",
  "rules": [
    {
      "conditions": {
        "Опыт": "Новичок",
        "Время": "Минимум времени",
        "Освещенность": "Тень/полутень"
      },
      "recommendations": ["Замиокулькас", "Сансевиерия"]
    },
    {
      "conditions": {
        "Опыт": "Новичок",
        "Время": "Минимум времени",
        "Освещенность": "Умеренное освещение"
      },
      "recommendations": ["Спатифиллум", "Драцена"]
    },
    {
      "conditions": {
        "Опыт": "Новичок",
        "Время": "Нормально времени",
        "Освещенность": "Тень/полутень"
      },
      "recommendations": ["Филодендрон", "Диффенбахия"]
    },
    {
      "conditions": {
        "Опыт": "Новичок",
        "Время": "Нормально времени",
        "Освещенность": "Умеренное освещение"
      },
      "recommendations": ["Фикус", "Шеффлера"]
    },
    {
      "conditions": {
        "Опыт": "Новичок",
        "Время": "Много времени",
        "Освещенность": "Много света"
      },
      "recommendations": ["Гибискус", "Бугенвиллея"]
    },
    {
      "conditions": {
        "Опыт": "Опытный",
        "Способ выращивания": "Из семян или черенков",
        "Размер": "Маленькое",
        "Экзотичность": "Да"
      },
      "recommendations": ["Литопс", "Эхеверия"]
    },
    {
      "conditions": {
        "Опыт": "Опытный",
        "Способ выращивания": "Из семян или черенков",
        "Размер": "Среднее",
        "Экзотичность": "Да"
      },
      "recommendations": ["Кодиеум", "Кротон"]
    },
    {
      "conditions": {
        "Опыт": "Опытный",
        "Способ выращивания": "Готовое растение",
        "Размер": "Большое",
        "Экзотичность": "Да"
      },
      "recommendations": ["Монстера деликатесная", "Филодендрон гигантский"]
    }
  ],
  "plant_descriptions": {
    "Замиокулькас": "Неприхотливое растение с глянцевыми темно-зелеными листьями. Хорошо переносит засуху и низкую освещенность.",
    "Сансевиерия": "Известна как 'щучий хвост', отлично очищает воздух. Устойчива к засухе и различным условиям освещения.",
    "Спатифиллум": "Известен как 'женское счастье'. Имеет красивые темно-зеленые листья и белые соцветия.",
    "Драцена": "Растение с древовидным стволом и пучком листьев на верхушке. Бывает разных размеров.",
    "Филодендрон": "Вьющееся растение с красивыми сердцевидными листьями. Хорошо растет в тени.",
    "Диффенбахия": "Растение с крупными пестрыми листьями. Любит умеренную влажность и тепло.",
    "Фикус": "Разнообразное семейство растений, включающее виды разных размеров и форм.",
    "Шеффлера": "Растение с красивыми пальчатыми листьями. Хорошо очищает воздух.",
    "Гибискус": "Цветущий кустарник с крупными яркими цветами. Любит солнце и регулярный полив.",
    "Бугенвиллея": "Красивоцветущая лиана с яркими прицветниками. Любит много света и умеренный полив.",
    "Литопс": "Суккулент, напоминающий камешки. Требует минимального полива и яркого света.",
    "Эхеверия": "Суккулент с розетками сочных листьев. Любит яркий свет и редкий полив.",
    "Кодиеум": "Растение с яркими, пестрыми листьями. Требует яркого рассеянного света и регулярного полива.",
    "Кротон": "Декоративнолиственное растение с яркоокрашенными листьями. Любит яркий свет и влажность.",
    "Монстера деликатесная": "Крупное лиановидное растение с большими резными листьями. Любит яркий рассеянный свет и влажность.",
    "Филодендрон гигантский": "Крупное растение с огромными листьями. Требует пространства и высокой влажности."
  },
  "plant_care_links": {
    "Замиокулькас": "https://rastenievod.com/zamiokulkas.html",
    "Сансевиерия": "https://rastenievod.com/sansevieriya.html",
    "Спатифиллум": "https://rastenievod.com/spatifillum.html",
    "Драцена": "https://rastenievod.com/dratsena.html",
    "Филодендрон": "https://rastenievod.com/filodendron.html",
    "Диффенбахия": "https://rastenievod.com/diffenbahiya.html",
    "Фикус": "https://rastenievod.com/fikus.html",
    "Шеффлера": "https://rastenievod.com/shefflera.html",
    "Гибискус": "https://rastenievod.com/gibiskus.html",
    "Бугенвиллея": "https://rastenievod.com/bugenvilleya.html",
    "Литопс": "https://rastenievod.com/litops.html",
    "Эхеверия": "https://rastenievod.com/eheveriya.html",
    "Кодиеум": "https://rastenievod.com/kroton.html",
    "Кротон": "https://rastenievod.com/kroton.html",
    "Монстера деликатесная": "https://rastenievod.com/monstera.html",
    "Филодендрон гигантский": "https://rastenievod.com/filodendron.html"
  }
}




почему при некоторых комбинациях выборов  в конце пишется что нет подходящих растений нужно чтобы во всех комбинациях рекомендовались растения что логично