#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Утилиты для управления администраторами бота
"""

import os
import logging
from typing import List, Optional, Callable, Any, Union
from functools import wraps
from telegram import Update
from telegram.ext import ContextTypes
from src.config.config import ADMIN_USER_IDS

# Настройка логирования
logger = logging.getLogger(__name__)

def is_admin(user_id: int) -> bool:
    """Проверяет, является ли пользователь администратором бота
    
    Args:
        user_id: ID пользователя Telegram
        
    Returns:
        True если пользователь администратор, иначе False
    """
    return user_id in ADMIN_USER_IDS

def admin_required(func: Callable) -> Callable:
    """Декоратор для проверки, является ли пользователь администратором
    
    Args:
        func: Оригинальная функция обработчика
        
    Returns:
        Обернутая функция с проверкой прав администратора
    """
    @wraps(func)
    async def wrapper(*args: Any, **kwargs: Any) -> Any:
        # Определяем, является ли функция методом класса
        # Если первый аргумент - это self, то второй должен быть update
        if len(args) >= 2 and isinstance(args[1], Update):
            self_obj = args[0]
            update = args[1]
            context = args[2] if len(args) > 2 else kwargs.get('context')
        else:
            # Если это обычная функция, то первый аргумент - update
            update = args[0] if args else kwargs.get('update')
            context = args[1] if len(args) > 1 else kwargs.get('context')
            self_obj = None
        
        # Проверяем доступность объекта update и effective_user
        if not update or not update.effective_user:
            logger.warning("Update object is incomplete, unable to check admin status")
            return
        
        user_id = update.effective_user.id
        username = update.effective_user.username or "Unknown"
        
        if not is_admin(user_id):
            logger.warning(f"Unauthorized access attempt by user {user_id} (@{username})")
            
            # Если это сообщение, отправляем уведомление
            if update.message:
                await update.message.reply_text(
                    "⛔️ У вас нет прав на использование этой команды.\n"
                    "Обратитесь к владельцу бота, чтобы получить доступ."
                )
            # Если это callback query, отвечаем на него
            elif update.callback_query:
                await update.callback_query.answer(
                    "⛔️ У вас нет прав на использование этой функции."
                )
            return
        
        # Если пользователь админ, вызываем оригинальную функцию
        return await func(*args, **kwargs)
    
    return wrapper

async def add_admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Добавляет нового администратора бота
    
    Args:
        update: Объект обновления Telegram
        context: Контекст вызова
    """
    if not update.message:
        return
        
    # Проверяем, что команду выполняет администратор
    if not update.effective_user or update.effective_user.id not in ADMIN_USER_IDS:
        await update.message.reply_text("⛔️ У вас нет прав для выполнения этой команды.")
        return
        
    # Проверяем, есть ли аргументы команды
    if not context.args or len(context.args) < 1:
        await update.message.reply_text(
            "❌ <b>Ошибка:</b> Необходимо указать ID пользователя.\n\n"
            "Пример использования:\n"
            "<code>/addadmin 123456789</code>",
            parse_mode="HTML"
        )
        return
        
    try:
        # Парсим ID нового администратора
        new_admin_id = int(context.args[0])
        
        # Проверяем, не является ли пользователь уже администратором
        if new_admin_id in ADMIN_USER_IDS:
            await update.message.reply_text(f"ℹ️ Пользователь с ID {new_admin_id} уже является администратором.")
            return
            
        # Добавляем нового администратора
        env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), '.env')
        
        # Читаем текущий файл .env
        env_content = ""
        with open(env_path, 'r', encoding='utf-8') as f:
            env_content = f.read()
            
        # Находим строку с ADMIN_USER_IDS
        lines = env_content.split('\n')
        admin_line_idx = -1
        
        for i, line in enumerate(lines):
            if line.startswith('ADMIN_USER_IDS='):
                admin_line_idx = i
                break
                
        # Обновляем или добавляем строку с администраторами
        if admin_line_idx >= 0:
            current_ids = lines[admin_line_idx].split('=')[1].strip()
            new_ids = f"{current_ids},{new_admin_id}" if current_ids else str(new_admin_id)
            lines[admin_line_idx] = f"ADMIN_USER_IDS={new_ids}"
        else:
            lines.append(f"ADMIN_USER_IDS={new_admin_id}")
            
        # Записываем обновленный файл
        with open(env_path, 'w', encoding='utf-8') as f:
            f.write('\n'.join(lines))
            
        # Обновляем список в памяти
        ADMIN_USER_IDS.append(new_admin_id)
        
        await update.message.reply_text(
            f"✅ <b>Успешно!</b>\n\n"
            f"Пользователь с ID <code>{new_admin_id}</code> добавлен в список администраторов.",
            parse_mode="HTML"
        )
        
        logger.info(f"User {update.effective_user.id} added a new admin: {new_admin_id}")
        
    except ValueError:
        await update.message.reply_text(
            "❌ <b>Ошибка:</b> ID пользователя должен быть целым числом.\n\n"
            "Пример использования:\n"
            "<code>/addadmin 123456789</code>",
            parse_mode="HTML"
        )
    except Exception as e:
        logger.error(f"Error adding admin: {str(e)}")
        await update.message.reply_text(
            f"❌ <b>Произошла ошибка при добавлении администратора:</b>\n\n{str(e)}",
            parse_mode="HTML"
        )

async def remove_admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Удаляет администратора бота
    
    Args:
        update: Объект обновления Telegram
        context: Контекст вызова
    """
    if not update.message:
        return
        
    # Проверяем, что команду выполняет администратор
    if not update.effective_user or update.effective_user.id not in ADMIN_USER_IDS:
        if update.message:
            await update.message.reply_text("⛔️ У вас нет прав для выполнения этой команды.")
        return
        
    # Проверяем, есть ли аргументы команды
    if not context.args or len(context.args) < 1:
        if update.message:
            await update.message.reply_text(
                "❌ <b>Ошибка:</b> Необходимо указать ID пользователя.\n\n"
                "Пример использования:\n"
                "<code>/removeadmin 123456789</code>",
                parse_mode="HTML"
            )
        return
        
    try:
        # Парсим ID администратора для удаления
        admin_id = int(context.args[0])
        
        # Проверяем, не удаляет ли админ сам себя
        if admin_id == update.effective_user.id:
            if update.message:
                await update.message.reply_text("⚠️ Вы не можете удалить самого себя из администраторов.")
            return
            
        # Проверяем, является ли пользователь администратором
        if admin_id not in ADMIN_USER_IDS:
            if update.message:
                await update.message.reply_text(f"ℹ️ Пользователь с ID {admin_id} не является администратором.")
            return
            
        # Удаляем администратора
        env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), '.env')
        
        # Читаем текущий файл .env
        env_content = ""
        with open(env_path, 'r', encoding='utf-8') as f:
            env_content = f.read()
            
        # Находим строку с ADMIN_USER_IDS
        lines = env_content.split('\n')
        admin_line_idx = -1
        
        for i, line in enumerate(lines):
            if line.startswith('ADMIN_USER_IDS='):
                admin_line_idx = i
                break
                
        # Удаляем ID из строки с администраторами
        if admin_line_idx >= 0:
            current_ids = lines[admin_line_idx].split('=')[1].strip().split(',')
            new_ids = [id for id in current_ids if int(id) != admin_id]
            
            if not new_ids:
                # Если не осталось администраторов, добавляем текущего пользователя
                # чтобы избежать ситуации, когда нет администраторов
                new_ids = [str(update.effective_user.id)]
                
            lines[admin_line_idx] = f"ADMIN_USER_IDS={','.join(new_ids)}"
            
            # Записываем обновленный файл
            with open(env_path, 'w', encoding='utf-8') as f:
                f.write('\n'.join(lines))
                
            # Обновляем список в памяти
            ADMIN_USER_IDS.remove(admin_id)
            
            await update.message.reply_text(
                f"✅ <b>Успешно!</b>\n\n"
                f"Пользователь с ID <code>{admin_id}</code> удален из списка администраторов.",
                parse_mode="HTML"
            )
            
            logger.info(f"User {update.effective_user.id} removed admin: {admin_id}")
        else:
            await update.message.reply_text("❌ <b>Ошибка:</b> Не удалось найти настройки администраторов.")
            
    except ValueError:
        await update.message.reply_text(
            "❌ <b>Ошибка:</b> ID пользователя должен быть целым числом.\n\n"
            "Пример использования:\n"
            "<code>/removeadmin 123456789</code>",
            parse_mode="HTML"
        )
    except Exception as e:
        logger.error(f"Error removing admin: {str(e)}")
        await update.message.reply_text(
            f"❌ <b>Произошла ошибка при удалении администратора:</b>\n\n{str(e)}",
            parse_mode="HTML"
        )

async def list_admins(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Показывает список администраторов бота
    
    Args:
        update: Объект обновления Telegram
        context: Контекст вызова
    """
    if not update.message:
        return
        
    # Проверяем, что команду выполняет администратор
    if not update.effective_user or update.effective_user.id not in ADMIN_USER_IDS:
        if update.message:
            await update.message.reply_text("⛔️ У вас нет прав для выполнения этой команды.")
        return
        
    try:
        if not ADMIN_USER_IDS:
            if update.message:
                await update.message.reply_text("⚠️ Список администраторов пуст.")
            return
            
        # Формируем сообщение со списком администраторов
        admin_list = "\n".join([f"• <code>{admin_id}</code>" for admin_id in ADMIN_USER_IDS])
        
        if update.message:
            await update.message.reply_text(
                f"👑 <b>Список администраторов бота:</b>\n\n"
                f"{admin_list}\n\n"
                f"Всего администраторов: {len(ADMIN_USER_IDS)}",
                parse_mode="HTML"
            )
        
    except Exception as e:
        logger.error(f"Error listing admins: {str(e)}")
        if update.message:
            await update.message.reply_text(
                f"❌ <b>Произошла ошибка при получении списка администраторов:</b>\n\n{str(e)}",
                parse_mode="HTML"
            )
