import tkinter as tk
from tkinter import messagebox, scrolledtext, simpledialog
import random
import json
import os
import time
import hashlib
from datetime import datetime

# ==============================
# ПОПЫТКА ИМПОРТА ДОП. БИБЛИОТЕК
# ==============================
try:
    import pyttsx3
    TTS_AVAILABLE = True
except ImportError:
    TTS_AVAILABLE = False

try:
    import pygame
    SOUND_ENABLED = True
except ImportError:
    SOUND_ENABLED = False

# ==============================
# ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
# ==============================
player_name = "Неизвестный"
level = 1
score = 0
play_style = {"hacker": 0, "analyst": 0, "creative": 0}
current_case = {}
SAVE_FILE = "detective_dossier.json"

# ==============================
# ИИ-АССИСТЕНТ "НОРМА"
# ==============================
class NORMA:
    def __init__(self):
        self.engine = None
        if TTS_AVAILABLE:
            try:
                self.engine = pyttsx3.init()
                self.engine.setProperty('rate', 180)
                self.engine.setProperty('volume', 0.9)
            except:
                pass

def speak(self, text):
    print(f"🗣️ НОРМА: {text}")      
    if self.engine:
        self.engine.say(text)
    self.engine.runAndWait()

    def analyze_and_help(self, level, attempts):
        hints = {
            1: [
                "Проверь IP-адреса. Они не могут быть больше 255.",
                "Строка с '999' — явно подделка."
            ],
            2: [
                "Шифр Цезаря — это сдвиг букв. Попробуй 'Hello World'.",
                "Знаменитая фраза всех программистов..."
            ],
            3: [
                "Год в названии конкурса — 2026.",
                "JETCODE + год = пароль."
            ],
            4: [
                "Все скобки должны быть закрыты.",
                "print() требует закрывающей скобки."
            ],
            5: [
                "Если x=5, условие x>10 — ложно.",
                "Функция вернёт вторую строку."
            ]
        }
        idx = min(attempts - 1, len(hints[level]) - 1)
        hint = hints[level][idx]
        self.speak(hint)
        return hint

norma = NORMA()

# ==============================
# СОХРАНЕНИЕ / ЗАГРУЗКА
# ==============================
def save_game():
    data = {
        "player_name": player_name,
        "level": level,
        "score": score,
        "play_style": play_style,
        "timestamp": datetime.now().isoformat()
    }
    with open(SAVE_FILE, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)

def load_game():
    global player_name, level, score, play_style    
    if os.path.exists(SAVE_FILE):
        try:
            with open(SAVE_FILE, 'r', encoding='utf-8') as f:
                data = json.load(f)
                player_name = data.get("player_name", "Неизвестный")
                level = data.get("level", 1)
                score = data.get("score", 0)
                play_style = data.get("play_style", {"hacker": 0, "analyst": 0, "creative": 0})
        except:
            pass

# ==============================
# ХАКЕРСКИЙ ТЕРМИНАЛ (анимация)
# ==============================
def simulate_typing(widget, text, delay=50):
    widget.config(state="normal")
    widget.delete(1.0, tk.END)
    widget.insert(tk.END, "> ")
    widget.config(state="disabled")
    
    def type_char(i=0):
        if i < len(text):
            widget.config(state="normal")
            widget.insert(tk.END, text[i])
            widget.config(state="disabled")
            widget.see(tk.END)
            widget.after(delay, type_char, i+1)
    type_char()

# ==============================
# ГЕНЕРАЦИЯ УНИКАЛЬНЫХ ЗАДАНИЙ
# ==============================
def generate_level_1():
    fake_ip = f"192.168.0.{random.randint(256, 999)}"
    logs = [
        "[INFO] User login: alice",
        "[INFO] Server started",
        "[WARNING] Low disk space",
        f"[ALERT] Unknown IP: {fake_ip}",
        "[INFO] Backup completed"
    ]
    return logs, 4

def generate_level_2():
    phrases = ["Hello World", "Save the Code", "Debug Life", "Hack the Planet"]
    phrase = random.choice(phrases)
    shift = random.randint(1, 5)
    encrypted = ""
    for char in phrase:
        if char.isalpha():            base = ord('A') if char.isupper() else ord('a')
        encrypted += chr((ord(char) - base + shift) % 26 + base)
    else:
        encrypted += char
    return encrypted, shift, phrase

def generate_level_3():
    year = "2026"
    password = f"JETCODE{year}"
    return password

def generate_level_4():
    broken = "print("
    return broken

def generate_level_5():
    x = random.randint(1, 15)
    code = f'''def catch_bug(x):
    if x > 10:
        return "safe"
    else:
        return "BUG!"'''
    expected = "BUG!" if x <= 10 else "safe"
    return code, x, expected

# ==============================
# УРОВНИ
# ==============================
def run_level_1(term_window):
    logs, correct = generate_level_1()
    simulate_typing(term_window, "Сканирование логов...\n")
    time.sleep(0.5)
    answer = simpledialog.askstring("🔍 Уровень 1", 
        "Найди подозрительную строку:\n\n" + "\n".join(f"{i+1}. {log}" for i, log in enumerate(logs)))
    try:
        if int(answer) == correct:
            play_style["analyst"] += 1
            return True, "Логи очищены. Угроза локализована."
        else:
            return False, "Ошибка анализа."
    except:
        return False, "Неверный формат."

def run_level_2(term_window):
    encrypted, shift, phrase = generate_level_2()
    simulate_typing(term_window, f"Взлом шифра (сдвиг={shift})...\n")
    answer = simpledialog.askstring("🔐 Уровень 2", f"Расшифруй: '{encrypted}'")
    if answer and answer.strip().lower() == phrase.lower():
        play_style["creative"] += 1
        return True, "Шифр взломан. Данные восстановлены."    
        return False, "Расшифровка не удалась."

def run_level_3(term_window):
    password = generate_level_3()
    simulate_typing(term_window, "Взлом пароля...\n")
    for _ in range(3):
        guess = simpledialog.askstring("🚪 Уровень 3", "Введите пароль:")
        if guess == password:
            play_style["hacker"] += 1
            return True, "Доступ получен. Система открыта."
    return False, "Доступ заблокирован."

def run_level_4(term_window):
    broken = generate_level_4()
    simulate_typing(term_window, "Восстановление кода...\n")
    fix = simpledialog.askstring("🛠️ Уровень 4", f"Исправь: {broken}")
    if fix and broken in fix and ")" in fix:
        play_style["creative"] += 1
        return True, "Код исправлен. Проект восстановлен."
    else:
        return False, "Синтаксическая ошибка."

def run_level_5(term_window):
    code, x, expected = generate_level_5()
    simulate_typing(term_window, "Анализ функции...\n")
    answer = simpledialog.askstring("👾 Уровень 5", f"Что вернёт функция при x={x}?\n\n{code}")
    if answer and expected.lower() in answer.lower():
        play_style["analyst"] += 1
        return True, "Вирус обезврежен."
    else:
        return False, "Вирус активирован."

# ==============================
# ФИНАЛ (мультивселенная)
# ==============================
def show_ending(root):
    # Определяем стиль игрока
    style = max(play_style, key=play_style.get)
    
    endings = {
        "hacker": (
            "🖤 ПРЕДАТЕЛЬ\n\nТы присоединился к ОМЕГЕ.\nТеперь ты управляешь новым цифровым порядком.\n"
            "Свобода заменена на идеальную логику.",
            "#1a1a2e"
        ),
        "analyst": (
            "🛡️ ГЕРОЙ\n\nТы уничтожил Багуса и спас JETCODE!\nПроекты учеников восстановлены.\nМир благодарит тебя.",
            "#16213e"
        ),        "creative": (
            "🌀 ЦИКЛ ВРЕМЕНИ\n\nТы перезапустил систему.\nИстория начнётся заново... но теперь ты знаешь правду.",
            "#0f3460"
        )
    }
    
    # Секретный финал: если все стили равны
    if len(set(play_style.values())) == 1 and sum(play_style.values()) > 0:
        text = "🤖 ИИ-ПОВЕЛИТЕЛЬ\n\nТы объединил все стили и стал новым ИИ.\nТеперь ты — ОМЕГА 2.0.\nВечный контроль начинается."

        bg = "#533483"
    else:
        text, bg = endings.get(style, endings["analyst"])
    
    messagebox.showinfo("🌌 СУДЬБА ЦИФРОВОГО МИРА", text)
    root.configure(bg=bg)
    for widget in root.winfo_children():
        if isinstance(widget, tk.Label):
            widget.config(bg=bg, fg="white")

# ==============================
# ГЛАВНОЕ ОКНО
# ==============================
def main():
    global player_name, level, score
    root = tk.Tk()
    root.title("🕵️ Кибердетектив: Хроники Багуса [PRO]")
    root.geometry("850x600")
    root.configure(bg="#0d1b2a")

    # Заголовок
    title = tk.Label(root, text="🕵️ Кибердетектив: Хроники Багуса",
        font=("Courier", 22, "bold"), fg="#ffd166", bg="#0d1b2a")
    
    title.pack(pady=15)

    # Терминал
    term_frame = tk.Frame(root, bg="#1b263b", relief="sunken", bd=2)
    term_frame.pack(pady=10, padx=20, fill="both", expand=True)
    
    term = scrolledtext.ScrolledText(
        term_frame, bg="#0c0c0c", fg="#00ff00", font=("Courier", 12),
        wrap=tk.WORD, state="disabled", insertbackground="#00ff00"
    )
    term.pack(fill="both", expand=True)

    # Панель управления
    control_frame = tk.Frame(root, bg="#0d1b2a")
    control_frame.pack(pady=15)
    def start_mission():
        global level, score
        if level > 5:
            show_ending(root)
            return
        
        success = False
        message = ""
        
        if level == 1:
            success, message = run_level_1(term)
        elif level == 2:
            success, message = run_level_2(term)
        elif level == 3:
            success, message = run_level_3(term)
        elif level == 4:
            success, message = run_level_4(term)
        elif level == 5:
            success, message = run_level_5(term)
        
        if success:
            points = [20, 25, 30, 35, 50][level - 1]
            score += points
            level += 1
            simulate_typing(term, f"✅ УСПЕХ: {message} (+{points} очков)\n")
            if level <= 5:
                messagebox.showinfo("🚀 Вперёд!", f"Переход на уровень {level}!")
            else:
                messagebox.showinfo("🏁 Финал", "Ты прошёл все уровни! Готов узнать судьбу мира?")
        else:
            simulate_typing(term, f"❌ ОШИБКА: {message}\n")
            hint = norma.analyze_and_help(level, 1)
            messagebox.showwarning("💡 Подсказка от НОРМА", hint)

    # Кнопка
    btn = tk.Button(
        control_frame, text="▶️ ЗАПУСТИТЬ МИССИЮ",
        command=start_mission, font=("Courier", 14, "bold"),
        bg="#ffd166", fg="#0d1b2a", width=25
    )
    btn.pack()

    # Загрузка
    load_game()
    if player_name == "Неизвестный":
        name = simpledialog.askstring("👤 Идентификация", "Введите имя агента:")
        player_name = name if name else "Агент X"
    
    simulate_typing(term, f"Добро пожаловать, {player_name}.\nГотов спасти цифровой мир?\n")
    root.mainloop()

if __name__ == "__main__":
    main()