# Backup_Manager.py
#
# Imports:
import os
import shutil
import sqlite3
from datetime import datetime
import logging
#
# Local Imports:
from App_Function_Libraries.DB.Character_Chat_DB import chat_DB_PATH
from App_Function_Libraries.DB.RAG_QA_Chat_DB import get_rag_qa_db_path
from App_Function_Libraries.Utils.Utils import get_project_relative_path
#
# End of Imports
#######################################################################################################################
#
# Functions:

def init_backup_directory(backup_base_dir: str, db_name: str) -> str:
    """Initialize backup directory for a specific database."""
    backup_dir = os.path.join(backup_base_dir, db_name)
    os.makedirs(backup_dir, exist_ok=True)
    return backup_dir


def create_backup(db_path: str, backup_dir: str, db_name: str) -> str:
    """Create a full backup of the database."""
    try:
        db_path = os.path.abspath(db_path)
        backup_dir = os.path.abspath(backup_dir)

        logging.info(f"Creating backup:")
        logging.info(f"  DB Path: {db_path}")
        logging.info(f"  Backup Dir: {backup_dir}")
        logging.info(f"  DB Name: {db_name}")

        # Create subdirectory based on db_name
        specific_backup_dir = os.path.join(backup_dir, db_name)
        os.makedirs(specific_backup_dir, exist_ok=True)

        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_file = os.path.join(specific_backup_dir, f"{db_name}_backup_{timestamp}.db")
        logging.info(f"  Full backup path: {backup_file}")

        # Create a backup using SQLite's backup API
        with sqlite3.connect(db_path) as source, \
                sqlite3.connect(backup_file) as target:
            source.backup(target)

        logging.info(f"Backup created successfully: {backup_file}")
        return f"Backup created: {backup_file}"
    except Exception as e:
        error_msg = f"Failed to create backup: {str(e)}"
        logging.error(error_msg)
        return error_msg


def create_incremental_backup(db_path: str, backup_dir: str, db_name: str) -> str:
    """Create an incremental backup using VACUUM INTO."""
    try:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_file = os.path.join(backup_dir,
                                   f"{db_name}_incremental_{timestamp}.sqlib")

        with sqlite3.connect(db_path) as conn:
            conn.execute(f"VACUUM INTO '{backup_file}'")

        logging.info(f"Incremental backup created: {backup_file}")
        return f"Incremental backup created: {backup_file}"
    except Exception as e:
        error_msg = f"Failed to create incremental backup: {str(e)}"
        logging.error(error_msg)
        return error_msg


def list_backups(backup_dir: str) -> str:
    """List all available backups."""
    try:
        backups = [f for f in os.listdir(backup_dir)
                   if f.endswith(('.db', '.sqlib'))]
        backups.sort(reverse=True)  # Most recent first
        return "\n".join(backups) if backups else "No backups found"
    except Exception as e:
        error_msg = f"Failed to list backups: {str(e)}"
        logging.error(error_msg)
        return error_msg


def restore_single_db_backup(db_path: str, backup_dir: str, db_name: str, backup_name: str) -> str:
    """Restore database from a backup file."""
    try:
        logging.info(f"Restoring backup: {backup_name}")
        backup_path = os.path.join(backup_dir, backup_name)
        if not os.path.exists(backup_path):
            logging.error(f"Backup file not found: {backup_name}")
            return f"Backup file not found: {backup_name}"

        # Create a timestamp for the current db
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        current_backup = os.path.join(backup_dir,
                                      f"{db_name}_pre_restore_{timestamp}.db")

        # Backup current database before restore
        logging.info(f"Creating backup of current database: {current_backup}")
        shutil.copy2(db_path, current_backup)

        # Restore the backup
        logging.info(f"Restoring database from {backup_name}")
        shutil.copy2(backup_path, db_path)

        logging.info(f"Database restored from {backup_name}")
        return f"Database restored from {backup_name}"
    except Exception as e:
        error_msg = f"Failed to restore backup: {str(e)}"
        logging.error(error_msg)
        return error_msg


def setup_backup_config():
    """Setup configuration for database backups."""
    backup_base_dir = get_project_relative_path('tldw_DB_Backups')
    logging.info(f"Base backup directory: {os.path.abspath(backup_base_dir)}")

    # RAG Chat DB configuration
    rag_db_path = get_rag_qa_db_path()
    rag_backup_dir = os.path.join(backup_base_dir, 'rag_chat')
    os.makedirs(rag_backup_dir, exist_ok=True)
    logging.info(f"RAG backup directory: {os.path.abspath(rag_backup_dir)}")

    rag_db_config = {
        'db_path': rag_db_path,
        'backup_dir': rag_backup_dir,  # Make sure we use the full path
        'db_name': 'rag_qa'
    }

    # Character Chat DB configuration
    char_backup_dir = os.path.join(backup_base_dir, 'character_chat')
    os.makedirs(char_backup_dir, exist_ok=True)
    logging.info(f"Character backup directory: {os.path.abspath(char_backup_dir)}")

    char_db_config = {
        'db_path': chat_DB_PATH,
        'backup_dir': char_backup_dir,  # Make sure we use the full path
        'db_name': 'chatDB'
    }

    # Media DB configuration (based on your logs)
    media_backup_dir = os.path.join(backup_base_dir, 'media')
    os.makedirs(media_backup_dir, exist_ok=True)
    logging.info(f"Media backup directory: {os.path.abspath(media_backup_dir)}")

    media_db_config = {
        'db_path': os.path.join(os.path.dirname(chat_DB_PATH), 'media_summary.db'),
        'backup_dir': media_backup_dir,
        'db_name': 'media'
    }

    return rag_db_config, char_db_config, media_db_config