from telethon.events import StopPropagation
from telethon import events, Button
import random, os, re

from utils.functions import reset_numbers, convert_to_sticker, convert_status
from utils.database import Settings, redis
from utils.client import client, connect


@client.on(events.NewMessage())
@client.on(events.CallbackQuery())
async def check_bot(event):
    user = await event.get_sender()
    
    if Settings.get().bot_status == False and user.id != int(os.getenv('OWNER')):
        await (event.edit if hasattr(event, 'data') else event.reply)('<b>⚠️ The bot is temporarily turned off.</b>')
        raise StopPropagation


@client.on(events.NewMessage(pattern=r'^/start$'))
async def start(event):
    user = await event.get_sender()
    redis.set(f'step:{user.id}', 'none')
    await event.reply('<b>👋 Hey, your welcome to the Resetter Bot.\n\n🔽 Send your numbers with .txt file or manual (/format):</b>')


@client.on(events.NewMessage(pattern=r'^/format$'))
async def format(event):
    await event.reply('<b>🔖 Correct format (file or manual):\n\n• phone_number|api_url\n• phone_number-api_url</b>')


@client.on(events.NewMessage(pattern=r'^/settings$'))
@client.on(events.CallbackQuery(pattern=r'^back$'))
async def settings(event):
    user = await event.get_sender()
    
    await (event.edit if hasattr(event, 'data') else event.reply)(
        f'<b>⚙️ You can change your current settings here.\n\n'
        
        f'• Bot Status: <code>{convert_to_sticker(Settings.get().bot_status)}</code>\n'
        f'• Reset Status: <code>{convert_to_sticker(Settings.get().reset_status)}</code>\n\n'
        
        f'• Proxy Status: <code>{convert_to_sticker(Settings.get().proxy_status)}</code>\n'
        f'• Password Status: <code>{convert_to_sticker(Settings.get().password_status)}</code>\n\n'
        
        f'• Password: <code>{(Settings.get().password if Settings.get().password is not None else "Not Setted")}</code>\n'
        
        f'\n<b>🔄 Use /settings to change your settings.</b>'
        f'</b>',
        buttons = [
            [Button.inline(f'{convert_status(Settings.get().proxy_status)} Proxy', data='change_proxy_status'), Button.inline(f'📥️️️️️️ Upload new proxies' if Settings.get().proxy_status else '', data='upload_proxies')],
            [Button.inline(f'{convert_status(Settings.get().password_status)} Password', data='change_password_status'), Button.inline(f'🔑 Set password' if Settings.get().password_status else '', data='set_password')],
            [Button.inline(f'{convert_status(Settings.get().bot_status)} Bot' if user.id == int(os.getenv('OWNER')) else '', data='change_bot_status'), Button.inline(f'{convert_status(Settings.get().reset_status)} Reset' if user.id == int(os.getenv('OWNER')) else '', data='change_reset_status')],
            [Button.url('📞 Support', url='https://t.me/omidamiri2019')]
        ]
    )


@client.on(events.CallbackQuery(pattern=r'^change_(.*)$'))
async def settings(event):
    user = await event.get_sender()
    
    method = event.pattern_match.group(1).decode('utf-8')
    
    toggle_settings = {
        'proxy_status': 'proxy_status',
        'reset_status': 'reset_status',
        'bot_status': 'bot_status',
        'password_status': 'password_status',
    }
    
    if method in toggle_settings:
        setting_name = toggle_settings[method]
        Settings.update(**{setting_name: not getattr(Settings.get(), setting_name)}).execute()
        
        await (event.edit if hasattr(event, 'data') else event.reply)(
            f'<b>⚙️ You can change your current settings here.\n\n'
        
            f'• Bot Status: <code>{convert_to_sticker(Settings.get().bot_status)}</code>\n'
            f'• Reset Status: <code>{convert_to_sticker(Settings.get().reset_status)}</code>\n\n'
            
            f'• Proxy Status: <code>{convert_to_sticker(Settings.get().proxy_status)}</code>\n'
            f'• Password Status: <code>{convert_to_sticker(Settings.get().password_status)}</code>\n\n'
            
            f'• Password: <code>{(Settings.get().password if Settings.get().password is not None else "Not Setted")}</code>\n'
            
            f'\n<b>🔄 Use /settings to change your settings.</b>'
            f'</b>',
            buttons = [
                [Button.inline(f'{convert_status(Settings.get().proxy_status)} Proxy', data='change_proxy_status'), Button.inline(f'📥️️️️️️ Upload new proxies' if Settings.get().proxy_status else '', data='upload_proxies')],
                [Button.inline(f'{convert_status(Settings.get().password_status)} Password', data='change_password_status'), Button.inline(f'🔑 Set password' if Settings.get().password_status else '', data='set_password')],
                [Button.inline(f'{convert_status(Settings.get().bot_status)} Bot' if user.id == int(os.getenv('OWNER')) else '', data='change_bot_status'), Button.inline(f'{convert_status(Settings.get().reset_status)} Reset' if user.id == int(os.getenv('OWNER')) else '', data='change_reset_status')],
                [Button.url('📞 Support', url='https://t.me/omidamiri2019')]
            ]
        )


@client.on(events.CallbackQuery(pattern=r'^upload_proxies$'))
async def upload_proxies(event):
    user = await event.get_sender()
    
    redis.set(f'step:{user.id}', 'upload_proxies')
    
    await event.edit(
        '<b>📁 Send your proxy file with correct format (.txt):</b>',
        buttons = [
            [Button.inline('🔙 back', data='back')]
        ]
    )


@client.on(events.NewMessage(func=lambda e: e.file and e.file.name.endswith('.txt') and redis.get(f'step:{e.sender_id}').decode() == 'upload_proxies'))
async def upload_proxies(event):
    user = await event.get_sender()
    
    wait = await event.reply(f'<b>⏱ Please wait few second ...</b>')
    
    await event.download_media(file='utils/proxies.txt')
    redis.set(f'step:{user.id}', 'none')
    
    await wait.edit(
        f'<b>✅️️️️️️️ New proxies successfully uploaded in server.</b>',
        buttons = [
            [Button.inline('⚙️ Settings', data='back')]
        ]
    )
    
    raise StopPropagation


@client.on(events.CallbackQuery(pattern=r'^set_password$'))
async def set_password(event):
    user = await event.get_sender()
    
    redis.set(f'step:{user.id}', 'set_password')
    
    await event.edit(
        '<b>🔑 Send your 2FA password:</b>',
        buttons = [
            [Button.inline('🔙 back', data='back')]
        ]
    )


@client.on(events.NewMessage(func=lambda e: redis.get(f'step:{e.sender_id}').decode() == 'set_password'))
async def set_password(event):
    user = await event.get_sender()
    
    wait = await event.reply(f'<b>⏱ Please wait few second ...</b>')
    
    Settings.update(password = event.raw_text).execute()
    redis.set(f'step:{user.id}', 'none')
    
    await wait.edit(
        f'<b>✅️️️️️️️ New password (2FA) successfully setted.</b>',
        buttons = [
            [Button.inline('⚙️ Settings', data='back')]
        ]
    )
    
    raise StopPropagation


@client.on(events.NewMessage(func=lambda e: e.is_private and any(re.search(r'\+?\d[\d\s\-()]{9,}', line) for line in e.text.splitlines())))
async def reset(event):
    user = await event.get_sender()
    
    if Settings.get().reset_status == False and user.id != int(os.getenv('OWNER')):
        await event.reply('<b>⚠️ Reset accounts is temporarily turned off.</b>')
        raise StopPropagation
    
    unique_numbers = {}
    for line in event.text.splitlines():
        line = line.strip()
        line = re.sub(r'(\||\-)<a href="([^"]+)">.*?</a>', r'\1\2', line)
        
        if line:
            phone = line
        
            phone = phone.strip()

            if phone.startswith('1') and not phone.startswith('+'):
                phone_number = '+1' + phone[1:]
            elif not phone.startswith('+'):
                phone_number = '+' + phone
            else:
                phone_number = phone

            if phone_number.startswith('+'):
                unique_numbers[phone_number] = None

    phone_numbers = list(unique_numbers.keys())
    
    wait = await event.reply('<b>⏳ Please wait a moment ...</b>')
    
    process_message = await wait.edit(f'<b>✅ File analyzed, resetting ...\n\n• Total Numbers: <code>{len(phone_numbers)}</code>\n• Processed: <code>0/{len(phone_numbers)}</code></b>')
    
    #random.shuffle(phone_numbers)
    
    await reset_numbers(user_id=event.sender.id, accounts=phone_numbers, process_message=process_message)
    
    files = [
        f'({user.id})-(success-reset-email).txt', f'({user.id})-(unsuccess-reset-email).txt',
        f'({user.id})-(success-reset-2fa).txt', f'({user.id})-(unsuccess-reset-2fa).txt',
        f'({user.id})-(not-found-verifaction-code).txt', f'({user.id})-(unsuccess-sms).txt',
        f'({user.id})-(banned).txt', f'({user.id})-(flooded).txt', f'({user.id})-(unknow).txt',
        f'({user.id})-(unsuccess-email-code).txt', f'({user.id})-(unsuccess-setup-email).txt',
        f'({user.id})-(sessions).zip'
    ]
    for file in files:
        if os.path.exists(file):
            await event.reply(file = file)
            os.unlink(file)


@client.on(events.NewMessage(func=lambda e: e.is_private and e.file and e.file.name.endswith('.txt')))
async def reset(event):
    user = await event.get_sender()
    
    if Settings.get().reset_status == False and user.id != int(os.getenv('OWNER')):
        await event.reply('<b>⚠️ Reset accounts is temporarily turned off.</b>')
        raise StopPropagation
    
    wait = await event.reply('<b>⏳ Please wait a moment ...</b>')
    
    file = await event.download_media()
    
    unique_numbers = {}
    with open(file, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            line = re.sub(r'(\||\-)<a href="([^"]+)">.*?</a>', r'\1\2', line)
            
            if line:
                phone = line

                if phone.startswith('1') and not phone.startswith('+'):
                    phone_number = '+1' + phone[1:]
                elif not phone.startswith('+'):
                    phone_number = '+' + phone
                else:
                    phone_number = phone

                if phone_number.startswith('+'):
                    unique_numbers[phone_number] = None
    os.remove(file)
    
    phone_numbers = list(unique_numbers.keys())
    
    process_message = await wait.edit(f'<b>✅ File analyzed, resetting ...\n\n• Total Numbers: <code>{len(phone_numbers)}</code>\n• Processed: <code>0/{len(phone_numbers)}</code></b>')
    
    #random.shuffle(phone_numbers)
    
    await reset_numbers(user_id=event.sender.id, accounts=phone_numbers, process_message=process_message)
    
    files = [
        f'({user.id})-(success-reset-email).txt', f'({user.id})-(unsuccess-reset-email).txt',
        f'({user.id})-(success-reset-2fa).txt', f'({user.id})-(unsuccess-reset-2fa).txt',
        f'({user.id})-(not-found-verifaction-code).txt', f'({user.id})-(unsuccess-sms).txt',
        f'({user.id})-(unsuccess-email-code).txt', f'({user.id})-(unsuccess-setup-email).txt',
        f'({user.id})-(banned).txt', f'({user.id})-(flooded).txt', f'({user.id})-(unknow).txt',
        f'({user.id})-(sessions).zip'
    ]
    for file in files:
        if os.path.exists(file):
            await event.reply(file = file)
            os.unlink(file)


connect()
