"""
Django management команда для восстановления базы данных из бэкапа.
Использование: python manage.py restore_database <путь_к_бэкапу>
"""

import os
import gzip
from django.core.management.base import BaseCommand
from django.conf import settings
from django.db import connection
import logging

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = 'Восстанавливает базу данных из резервной копии'

    def add_arguments(self, parser):
        parser.add_argument(
            'backup_file',
            type=str,
            help='Путь к файлу бэкапа (.sql или .sql.gz)',
        )
        parser.add_argument(
            '--confirm',
            action='store_true',
            help='Подтверждение восстановления (обязательно для production)',
        )

    def handle(self, *args, **options):
        backup_file = options['backup_file']
        confirm = options['confirm']

        if not os.path.exists(backup_file):
            self.stdout.write(
                self.style.ERROR(f'Файл бэкапа не найден: {backup_file}')
            )
            return

        # Проверка режима production
        if not settings.DEBUG and not confirm:
            self.stdout.write(
                self.style.ERROR(
                    'ВНИМАНИЕ: Вы пытаетесь восстановить базу данных в production режиме!\n'
                    'Используйте --confirm для подтверждения.'
                )
            )
            return

        # Получаем параметры подключения к БД
        db_config = settings.DATABASES['default']
        db_name = db_config['NAME']
        db_user = db_config['USER']
        db_host = db_config.get('HOST', 'localhost')
        db_port = db_config.get('PORT', '5432')

        self.stdout.write(
            self.style.WARNING(
                f'ВНИМАНИЕ: Это действие перезапишет базу данных {db_name}!\n'
                f'Убедитесь, что у вас есть актуальный бэкап перед продолжением.'
            )
        )

        if not confirm:
            response = input('Продолжить? (yes/no): ')
            if response.lower() != 'yes':
                self.stdout.write('Восстановление отменено.')
                return

        try:
            import subprocess

            # Определяем, сжат ли файл
            is_compressed = backup_file.endswith('.gz')

            # Формируем команду psql
            psql_cmd = [
                'psql',
                '-h', db_host,
                '-p', str(db_port),
                '-U', db_user,
                '-d', db_name,
                '--no-password',
            ]

            # Устанавливаем пароль через переменную окружения
            env = os.environ.copy()
            if 'PASSWORD' in db_config:
                env['PGPASSWORD'] = db_config['PASSWORD']

            self.stdout.write(f'Восстановление из файла: {backup_file}...')

            # Открываем файл бэкапа
            if is_compressed:
                file_handle = gzip.open(backup_file, 'rt', encoding='utf-8')
            else:
                file_handle = open(backup_file, 'r', encoding='utf-8')

            # Выполняем восстановление
            with file_handle:
                process = subprocess.Popen(
                    psql_cmd,
                    stdin=file_handle,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    env=env,
                )

                stdout, stderr = process.communicate()

                if process.returncode != 0:
                    error_msg = stderr.decode('utf-8')
                    self.stdout.write(
                        self.style.ERROR(f'Ошибка восстановления: {error_msg}')
                    )
                    return

            self.stdout.write(
                self.style.SUCCESS('✓ База данных успешно восстановлена!')
            )

            # Рекомендуем выполнить миграции
            self.stdout.write(
                self.style.WARNING(
                    'Рекомендуется выполнить: python manage.py migrate'
                )
            )

        except FileNotFoundError:
            self.stdout.write(
                self.style.ERROR(
                    'psql не найден. Убедитесь, что PostgreSQL клиент установлен.'
                )
            )
        except Exception as e:
            self.stdout.write(
                self.style.ERROR(f'Ошибка при восстановлении: {str(e)}')
            )
            logger.error(f'Restore error: {e}', exc_info=True)

