import logging
import sqlite3
from aiogram import Router, F, Bot
from aiogram.types import CallbackQuery, Message, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import StatesGroup, State
from db import get_user_language, get_language_text, get_button_text, add_user_balance, get_user_balance
import aiohttp
import json
import os

logger = logging.getLogger(__name__)

router = Router(name="popolnit")

# Состояния для пополнения баланса
class BalanceStates(StatesGroup):
    wait_amount = State()
    wait_payment_method = State()

# Callback данные
BACK_CB = "menu:button9"

# Загрузка API ключа из crypto_api.json
def load_cryptobot_token():
    try:
        current_dir = os.path.dirname(os.path.abspath(__file__))
        config_path = os.path.join(current_dir, 'crypto_api.json')
        print(f"Looking for config at: {config_path}")
        
        with open(config_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
            token = config.get('cryptobot_token')
            print(f"Token loaded: {token[:10]}..." if token else "Token not found")
            return token
    except Exception as e:
        logger.error(f"Ошибка загрузки crypto_api.json: {e}")
        return None

# Загружаем токен при старте
CRYPTOBOT_TOKEN = load_cryptobot_token()
CRYPTOBOT_API_URL = "https://pay.crypt.bot/api"

def get_button9_text(lang: str) -> str:
    """Получает текст кнопки назад"""
    label = "⬅️ Назад"
    try:
        from db import MENU_DB
        conn = sqlite3.connect(MENU_DB)
        cur = conn.cursor()
        cur.execute("SELECT button9 FROM language WHERE name = ?", (lang,))
        row = cur.fetchone()
        conn.close()
        if row and row[0] and str(row[0]).strip():
            label = str(row[0]).strip()
    except Exception as e:
        logger.error(f"get_button9_text error for lang={lang}: {e}")
    return label

def build_back_keyboard(lang: str) -> InlineKeyboardMarkup:
    """Создает клавиатуру с кнопкой назад"""
    return InlineKeyboardMarkup(
        inline_keyboard=[[InlineKeyboardButton(text=get_button9_text(lang), callback_data=BACK_CB)]]
    )

def build_payment_methods_keyboard(lang: str) -> InlineKeyboardMarkup:
    """Создает клавиатуру с методами оплаты"""
    button13_text = get_button_text(lang, "button13", "💳 CryptoBot")
    button14_text = get_button_text(lang, "button14", "💳 Банковская карта")
    back_text = get_button9_text(lang)
    
    return InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text=button13_text, callback_data="balance_pay:cryptobot")],
            [InlineKeyboardButton(text=button14_text, callback_data="balance_pay:card")],
            [InlineKeyboardButton(text=back_text, callback_data=BACK_CB)]
        ]
    )

async def create_balance_invoice(amount: float, description: str = "Пополнение баланса") -> dict:
    """
    Создает инвойс в CryptoBot для пополнения баланса
    """
    if not CRYPTOBOT_TOKEN:
        logger.error("CryptoBot token not loaded")
        return None
        
    url = f"{CRYPTOBOT_API_URL}/createInvoice"
    
    headers = {
        "Crypto-Pay-API-Token": CRYPTOBOT_TOKEN,
        "Content-Type": "application/json"
    }
    
    data = {
        "asset": "USDT",
        "amount": str(amount),
        "description": description,
        "paid_btn_name": "viewItem",
        "paid_btn_url": "https://t.me/your_bot",
        "allow_comments": False,
        "allow_anonymous": False,
        "expires_in": 3600
    }
    
    print(f"Creating balance invoice for amount: {amount}")
    
    try:
        async with aiohttp.ClientSession() as session:
            async with session.post(url, headers=headers, json=data) as response:
                result = await response.json()
                print(f"CryptoBot API response: {result}")
                if result.get("ok"):
                    return result.get("result")
                else:
                    logger.error(f"CryptoBot API error: {result}")
                    return None
    except Exception as e:
        logger.error(f"CryptoBot request error: {e}")
        return None

async def check_balance_invoice(invoice_id: int) -> dict:
    """
    Проверяет статус инвойса в CryptoBot для пополнения баланса
    """
    if not CRYPTOBOT_TOKEN:
        logger.error("CryptoBot token not loaded")
        return None
        
    url = f"{CRYPTOBOT_API_URL}/getInvoices"
    
    headers = {
        "Crypto-Pay-API-Token": CRYPTOBOT_TOKEN
    }
    
    params = {
        "invoice_ids": str(invoice_id),
        "count": 1
    }
    
    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers, params=params) as response:
                result = await response.json()
                print(f"Check balance invoice response: {result}")
                if result.get("ok") and result.get("result", {}).get("items"):
                    return result["result"]["items"][0]
                else:
                    return None
    except Exception as e:
        logger.error(f"CryptoBot check invoice error: {e}")
        return None

def build_balance_payment_keyboard(lang: str, invoice_url: str) -> InlineKeyboardMarkup:
    """
    Создает клавиатуру с кнопками оплаты и проверки для пополнения баланса
    """
    pay_button_text = get_button_text(lang, "button17", "💳 Оплатить")
    check_button_text = get_button_text(lang, "button15", "✅ Проверить оплату")
    
    keyboard = InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text=pay_button_text, url=invoice_url)],
            [InlineKeyboardButton(text=check_button_text, callback_data="balance_check_crypto")],
            [InlineKeyboardButton(text=get_button9_text(lang), callback_data=BACK_CB)]
        ]
    )
    
    return keyboard

def get_referrer_id(user_id: int) -> int | None:
    """
    Получает ID реферера (пригласившего) пользователя
    """
    try:
        conn = sqlite3.connect('data.db')
        cur = conn.cursor()
        cur.execute("SELECT gen_referal_user_id FROM referals WHERE referals_user_id = ?", (user_id,))
        row = cur.fetchone()
        conn.close()
        if row and row[0]:
            return int(row[0])
        return None
    except Exception as e:
        logger.error(f"Error getting referrer for user {user_id}: {e}")
        return None

def add_referral_bonus(referrer_id: int, amount: float) -> bool:
    """
    Начисляет 10% бонус рефереру от суммы пополнения
    """
    try:
        bonus_amount = amount * 0.10  # 10% от суммы пополнения
        conn = sqlite3.connect('data.db')
        cur = conn.cursor()
        
        # Обновляем баланс реферера
        cur.execute("UPDATE users SET balance = balance + ?, referal_balance = referal_balance + ? WHERE user_id = ?", 
                   (bonus_amount, bonus_amount, referrer_id))
        
        conn.commit()
        conn.close()
        
        logger.info(f"Referral bonus added: user {referrer_id} +{bonus_amount}$ (10% from {amount}$)")
        return True
    except Exception as e:
        logger.error(f"Error adding referral bonus to user {referrer_id}: {e}")
        return False

@router.callback_query(F.data == "menu:button8")
async def open_balance_topup(cb: CallbackQuery, state: FSMContext):
    """
    Открывает меню пополнения баланса (button8)
    """
    user_id = cb.from_user.id
    lang = get_user_language(user_id)
    
    # Получаем текст вопроса из text24
    text24 = get_language_text(lang, "text24") or "Введите сумму для пополнения баланса (минимум 1$):"
    
    try:
        await cb.message.delete()
    except Exception:
        pass
    
    # Отправляем вопрос с кнопкой назад
    await cb.message.answer(text24, reply_markup=build_back_keyboard(lang))
    
    # Устанавливаем состояние ожидания суммы
    await state.set_state(BalanceStates.wait_amount)
    await cb.answer()

@router.message(BalanceStates.wait_amount)
async def handle_amount_input(message: Message, state: FSMContext):
    """
    Обрабатывает ввод суммы для пополнения
    """
    user_id = message.from_user.id
    lang = get_user_language(user_id)
    
    try:
        # Пытаемся преобразовать введенный текст в число
        amount = float(message.text.strip())
        
        # Проверяем минимальную сумму
        if amount < 1:
            error_text = "Минимальная сумма пополнения - 1$"
            await message.answer(error_text, reply_markup=build_back_keyboard(lang))
            return
            
        # Сохраняем сумму в состоянии
        await state.update_data(amount=amount)
        
        # Получаем текст из text25
        text25 = get_language_text(lang, "text25") or "Выберите способ оплаты:"
        
        # Показываем методы оплаты
        await message.answer(text25, reply_markup=build_payment_methods_keyboard(lang))
        
        # Переходим в состояние выбора метода оплаты
        await state.set_state(BalanceStates.wait_payment_method)
        
    except ValueError:
        # Если введено не число
        error_text = "Пожалуйста, введите число (например: 10.5)"
        await message.answer(error_text, reply_markup=build_back_keyboard(lang))
    except Exception as e:
        logger.error(f"Error handling amount input: {e}")
        error_text = "Произошла ошибка. Попробуйте снова."
        await message.answer(error_text, reply_markup=build_back_keyboard(lang))

@router.callback_query(F.data == "balance_pay:cryptobot")
async def handle_balance_cryptobot(cb: CallbackQuery, state: FSMContext):
    """
    Обработчик выбора CryptoBot для пополнения баланса
    """
    user_id = cb.from_user.id
    lang = get_user_language(user_id)
    
    # Получаем сумму из состояния
    state_data = await state.get_data()
    amount = state_data.get('amount', 0)
    
    if amount <= 0:
        await cb.answer("Ошибка: неверная сумма", show_alert=True)
        return
    
    try:
        await cb.message.delete()
    except Exception:
        pass
    
    # Создаем инвойс для пополнения баланса
    invoice = await create_balance_invoice(
        amount=amount,
        description=f"Пополнение баланса на {amount}$"
    )
    
    if not invoice or not invoice.get('pay_url'):
        error_text = "Ошибка: не удалось создать инвойс для пополнения"
        await cb.message.answer(error_text)
        await cb.answer()
        return
    
    print(f"Balance topup invoice created: {invoice['invoice_id']}, URL: {invoice['pay_url']}")
    
    # Сохраняем ID инвойса и сумму в состоянии для будущей проверки
    await state.update_data(
        balance_invoice_id=invoice['invoice_id'],
        balance_amount=amount
    )
    
    # Формируем текст сообщения
    amount_text = f"Оплатите {amount}$ USDT для пополнения баланса"
    description_text = "Для оплаты нажмите кнопку ниже:"
    
    payment_text = f"{amount_text}\n\n{description_text}"
    
    # Создаем клавиатуру с кнопками
    keyboard = build_balance_payment_keyboard(lang, invoice['pay_url'])
    
    payment_message = await cb.message.answer(payment_text, reply_markup=keyboard)
    
    # Сохраняем ID сообщения с оплатой для удаления при проверке
    await state.update_data(balance_payment_message_id=payment_message.message_id)
    
    await cb.answer()

@router.callback_query(F.data == "balance_pay:card")
async def handle_balance_card(cb: CallbackQuery, state: FSMContext):
    """
    Обработчик выбора банковской карты для пополнения баланса
    """
    user_id = cb.from_user.id
    lang = get_user_language(user_id)
    
    # Получаем сумму из состояния
    state_data = await state.get_data()
    amount = state_data.get('amount', 0)
    
    if amount <= 0:
        await cb.answer("Ошибка: неверная сумма", show_alert=True)
        return
    
    try:
        await cb.message.delete()
    except Exception:
        pass
    
    # Показываем text26 с информацией о пополнении (без фактического пополнения баланса)
    text26 = get_language_text(lang, "text26") or "Для пополнения баланса следуйте инструкциям..."
    info_message = f"{text26}\n\nСумма пополнения: {amount}$"
    
    await cb.message.answer(info_message, reply_markup=build_back_keyboard(lang))
    print(f"Card payment selected for balance topup: user {user_id}, amount: {amount}$")
    
    # Очищаем состояние
    await state.clear()
    await cb.answer()

@router.callback_query(F.data == "balance_check_crypto")
async def handle_balance_crypto_check(cb: CallbackQuery, state: FSMContext, bot: Bot):
    """
    Обработчик проверки оплаты CryptoBot для пополнения баланса
    """
    user_id = cb.from_user.id
    lang = get_user_language(user_id)
    
    print(f"=== BALANCE CRYPTO CHECK ===")
    print(f"User: {user_id}")
    
    # Получаем данные из состояния
    state_data = await state.get_data()
    invoice_id = state_data.get('balance_invoice_id')
    amount = state_data.get('balance_amount', 0)
    payment_message_id = state_data.get('balance_payment_message_id')
    
    print(f"Invoice ID: {invoice_id}, Amount: {amount}")
    
    # Удаляем сообщение с оплатой
    try:
        if payment_message_id:
            await bot.delete_message(chat_id=cb.message.chat.id, message_id=payment_message_id)
            print(f"Deleted payment message: {payment_message_id}")
        else:
            await cb.message.delete()
            print("Deleted current message")
    except Exception as e:
        print(f"Error deleting payment message: {e}")
    
    if not invoice_id:
        # Если нет invoice_id в состоянии
        error_text = get_language_text(lang, "text16") or "Оплата не прошла"
        await cb.message.answer(error_text, reply_markup=build_back_keyboard(lang))
        print("No invoice ID in state")
        return
    
    # Проверяем статус инвойса
    invoice_data = await check_balance_invoice(invoice_id)
    
    if not invoice_data:
        error_text = get_language_text(lang, "text16") or "Оплата не прошла"
        await cb.message.answer(error_text, reply_markup=build_back_keyboard(lang))
        print("Invoice check failed")
        return
    
    status = invoice_data.get('status', 'active')
    print(f"Invoice status: {status}")
    
    if status == 'paid':
        # ПОПОЛНЯЕМ БАЛАНС пользователя
        balance_updated = add_user_balance(user_id, amount)
        
        if balance_updated:
            # Получаем обновленный баланс
            new_balance = get_user_balance(user_id)
            
            # Проверяем есть ли у пользователя реферер
            referrer_id = get_referrer_id(user_id)
            if referrer_id:
                # Начисляем 10% бонус рефереру
                bonus_added = add_referral_bonus(referrer_id, amount)
                if bonus_added:
                    print(f"Referral bonus added: {referrer_id} got 10% from {amount}$")
                else:
                    print(f"Failed to add referral bonus to {referrer_id}")
            
            # Показываем text26 с информацией о пополнении
            text26 = get_language_text(lang, "text26") or "Баланс успешно пополнен!"
            success_message = f"{text26}\n\nПополнено: {amount}$\nТекущий баланс: {new_balance}$"
            
            await cb.message.answer(success_message, reply_markup=build_back_keyboard(lang))
            print(f"Balance topped up via CryptoBot: user {user_id} +{amount}$, new balance: {new_balance}$")
        else:
            error_text = "Ошибка пополнения баланса"
            await cb.message.answer(error_text, reply_markup=build_back_keyboard(lang))
    else:
        error_text = get_language_text(lang, "text16") or "Оплата не прошла"
        await cb.message.answer(error_text, reply_markup=build_back_keyboard(lang))
        print(f"Payment not completed (status: {status})")
    
    # Очищаем состояние после проверки
    await state.clear()
    await cb.answer()