import os
import shutil
import time
import datetime
import sqlite3
import threading

DB_NAME = 'my_data.db'

class FolderSynchronizer:
    def __init__(self, name, folder1, folder2, interval):
        self.name = name
        self.folder1 = folder1
        self.folder2 = folder2
        self.interval = interval
        self.local = threading.local()
        self.create_table()

    def get_connection(self):
            if not hasattr(self.local, 'conn'):
                self.local.conn = sqlite3.connect(DB_NAME)
            return self.local.conn

    def get_cursor(self):
        return self.get_connection().cursor()

    def create_table(self):
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(f'''
            CREATE TABLE IF NOT EXISTS {self.name} (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                rel_dir TEXT,
                file_name TEXT,
                modified1 REAL,
                exist1 INTEGER,
                modified2 REAL,
                exist2 INTEGER,
                UNIQUE(rel_dir, file_name)
            )
        ''')
        conn.commit()

    # def delete_job(self):
    #     conn = self.get_connection()
    #     cursor = conn.cursor()
    #     cursor.execute(f"DROP TABLE IF EXISTS {self.name}")
    #     conn.commit()
    #     print(f"Job '{self.name}' has been deleted.")

    def update_db(self, rel_dir, file_name, modified1, exist1, modified2, exist2):
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(f'''
            INSERT OR REPLACE INTO {self.name} 
            (rel_dir, file_name, modified1, exist1, modified2, exist2)
            VALUES (?, ?, ?, ?, ?, ?)
        ''', (rel_dir, file_name, modified1, exist1, modified2, exist2))
        conn.commit()

    def get_file_info(self, rel_dir, file_name):
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(f'''
            SELECT * FROM {self.name}
            WHERE rel_dir = ? AND file_name = ?
        ''', (rel_dir, file_name))
        return cursor.fetchone()

    def sync_folders(self):
        def sync_files(src_folder, dest_folder):
            current_time = time.time()
            total_sync = 0
            count_sync = 0
            for root, _, files in os.walk(src_folder):
                for filename in files:
                    src_path = os.path.join(root, filename)
                    rel_dir = os.path.relpath(root, src_folder)
                    dest_path = os.path.join(dest_folder, rel_dir, filename)
                    total_sync += 1

                    src_modified = os.path.getmtime(src_path)
                    file_info = self.get_file_info(rel_dir, filename)

                    if not file_info:
                        # New file
                        os.makedirs(os.path.dirname(dest_path), exist_ok=True)
                        shutil.copy2(src_path, dest_path)
                        count_sync += 1
                        dest_modified = current_time
                        modified1, exist1, modified2, exist2 = src_modified, 1, dest_modified, 1
                    else:
                        # Existing file
                        if src_modified > file_info[3] or not file_info[4]:
                            shutil.copy2(src_path, dest_path)
                            count_sync += 1
                            dest_modified = current_time
                            modified1, exist1, modified2, exist2 = src_modified, 1, dest_modified, 1
                        else:
                            modified1, exist1, modified2, exist2 = src_modified, 1, file_info[5], file_info[6]

                    self.update_db(rel_dir, filename, modified1, exist1, modified2, exist2)

            return total_sync, count_sync

        def check_deleted_files():
            conn = self.get_connection()
            cursor = conn.cursor()
            current_time = time.time()
            count_sync = 0
            cursor.execute(f"SELECT rel_dir, file_name, modified1, exist1, modified2, exist2 FROM {self.name}")
            for row in cursor.fetchall():
                rel_dir, file_name, modified1, exist1, modified2, exist2 = row
                path1 = os.path.join(self.folder1, rel_dir, file_name)
                path2 = os.path.join(self.folder2, rel_dir, file_name)

                if not os.path.exists(path1) and not os.path.exists(path2):
                    count_sync += 1
                    cursor.execute(f"DELETE FROM {self.name} WHERE rel_dir = ? AND file_name = ?", (rel_dir, file_name))
                elif not os.path.exists(path1) and exist1:
                    modified1 = current_time
                    if modified1 > modified2:
                        count_sync += 1
                        os.remove(path2)
                        cursor.execute(f"DELETE FROM {self.name} WHERE rel_dir = ? AND file_name = ?", (rel_dir, file_name))
                    else:
                        self.update_db(rel_dir, file_name, modified1, 0, modified2, exist2)
                elif not os.path.exists(path2) and exist2:
                    modified2 = current_time
                    if modified2 > modified1:
                        count_sync += 1
                        os.remove(path1)
                        cursor.execute(f"DELETE FROM {self.name} WHERE rel_dir = ? AND file_name = ?", (rel_dir, file_name))
                    else:
                        self.update_db(rel_dir, file_name, modified1, exist1, modified2, 0)

            conn.commit()
            return count_sync

        total_sync1, count_sync1 = sync_files(self.folder1, self.folder2)
        total_sync2, count_sync2 = sync_files(self.folder2, self.folder1)
        count_sync3 = check_deleted_files()

        total_sync = max(total_sync1, total_sync2)
        count_sync = count_sync1 + count_sync2 + count_sync3

        # now = datetime.datetime.now()
        # formatted_datetime = now.strftime("[%Y-%m-%d %H:%M:%S]")
        
        # return f"[{self.name}] \'{self.folder1} <-> {self.folder2}\' Sync completed! (sync count: {count_sync}, total files: {total_sync})"
        return f"[{self.name}] Sync completed! (sync count: {count_sync}, total files: {total_sync})"