import os, shutil, subprocess, smtplib
from email.message import EmailMessage
import glob
from datetime import datetime

# --- 1. СПИСКИ ---
# УКАЗЫВАЕМ ФАЙЛЫ КОТОРЫЕ ХОТИМ СОХРАНИТЬ НА ПОЧТУ
FILES_TO_BACKUP = [
    '/root/.bashrc',
    '/root/.aliases',
    '/root/.gitconfig',
    '/root/.vimrc',
    '/root/.tmux.conf',
    '/home/jeen/sites/lara/app/helpers/pythoni/.env',
    '/home/jeen/sites/lara/.env',
    '/home/jeen/sites/lara/app/helpers/python/scripts/backup/SETTINGS_JETBRAINS*.rar',
    '/home/jeen/sites/lara/database/backup/lara_*.sql'
]

# УКАЗЫВАЕМ ПАПКИ КОТОРЫЕ ХОТИМ СОХРАНИТЬ НА ПОЧТУ
DIRS_TO_BACKUP = [
    '/etc/nginx/conf.d',
    '/etc/nginx/sites-available',
    '/home/jeen/sites/lara/app/helpers/python/get_http/chrome_extensions',
    '/home/jeen/sites/lara/app/helpers/python/get_http/tabs',
    '/root/.wireguard',
    '/root/z0rde',
    '/home/jeen/sites/lara/app/helpers/python/services'
]

# Настройки путей
TMP_DIR = '/tmp/backup_stage/'
ARCHIVE_PATH = '/tmp/final_backup.rar'
RAR_PASSWORD = 'buria'

# Настройки почты
EMAIL_SENDER = "jeep65418@gmail.com"
EMAIL_PASSWORD = "ihzs nfxz hcfi xjsg"
EMAIL_RECEIVER = "jeep456@yandex.ru"
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 465

# Настройки Postgres
DB_NAME = "lara"
DB_USER = "jeen"
DB_PASSWORD = "hula"
DB_HOST = "localhost"
DB_PORT = "5432"
# Путь теперь указан точно по твоему запросу
BACKUP_PATH_DB = "/home/jeen/sites/lara/database/backup/"


# --- 2. ФУНКЦИИ ---

def clear_backup_folder(path):
    """Удаляет все файлы и папки внутри указанной директории"""
    if os.path.exists(path):
        print(f"Очистка папки бэкапов: {path}")
        for item in os.listdir(path):
            item_path = os.path.join(path, item)
            try:
                if os.path.isfile(item_path) or os.path.islink(item_path):
                    os.unlink(item_path)
                elif os.path.isdir(item_path):
                    shutil.rmtree(item_path)
            except Exception as e:
                print(f"Не удалось удалить {item_path}: {e}")
    else:
        # Если папки нет, создаем её
        os.makedirs(path)

def create_backup_db():
    # 1. Очищаем папку перед созданием нового бэкапа
    clear_backup_folder(BACKUP_PATH_DB)

    # 2. Формируем имя файла: lara_15.02.26_10_20_10.sql
    # %d - день, %m - месяц, %y - год (две цифры), %H, %M, %S - время
    timestamp = datetime.now().strftime("%d.%m.%y_%H_%M_%S")
    filename = f"{DB_NAME}_{timestamp}.sql"
    file_path = os.path.join(BACKUP_PATH_DB, filename)

    # Устанавливаем пароль в переменные окружения
    env = os.environ.copy()
    env["PGPASSWORD"] = DB_PASSWORD

    # Команда для pg_dump
    command = [
        "pg_dump",
        "-h", DB_HOST,
        "-p", DB_PORT,
        "-U", DB_USER,
        "-f", file_path,
        DB_NAME
    ]

    try:
        print(f"Запуск бэкапа базы {DB_NAME}...")
        subprocess.run(command, env=env, check=True)
        print(f"Успех! Файл создан: {file_path}")
    except subprocess.CalledProcessError as e:
        print(f"Ошибка при создании бэкапа: {e}")

def prepare_dirs():
    """Копирует содержимое указанных директорий в папку бэкапа"""
    for d in DIRS_TO_BACKUP:
        if os.path.exists(d):
            base_name = os.path.basename(d.rstrip('/'))
            target = os.path.join(TMP_DIR, base_name)
            shutil.copytree(d, target, dirs_exist_ok=True)
            print(f"Директория скопирована: {d}")

def save_crontab():
    """Читает текущий кронтаб и сохраняет его в файл"""
    cron_file = os.path.join(TMP_DIR, 'crontab_root.txt')
    try:
        with open(cron_file, "w") as f:
            subprocess.run(['crontab', '-l'], stdout=f, check=True)
        print("Кронтаб сохранен.")
    except subprocess.CalledProcessError:
        print("Кронтаб пуст или недоступен.")

def create_final_archive():
    """Собирает всё в кучу, включая файлы по маскам, и архивирует"""
    # 1. Сначала создаем свежий дамп базы данных
    # Теперь файл появится в /home/jeen/sites/lara/database/backup/ ДО поиска файлов
    create_backup_db()

    # 2. Готовим временную папку
    if os.path.exists(TMP_DIR):
        shutil.rmtree(TMP_DIR)
    os.makedirs(TMP_DIR)

    # 3. Копируем файлы (теперь glob точно найдет свежий .sql файл)
    for pattern in FILES_TO_BACKUP:
        found_files = glob.glob(pattern)
        for f in found_files:
            if os.path.isfile(f):
                shutil.copy(f, TMP_DIR)
                print(f"Скопирован: {os.path.basename(f)}")

    # 4. Собираем остальное
    prepare_dirs()
    save_crontab()

    # 5. Архивируем
    try:
        # Добавил флаг -y для автоматического подтверждения замены старого архива
        subprocess.run([
            'rar', 'a', f'-p{RAR_PASSWORD}', '-ep1', '-r', '-y',
            ARCHIVE_PATH, TMP_DIR
        ], check=True)
        return True
    except Exception as e:
        print(f"Ошибка при архивации: {e}")
        return False


def send_and_cleanup():
    """Отправляет письмо и удаляет архив в случае успеха"""
    # Получаем текущее время для темы письма
    current_time = datetime.now().strftime("%d.%m.%y %H:%M:%S")
    subject = f"Системный бэкап {current_time}"
    
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = EMAIL_SENDER
    msg['To'] = EMAIL_RECEIVER
    msg.set_content("Готовый архив во вложении.")

    with open(ARCHIVE_PATH, 'rb') as f:
        msg.add_attachment(
            f.read(),
            maintype='application',
            subtype='x-rar-compressed',
            filename=os.path.basename(ARCHIVE_PATH)
        )

    with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as smtp:
        smtp.login(EMAIL_SENDER, EMAIL_PASSWORD)
        smtp.send_message(msg)

    print(f"Архив отправлен на почту. Тема: {subject}")

    # Удаление файла после успешной отправки
    if os.path.exists(ARCHIVE_PATH):
        os.remove(ARCHIVE_PATH)
        print(f"Файл {ARCHIVE_PATH} удален.")

# --- 3. ЗАПУСК ---
if __name__ == "__main__":
    try:
        if create_final_archive():
            send_and_cleanup()
    finally:
        # В любом случае чистим временную папку
        if os.path.exists(TMP_DIR):
            shutil.rmtree(TMP_DIR)
            shutil.rmtree(BACKUP_PATH_DB)
