import speech_recognition as sr
import pygame
import os
import json
import nltk
import time
import webbrowser
import wave
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import LabelEncoder
import joblib
import librosa
import noisereduce as nr
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from gtts import gTTS
import tkinter as tk
from tkinter import messagebox, simpledialog, Toplevel
from tkinter import Button, Entry, Label, Listbox, StringVar
from PIL import Image, ImageTk
import datetime
from datetime import date
import requests
import serial
import pocketsphinx as ps
from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor
from transformers import BertTokenizer, BertModel
from transformers import ChatGPT
from transformers import Wav2Vec2Model, Wav2Vec2Tokenizer
from tkinter import messagebox
from tkinter import Button, Text, Label, Listbox
import pyautogui
import sounddevice as sd
from scipy.io import wavfile
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import random
import distutils
import torch
from sklearn.model_selection import train_test_split
import sys
import platform
from datetime import datetime

# ΜΕΤΡΑ---------------------------------------------------------------------------------


# Έλεγχος για CUDA
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Αρχικοποίηση του μοντέλου BERT
bert_model_name = "bert-base-uncased"
bert_tokenizer = BertTokenizer.from_pretrained(bert_model_name)
bert_model = BertModel.from_pretrained(bert_model_name)

# Αρχικοποίηση του μοντέλου ChatGPT
chatgpt_model = ChatGPT()

# Αρχικοποίηση του Wav2Vec2 μοντέλου και του processor
processor = Wav2Vec2Processor.from_pretrained("facebook/wav2vec2-base-960h")
model = Wav2Vec2ForCTC.from_pretrained("facebook/wav2vec2-base-960h").to(device)

# Φόρτωση των υπαρχόντων ερωτήσεων-απαντήσεων και ιστορικού συνομιλίας
def load_qa_pairs_and_history():
    # Ο κώδικας για φόρτωση ερωτήσεων-απαντήσεων και ιστορικού παραμένει αμετάβλητος

 qa_pairs, conversation_history = load_qa_pairs_and_history()

# Συνάρτηση για ακρόαση και αναγνώριση ομιλίας
def listen():
    # Ο κώδικας για αναγνώριση ομιλίας παραμένει αμετάβλητος

# Συνάρτηση για αποθήκευση ερωτήσεων-απαντήσεων και ιστορικού συνομιλίας
 def save_qa_pairs_and_history(qa_pairs, conversation_history):
     # Ο κώδικας για αποθήκευση ερωτήσεων-απαντήσεων και ιστορικού παραμένει αμετάβλητος

# Συνάρτηση για προεπεξεργασία κειμένου
  def preprocess_text(text):
    # Ο κώδικας για προεπεξεργασία κειμένου παραμένει αμετάβλητος

# Συνάρτηση για ανάλυση συναισθήματος
   def analyze_sentiment(text):
    # Ο κώδικας για ανάλυση συναισθήματος παραμένει αμετάβλητος

# Συνάρτηση για εξαγωγή χαρακτηριστικών από κείμενο με χρήση BERT
    def extract_text_embeddings(text):
    # Ο κώδικας για εξαγωγή χαρακτηριστικών κειμένου με χρήση BERT παραμένει αμετάβλητος

# Συνάρτηση για εξαγωγή χαρακτηριστικών ήχου με χρήση Wav2Vec
     def extract_audio_embeddings(audio):
    # Ο κώδικας για εξαγωγή χαρακτηριστικών ήχου με χρήση Wav2Vec παραμένει αμετάβλητος

# Συνάρτηση για παροχή προσαρμοσμένων απαντήσεων με βάση το ιστορικό συνομιλίας
      def get_response_with_history(question, conversation_history):
        preprocessed_question = preprocess_text(question)
    question_embedding = extract_text_embeddings(preprocessed_question)

    # Αναζήτηση σχετικών προηγούμενων αλληλεπιδράσεων
    relevant_history = [entry for entry in conversation_history if preprocessed_question in entry['question']]

    if relevant_history:
        # Προσαρμογή απάντησης με βάση το ιστορικό
        relevant_answers = [entry['answer'] for entry in relevant_history]
        response = "Έχω απαντήσει σε παρόμοια ερώτηση στο παρελθόν. Οι σχετικές απαντήσεις είναι: " + ", ".join(relevant_answers)
    else:
        response = get_response_with_bert_and_chatgpt(question)

    return response

# Συνάρτηση για παροχή απαντήσεων με χρήση BERT και ChatGPT
def get_response_with_bert_and_chatgpt(question):
    preprocessed_question = preprocess_text(question)
    question_embedding = extract_text_embeddings(preprocessed_question)

    # Εκπαίδευση ενός απλού μοντέλου ταξινόμησης για παροχή απαντήσεων
    tfidf_vectorizer = TfidfVectorizer()
    questions = list(qa_pairs.keys())
    tfidf_matrix = tfidf_vectorizer.fit_transform(questions)
    tfidf_question = tfidf_vectorizer.transform([preprocessed_question])
    similarity_scores = cosine_similarity(tfidf_question, tfidf_matrix)

    similar_indices = similarity_scores[0].argsort()[-2:][::-1]
    similar_questions = [questions[index] for index in similar_indices]

    if similar_questions:
        response = qa_pairs[similar_questions[0]]
    else:
        # Χρήση του ChatGPT για παροχή απάντησης
        chatgpt_response = chatgpt_model.generate_text(question, max_length=50)
        response = chatgpt_response[0]

    return response

# Συνάρτηση για ακρόαση και αναγνώριση ομιλίας με το Pocketsphinx
def listen_with_pocketsphinx():
    recognizer = ps.Recognizer()
    microphone = ps.Microphone()

    try:
        with microphone as source:
            print("Ακούω...")
            recognizer.adjust_for_ambient_noise(source)
            audio = recognizer.listen(source)

        print("Αναγνώριση...")
        text = recognizer.recognize(audio)
        print(f"Αναγνωρίστηκε: {text}")
        return text.lower()

    except ps.pocketsphinx.error as e:
        print(f"Σφάλμα αναγνώρισης ομιλίας: {e}")
        return ""

#-------------------------------------------------------------------------------------
#=======================================================================================================

#----------------------------arduino-------------------------------------------
# Initialize the serial connection to the Arduino
#serial_port = serial.Serial('COM3', 9600)  # Replace 'COM3' with the correct COM port

# Define the pin number for output
pin_number13 = 13

# Function to send commands to the Arduino
def send_command(command):
    global pin_number
    if command == "κωδικός 1":
        serial_port.write(b'1')  # Set pin 12 high
        
        print("Έθεσα το pin 13 σε κατάσταση high.")
    elif command == "κωδικός 2":
        serial_port.write(b'0')  # Set pin 12 low
        print("Έθεσα το pin 13 σε κατάσταση low.")
        speak("έκλεισα το pin 13 στο Arduino.")
    else:
        serial_port.write(command.encode())

# Λίστα με ελληνικά κανάλια τηλεόρασης που έχουν live streaming
greek_tv_channels = {
    
    "άνοιξε άλφα": "https://alphatv.gr/live/",
    "αλφα": "https://alphatv.gr/live/",
    "alpha": "https://alphatv.gr/live/",
    "ant1": "https://www.antenna.gr/webtv/live",
    "αντ1": "https://www.antenna.gr/webtv/live",
    "skai": "https://www.skai.gr/tv/live",
    "σκαϊ": "https://www.skai.gr/tv/live",
    "star": "https://www.star.gr/tv/live-stream",
    "σταρ": "https://www.star.gr/tv/live-stream",
    "ert": "https://www.ertflix.gr/epg/channel/ert1-live",
    "ertflix": "https://www.ertflix.gr/epg/channel/ert1-live",
    "ερτ": "https://www.ertflix.gr/epg/channel/ert1-live",
    "ερτφλιχ": "https://www.ertflix.gr/epg/channel/ert1-live",
    "ερτflix": "https://www.ertflix.gr/epg/channel/ert1-live",
    "youtube": "https://www.youtube.com/",
    "netflix": "https://www.netflix.com/browse",
    "kastamonitis": "https://www.youtube.com/@christoskastamonitis",
    "κασταμονίτης": "https://www.youtube.com/@christoskastamonitis",
    "μπατίδης": "https://www.youtube.com/@BillBad2050/videos",
    "ΜΠΑΝΤΙΔΗΣ": "https://www.youtube.com/@BillBad2050/videos",
    "μπαντίδης": "https://www.youtube.com/@BillBad2050/videos",
    "καιρός": "https://www.okairos.gr/%CE%BC%CE%B5%CE%B3%CE%B1%CE%BB%CF%8C%CF%80%CE%BF%CE%BB%CE%B7.html?d=nw",
    "καιρό": "https://www.okairos.gr/%CE%BC%CE%B5%CE%B3%CE%AC%CE%BB%CE%BF%CF%80%CE%BF%CE%BB%CE%B7.html?d=nw",
    "tik tok": "https://www.tiktok.com/foryou",
    "Έντεχνα": "https://www.youtube.com/watch?v=nUCZkuwPwGg",
    "ελληνικά": "https://www.youtube.com/watch?v=nUCZkuwPwGg",
    "έντεχνα": "https://www.youtube.com/watch?v=nUCZkuwPwGg",
    "ράδιο δρόμος": "https://live24.gr/radio/dromos.jsp",
    "ραδιοδρομος": "https://live24.gr/radio/dromos.jsp",
    "πρώτο θέμα": "https://www.protothema.gr/",
    "in.gr": "https://www.in.gr//",
    "ιν.gr": "https://www.in.gr//",
    "φωτιά τώρα": "https://www.google.com/search?q=%CF%86%CF%89%CF%84%CE%B9%CE%AC%20%CF%84%CF%8E%CF%81%CE%B1",
    "σεισμός τώρα ": "https://www.google.com/search?q=%CF%83%CE%B5%CE%B9%CF%83%CE%BC%CF%8C%CF%82%20%CF%84%CF%8E%CF%81%CE%B1",
    "σεισμός τώρα ": "https://www.seismoi-live.gr/",


    # Προσθέστε περισσότερα κανάλια και τους αντίστοιχους συνδέσμους εδώ
}

# Λειτουργία για άνοιγμα ελληνικού καναλιού τηλεόρασης
def open_greek_tv_channel(channel_name):
    channel_name = channel_name.lower()
    if channel_name in greek_tv_channels:
        url = greek_tv_channels[channel_name]
        webbrowser.open(url)
        speak(f"Άνοιξα το κανάλι {channel_name.upper()}")
    else:
        speak(f"Δεν βρέθηκε το κανάλι {channel_name.upper()}. Παρακαλώ δοκιμάστε ξανά.")

# Προβολή καταχωρημένων ερωτήσεων και απαντήσεων σε διχασμένο παράθυρο
#==========================================================================================================================

# Προβολή καταχωρημένων ερωτήσεων και απαντήσεων σε διχασμένο παράθυρο
def display_questions():
    global question_listbox, answer_listbox, question_entry, answer_entry, root

    def show_questions():
        question_listbox.delete(0, tk.END)
        answer_listbox.delete(0, tk.END)
        for index, (question, answer) in enumerate(qa_pairs.items()):
            question_listbox.insert(tk.END, f"{index + 1}. {question}")
            answer_listbox.insert(tk.END, f"{index + 1}. {answer}")

    def edit_question():
        selected_index = question_listbox.curselection()
        if selected_index:
            selected_question = list(qa_pairs.keys())[selected_index[0]]
            new_question = question_entry.get("1.0", tk.END).strip()

            if new_question:
                qa_pairs[new_question] = qa_pairs.pop(selected_question)  # Ενημέρωση της ερώτησης
                save_qa_pairs(qa_pairs)
                show_questions()
                speak("Η ερώτηση ενημερώθηκε με επιτυχία.")
            else:
                speak("Παρακαλώ εισάγετε μια νέα ερώτηση.")

        else:
            speak("Παρακαλώ επιλέξτε μια ερώτηση από τη λίστα για επεξεργασία.")

    def edit_answer():
        selected_index = answer_listbox.curselection()
        if selected_index:
            selected_question = list(qa_pairs.keys())[selected_index[0]]
            selected_answer = qa_pairs[selected_question]
            new_answer = answer_entry.get("1.0", tk.END).strip()

            if new_answer:
                qa_pairs[selected_question] = new_answer  # Ενημέρωση της απάντησης
                save_qa_pairs(qa_pairs)
                show_questions()
                speak("Η απάντηση ενημερώθηκε με επιτυχία.")
            else:
                speak("Παρακαλώ εισάγετε μια νέα απάντηση.")

        else:
            speak("Παρακαλώ επιλέξτε μια ερώτηση από τη λίστα για επεξεργασία.")

    def add_qa_pair():
        new_question = question_entry.get("1.0", tk.END).strip()
        if new_question:
            new_answer = answer_entry.get("1.0", tk.END).strip()
            if new_answer:
                qa_pairs[new_question] = new_answer  # Προσθήκη του νέου ζεύγους ερώτησης-απάντησης
                save_qa_pairs(qa_pairs)
                show_questions()
                speak("Το ζεύγος ερώτησης-απάντησης προστέθηκε με επιτυχία.")
            else:
                speak("Παρακαλώ εισάγετε μια νέα απάντηση.")
        else:
            speak("Παρακαλώ εισάγετε μια νέα ερώτηση.")

    def delete_qa_pair():
        selected_index = question_listbox.curselection()
        if selected_index:
            selected_question = list(qa_pairs.keys())[selected_index[0]]
            response = messagebox.askyesno("Διαγραφή Ερώτησης", f"Είστε σίγουροι ότι θέλετε να διαγράψετε την ερώτηση '{selected_question}' και την αντίστοιχη απάντηση;")
            if response:
                del qa_pairs[selected_question]  # Διαγραφή του επιλεγμένου ζεύγους ερώτησης-απάντησης
                save_qa_pairs(qa_pairs)
                show_questions()
                speak("Το ζεύγος ερώτησης-απάντησης διαγράφηκε με επιτυχία.")
        else:
            speak("Παρακαλώ επιλέξτε μια ερώτηση από τη λίστα για διαγραφή.")

    def on_close():
        root.destroy()

    def copy_question():
        selected_index = question_listbox.curselection()
        if selected_index:
            selected_question = list(qa_pairs.keys())[selected_index[0]]
            question_entry.delete("1.0", tk.END)
            question_entry.insert("1.0", selected_question)

    def copy_answer():
        selected_index = answer_listbox.curselection()
        if selected_index:
            selected_answer = list(qa_pairs.values())[selected_index[0]]
            answer_entry.delete("1.0", tk.END)
            answer_entry.insert("1.0", selected_answer)

    def right_click_question(event):
        menu = tk.Menu(tearoff=0)
        menu.add_command(label="Αντιγραφή", command=copy_question)
        menu.add_command(label="Επικόλληση", command=lambda: question_entry.event_generate("<<Paste>>"))
        menu.add_command(label="Επεξεργασία", command=edit_question)
        menu.add_command(label="Διαγραφή", command=delete_qa_pair)
        menu.add_command(label="Επιλογή Όλων", command=lambda: question_entry.event_generate("<<SelectAll>>"))
        menu.tk_popup(event.x_root, event.y_root, 0)

    def right_click_answer(event):
        menu = tk.Menu(tearoff=0)
        menu.add_command(label="Αντιγραφή", command=copy_answer)
        menu.add_command(label="Επικόλληση", command=lambda: answer_entry.event_generate("<<Paste>>"))
        menu.add_command(label="Επεξεργασία", command=edit_answer)
        menu.add_command(label="Διαγραφή", command=delete_qa_pair)
        menu.add_command(label="Επιλογή Όλων", command=lambda: answer_entry.event_generate("<<SelectAll>>"))
        menu.tk_popup(event.x_root, event.y_root, 0)

    def right_click_question_entry(event):
        menu = tk.Menu(tearoff=0)
        menu.add_command(label="Αντιγραφή", command=lambda: question_entry.event_generate("<<Copy>>"))
        menu.add_command(label="Επικόλληση", command=lambda: question_entry.event_generate("<<Paste>>"))
        menu.add_command(label="Επεξεργασία", command=edit_question)
        menu.add_command(label="Διαγραφή", command=lambda: question_entry.delete("1.0", tk.END))
        menu.add_command(label="Επιλογή Όλων", command=lambda: question_entry.event_generate("<<SelectAll>>"))
        menu.add_command(label="Αποθήκευση", command=save_qa_pairs)
        menu.tk_popup(event.x_root, event.y_root, 0)

    def right_click_answer_entry(event):
        menu = tk.Menu(tearoff=0)
        menu.add_command(label="Αντιγραφή", command=lambda: answer_entry.event_generate("<<Copy>>"))
        menu.add_command(label="Επικόλληση", command=lambda: answer_entry.event_generate("<<Paste>>"))
        menu.add_command(label="Επεξεργασία", command=edit_answer)
        menu.add_command(label="Διαγραφή", command=lambda: answer_entry.delete("1.0", tk.END))
        menu.add_command(label="Επιλογή Όλων", command=lambda: answer_entry.event_generate("<<SelectAll>>"))
        menu.add_command(label="Αποθήκευση", command=save_qa_pairs)
        menu.tk_popup(event.x_root, event.y_root, 0)

    def save_changes():
        save_qa_pairs(qa_pairs)
        show_questions()
        speak("Οι αλλαγές αποθηκεύτηκαν με επιτυχία.")

    root = tk.Tk()
    root.title("Ερωτήσεις και Απαντήσεις")
    root.geometry("800x450")
    root.configure(bg="#F0F0F0")

    # Δημιουργία διχασμένου παραθύρου
    main_frame = tk.Frame(root, bg="#F0F0F0")
    main_frame.pack(fill=tk.BOTH, expand=True)

    question_frame = tk.Frame(main_frame, bg="#F0F0F0")
    question_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    answer_frame = tk.Frame(main_frame, bg="#F0F0F0")
    answer_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

    # Πλαίσιο Ερωτήσεων
    question_label = tk.Label(question_frame, text="Ερωτήσεις:", bg="#F0F0F0", fg="#333333", font=("Arial", 14, "bold"))
    question_label.pack(pady=10)

    question_listbox = tk.Listbox(question_frame, selectmode=tk.SINGLE, font=("Arial", 12), bg="#FFFFFF", fg="#333333", highlightthickness=0, bd=0)
    question_listbox.pack(pady=10, fill=tk.BOTH, expand=True)
    question_listbox.bind("<Button-3>", right_click_question)

    question_entry = tk.Text(question_frame, height=5, width=40, font=("Arial", 12))
    question_entry.pack(pady=5)
    question_entry.bind("<Button-3>", right_click_question_entry)

    # Πλαίσιο Απαντήσεων
    answer_label = tk.Label(answer_frame, text="Απαντήσεις:", bg="#F0F0F0", fg="#333333", font=("Arial", 14, "bold"))
    answer_label.pack(pady=10)

    answer_listbox = tk.Listbox(answer_frame, selectmode=tk.SINGLE, font=("Arial", 12), bg="#FFFFFF", fg="#333333", highlightthickness=0, bd=0)
    answer_listbox.pack(pady=10, fill=tk.BOTH, expand=True)
    answer_listbox.bind("<Button-3>", right_click_answer)

    answer_entry = tk.Text(answer_frame, height=5, width=40, font=("Arial", 12))
    answer_entry.pack(pady=5)
    answer_entry.bind("<Button-3>", right_click_answer_entry)

    copy_question_button = tk.Button(question_frame, text="Αντιγραφή Ερώτησης", command=copy_question, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    copy_question_button.pack(pady=5)

    copy_answer_button = tk.Button(answer_frame, text="Αντιγραφή Απάντησης", command=copy_answer, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    copy_answer_button.pack(pady=5)

    edit_question_button = tk.Button(question_frame, text="Επεξεργασία Ερώτησης", command=edit_question, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    edit_question_button.pack(pady=5)

    edit_answer_button = tk.Button(answer_frame, text="Επεξεργασία Απάντησης", command=edit_answer, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    edit_answer_button.pack(pady=5)

    add_button = tk.Button(answer_frame, text="Προσθήκη Ζεύγους", command=add_qa_pair, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    add_button.pack(pady=5)

    delete_button = tk.Button(answer_frame, text="Διαγραφή Ζεύγους", command=delete_qa_pair, bg="#FF5733", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    delete_button.pack(pady=5)

    save_button = tk.Button(answer_frame, text="Αποθήκευση Αλλαγών", command=save_changes, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    save_button.pack(pady=5)

    close_button = tk.Button(root, text="Κλείσιμο", command=root.destroy, bg="#4CAF50", fg="#FFFFFF", font=("Arial", 12, "bold"), relief=tk.RAISED, bd=3)
    close_button.pack(pady=10)

    root.protocol("WM_DELETE_WINDOW", on_close)

    show_questions()

    root.mainloop()




#========================================================================================----------------------
# Μετατροπή κειμένου σε ομιλία και αναπαραγωγή
def speak(text):
    try:
        tts = gTTS(text=text, lang='el')
        filename = "voice.mp3"
        tts.save(filename)

        pygame.mixer.init()
        pygame.mixer.music.load(filename)
        pygame.mixer.music.play()

        while pygame.mixer.music.get_busy():
            pygame.time.Clock().tick(20)

        pygame.mixer.music.stop()
        pygame.mixer.quit()

        os.remove(filename)

    except Exception as e:
        print(f"Σφάλμα κατά την αναπαραγωγή ομιλίας: {e}. Παρακαλώ ελέγξτε τη ρύθμιση ήχου και προσπαθήστε ξανά.")

# Συνάρτηση για αποστολή εντολών στο Arduino
def send_command(command):
    try:
        serial_port.write(command.encode())
    except:
        print("Αδυναμία αποστολής εντολής στο Arduino.")

# Κύρια λειτουργία του εικονικού βοηθού
# Συνάρτηση για αποστολή εντολών στο Arduino
def send_command(command):
    try:
        serial_port.write(command.encode())
    except:
        print("Αδυναμία αποστολής εντολής στο Arduino.")

# Κύρια λειτουργία του εικονικού βοηθού
def main():
    speak("Γεια σας! Είμαι η Μία, ο εικονικός σας βοηθός. Πώς μπορώ να σας βοηθήσω σήμερα;")

    while True:
        command = listen()
        if command:
            last_activity_time = time.time()

            if "έξοδος" in command or "σταμάτα" in command:
                speak("Αντίο! Ήταν χαρά μου που σας βοήθησα.")
                break
            
            elif "προσθήκη απάντησης" in command:
                speak("Πείτε μου την ερώτηση, παρακαλώ.")
                question = listen()
                if question:
                    speak("Τώρα, πείτε μου την απάντηση.")
                    answer = listen()
                    if answer:
                        qa_pairs[question] = answer
                        save_qa_pairs_and_history(qa_pairs, conversation_history)
                        speak("Η ερώτηση και η απάντηση προστέθηκαν με επιτυχία.")

            elif "προβολή απαντήσεων" in command:
                display_questions()
            elif "σημείωσε" in command:
                record_note()
            elif "άνοιξε youtube" in command:
                webbrowser.open("https://www.youtube.com")
                speak("Άνοιξα τη σελίδα του YouTube για εσάς.")
            elif "άνοιξε φώτα" in command:
                send_command("1")
                speak("Άνοιξα το pin 13 στο Arduino.")
                print("Άνοιξα το pin 13 στο Arduino.")
                print(f"Η τρέχουσα ώρα είναι {current_time}.")

            elif "κλείσε φώτα" in command:
                send_command("0")
                speak(" Eκλεισα το pin 13 στο Arduino.")
                print(" Eκλεισα το pin 13 στο Arduino.")
                print(f"Η τρέχουσα ώρα είναι {current_time}.")
            elif "τι ώρα είναι" in command:
                current_time = datetime.now().strftime("%H:%M")
                print(f"Η τρέχουσα ώρα είναι {current_time}.")
                speak(f"Η τρέχουσα ώρα είναι {current_time}.")
            elif "τι μέρα είναι" in command:
                today = date.today()
                current_day = today.strftime("%d, %A")
                speak(f"Σήμερα είναι {current_day}.")
            elif "διάβασε ειδήσεις" in command:
                read_news()
            elif "άνοιξε" in command.lower() and any(channel in command.lower() for channel in greek_tv_channels):
                for channel_name in greek_tv_channels:
                    if channel_name in command.lower():
                        open_greek_tv_channel(channel_name)
                        break
                speak("")
            elif "μέτρα" in command:
                open_coordinate_window()
            elif "κλείσε το παράθυρο" in command or "κλείσε" in command:
                try:
                    pyautogui.hotkey('ctrl', 'w')  # Για Windows/Linux
                    # pyautogui.hotkey('command', 'w')  # Για macOS
                    speak("Έκλεισα το παράθυρο του browser.")
                except Exception as e:
                    speak("Δεν μπόρεσα να κλείσω το παράθυρο. Παρουσιάστηκε σφάλμα.")
                    print(f"Σφάλμα κατά το κλείσιμο του παραθύρου: {e}")
            else:
                response = get_response_with_history(command, conversation_history)
                speak(response)

                timestamp = datetime.now().strftime("%Y-%m-%d %H")
                conversation_history.append({'question': command, 'answer': response, 'timestamp': timestamp})
                save_qa_pairs_and_history(qa_pairs, conversation_history)

if __name__ == "__main__":
    main()