import sys
import os
import asyncio
import urllib.parse
import hashlib
from hydrogram import Client
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from celery_tasks.celery import app
from config import TELEGRAM_API, SOFTSUB_DIR, THUMB_DIR, MOVIEO_TELEGRAM_API, MOVIEO_CLI, \
    HARDSUB_DIR, API_ID, API_HASH, PREMIUM_SESSION, BOT_ID, SUDO, DUBBED_DIR
from base.utils.funcs import identify_encoder_and_release,identify_quality,identify_seasons,identify_episodes,concat_ws,log_request,send_request,upload_video
from base.utils import MovieoDatabase,RedisDatabase,YOUR_REQUEST_ADDED,YOUR_REQUEST_CLOSED
from base.utils.subtitle_editor import *

def get_client():
    return Client(
        "premium_uploader",
        api_id=API_ID,
        api_hash=API_HASH,
        session_string=PREMIUM_SESSION,
        in_memory=True,
        ipv6=True
    )

async def upload_video_via_userbot(file_path, thumb_path, file_name, sec, chat_id, caption):
    async with get_client() as app:
        res = await app.send_video(
            chat_id=chat_id,
            video=file_path,
            file_name=file_name,
            thumb=thumb_path,
            duration=sec,
            caption=caption,
            supports_streaming=True
        )
        return res.id

async def upload_document_via_userbot(file_path, file_name, chat_id, caption):
    async with get_client() as app:
        res = await app.send_document(
            chat_id=chat_id,
            document=file_path,
            file_name=file_name,
            caption=caption,
        )
        return res.id


async def copy_message_via_userbot(message_id, to_chat_id, from_chat_id, caption):
    async with get_client() as app:
        await app.copy_message(
            chat_id=to_chat_id,
            from_chat_id=from_chat_id,
            message_id=message_id,
            caption=caption
        )

@app.task(queue='uploads')
def upload_video_and_submit_request(second_step_res: dict, request_id: int, request_type_str: str, title_id: int, title_type: int, title_name: str, file_name: str, file_id: str):
    status = second_step_res['status']
    if status:
        api_url = second_step_res['api_url']
        user_id = second_step_res['user_id']
        try:
            username = second_step_res['username']
        except:
            username = None
        admin_review_required = second_step_res['admin_review']
        server_file_name = second_step_res['server_file_name']
        sec = second_step_res['duration']
        caption = second_step_res['caption']

        if 'SoftSub' in request_type_str:
            folder = SOFTSUB_DIR
        elif 'HardSub' in request_type_str:
            folder = HARDSUB_DIR
        else:
            folder = DUBBED_DIR

        print(f'\n**********************\n--- {folder}{file_name} have to send to {api_url} and {user_id} user id  \n**********************')

        print(f'\n**********************\n--- uploading file to the telegram... \n**********************')
        file_size_bytes = os.path.getsize(f'{folder}{server_file_name}')
        file_size = file_size_bytes / (1024 ** 2)
        upload_with_userbot = False
        if file_size <= 1985:
            with open(f'{folder}{server_file_name}', 'rb') as video_file, open(THUMB_DIR, 'rb') as thumb:
                files = {'video': (file_name, video_file), 'thumb': thumb}
                data = {
                    'chat_id': user_id,
                    'duration': sec,
                    'caption': caption,
                    'supports_streaming': True
                }
                res = upload_video(api_url, 'sendVideo', data, files, file_name)
            movieo_file_id = res['result']['video']['file_id']
        elif file_size > 1985 and file_size <= 4000:
            try:
                loop = asyncio.get_event_loop()
            except RuntimeError:
                loop = asyncio.new_event_loop()
                asyncio.set_event_loop(loop)
            if admin_review_required:
                caption = f'send to,{user_id},{caption}'
                loop.run_until_complete(upload_video_via_userbot(f'{folder}{server_file_name}', THUMB_DIR, file_name, sec, BOT_ID, caption))
            else:
                if username:
                    userbot_message_id = loop.run_until_complete(upload_video_via_userbot(f'{folder}{server_file_name}', THUMB_DIR, file_name, sec, username, caption))
                else:
                    userbot_message_id = loop.run_until_complete(upload_video_via_userbot(f'{folder}{server_file_name}', THUMB_DIR, file_name, sec, user_id, caption))
                movieo_file_id = 'None'
            upload_with_userbot = True
        else:
            with MovieoDatabase() as db:
                user_request_db = db.get_users_requests('id',request_id,'status')
            request_status = user_request_db[0][0]
            if request_status != 3:
                chat_id, movieo_id, title_name = log_request(request_id, 3)
                data = {
                    'chat_id': chat_id,
                    'text': YOUR_REQUEST_CLOSED(request_type_str, title_name)
                }
                send_request(MOVIEO_TELEGRAM_API, 'sendMessage', data)
            exit()

        for folder in [HARDSUB_DIR, SOFTSUB_DIR, DOWNLOAD_DIR, SUBTITLE_DIR, DUBBED_DIR]:
            for filename in os.listdir(folder):
                if file_id in filename:
                    os.remove(os.path.join(folder, filename))

        if admin_review_required == None:
            pass
        elif admin_review_required:
            if not upload_with_userbot:
                data = {
                    'chat_id': SUDO[0],
                    'video': movieo_file_id,
                    'caption': caption,
                    'supports_streaming': True
                }
                send_request(TELEGRAM_API, 'sendVideo', data)

            with MovieoDatabase() as db:
                user_request_db = db.get_users_requests('id', request_id, 'season,files,status')
            season = user_request_db[0][0]
            qu = user_request_db[0][1]
            request_status = user_request_db[0][2]
            if request_status == 0:
                outer_concat = concat_ws('|', title_id, season, 1, f'{qu}')
                combo_hash = hashlib.sha256(outer_concat.encode('utf-8')).hexdigest().upper()
                with MovieoDatabase() as db:
                    db.update_admins_requests(request_id, 'status', 1)
                    db.update_users_requests(request_id, 'status', 1)
                    file_db = db.get_files('combo_hash_sha256', combo_hash, 'file_id', f'ORDER BY RAND() LIMIT 1')
                file = file_db[0][0]
                caption = f'compress_video,{request_id},{qu}'
                data = {
                    'chat_id': MOVIEO_CLI,
                    'document': file,
                    'caption': caption
                }
                send_request(MOVIEO_TELEGRAM_API, 'sendDocument', data)
        else:
            if request_type_str == 'Persian SoftSub':
                file_type_str = '(Soft Sub)'
                file_type = 2
            elif request_type_str == 'English SoftSub':
                file_type_str = '(Soft Sub)'
                file_type = 5
            elif request_type_str == 'Persian HardSub':
                file_type_str = '(Hard Sub)'
                file_type = 3
            elif request_type_str == 'English HardSub':
                file_type_str = '(Hard Sub)'
                file_type = 6

            if title_type == 1:
                se = None
                permission, quality = identify_quality(file_name)
                release_type, encoder = identify_encoder_and_release(file_name)
                if release_type != str():
                    release_type = f' {release_type}'
                if encoder != str():
                    encoder = f' {encoder}'
                if permission:
                    btn = f'📥 {quality}{release_type}{encoder} {file_type_str}'
                    btn = urllib.parse.quote(btn)
                    qu = ' '.join([p for p in [quality.strip(), release_type.strip(), encoder.strip()] if p])
                    outer_concat = concat_ws('|', title_id, None, file_type, f'{qu}')
                    combo_hash = hashlib.sha256(outer_concat.encode('utf-8')).hexdigest().upper()
                    with MovieoDatabase() as db:
                        file_db = db.get_files('combo_hash_sha256', combo_hash)
                    if not file_db:
                        caption = f'ARCHIVE_MOVIE,{title_id},{quality},{release_type.strip()},{encoder.strip()},{btn},{file_type},{movieo_file_id}'
                        if not upload_with_userbot:
                            data = {
                                'chat_id': MOVIEO_CLI,
                                'video': movieo_file_id,
                                'caption': caption
                            }
                            res = send_request(MOVIEO_TELEGRAM_API, 'sendVideo', data)
                        else:
                            try:
                                loop = asyncio.get_event_loop()
                            except RuntimeError:
                                loop = asyncio.new_event_loop()
                                asyncio.set_event_loop(loop)
                            loop.run_until_complete(copy_message_via_userbot(userbot_message_id, '@amin_morty', user_id, caption))
            else:
                se = identify_seasons(file_name)
                permission, episodes, ep_s = identify_episodes(file_name)
                if permission:
                    if se < 10:
                        btn = urllib.parse.quote(f'📥 {title_name.split("(")[0]}S0{se}{episodes} {file_type_str}')
                    else:
                        btn = urllib.parse.quote(f'📥 {title_name.split("(")[0]}S{se}{episodes} {file_type_str}')
                    permission, quality = identify_quality(file_name)
                    release_type, encoder = identify_encoder_and_release(file_name)
                    if release_type != str():
                        release_type = f' {release_type}'
                    if encoder != str():
                        encoder = f' {encoder}'
                    if permission:
                        qu = ' '.join([p for p in [quality.strip(), release_type.strip(), encoder.strip()] if p])
                        outer_concat = concat_ws('|', title_id, se, file_type, f'{qu}')
                        combo_hash = hashlib.sha256(outer_concat.encode('utf-8')).hexdigest().upper()
                        with MovieoDatabase() as db:
                            file_db = db.get_files('combo_hash_sha256', combo_hash, order=f'AND ep = "{ep_s}"')
                        if not file_db:
                            caption = f'ARCHIVE_SERIES,{title_id},{quality},{release_type.strip()},{encoder.strip()},{btn},{ep_s},{se},{file_type},{movieo_file_id}'
                            if not upload_with_userbot:
                                data = {
                                    'chat_id': MOVIEO_CLI,
                                    'video': movieo_file_id,
                                    'caption': caption
                                }
                                send_request(MOVIEO_TELEGRAM_API, 'sendVideo', data)
                            else:
                                try:
                                    loop = asyncio.get_event_loop()
                                except RuntimeError:
                                    loop = asyncio.new_event_loop()
                                    asyncio.set_event_loop(loop)
                                loop.run_until_complete(copy_message_via_userbot(userbot_message_id, '@amin_morty', user_id, caption))


            print(f'\n**********************\n--- considering the possibility of submit the request \n**********************')
            counter_key = f"request:active:{request_id}"
            lock_key = f"request:lock:{request_id}"
            with RedisDatabase() as r:
                remaining = r.decr(counter_key)
                if remaining > 0:
                    print(f'\n**********************\n--- {remaining} tasks of request has left! \n**********************')
                elif r.get(lock_key):
                    print(f'\n**********************\n--- request already handled. \n**********************')
                else:
                    r.set(lock_key, "1")
                    chat_id, movieo_id, title_name = log_request(request_id, 2)
                    data = {
                        'chat_id': chat_id,
                        'text': YOUR_REQUEST_ADDED(request_id, title_name, movieo_id)
                    }
                    send_request(MOVIEO_TELEGRAM_API, 'sendMessage', data)

    else:
        with MovieoDatabase() as db:
            user_request_db = db.get_users_requests('id', request_id, 'season,files,status')
        season = user_request_db[0][0]
        qu = user_request_db[0][1]
        request_status = user_request_db[0][2]
        if request_status == 0:
            outer_concat = concat_ws('|', title_id, season, 1, f'{qu}')
            combo_hash = hashlib.sha256(outer_concat.encode('utf-8')).hexdigest().upper()
            with MovieoDatabase() as db:
                db.update_admins_requests(request_id, 'status', 1)
                db.update_users_requests(request_id, 'status', 1)
                file_db = db.get_files('combo_hash_sha256', combo_hash, 'file_id', f'ORDER BY RAND() LIMIT 1')
            file = file_db[0][0]
            caption = f'compress_video,{request_id},{qu}'
            data = {
                'chat_id': MOVIEO_CLI,
                'document': file,
                'caption': caption
            }
            send_request(MOVIEO_TELEGRAM_API, 'sendDocument', data)

@app.task(queue='uploads')
def upload_document(upload_data: dict):
    status = upload_data['status']
    if status:
        api_url = upload_data['api_url']
        user_id = upload_data['user_id']
        try:
            username = upload_data['username']
        except:
            username = None
        upload_list = upload_data['upload_list']
        title_id = upload_data['title_id']
        title_type = upload_data['title_type']
        try:
            for item in upload_list:
                for file_path, info in item.items():
                    file_name = file_path.split('/')[-1]
                    btn = info['btn']
                    quality = info['quality']
                    release_type = info['release_type']
                    encoder = info['encoder']
                    se = info['season']
                    ep_s = info['episode']

                    print(f'\n**********************\n--- uploading file to the telegram... \n**********************')
                    file_size_bytes = os.path.getsize(f'{file_path}')
                    file_size = file_size_bytes / (1024 ** 2)
                    upload_with_userbot = False
                    if file_size <= 1985:
                        with open(f'{file_path}', 'rb') as video_file:
                            files = {'document': (file_name, video_file)}
                            data = {
                                'chat_id': user_id,
                                'caption': file_name,
                            }
                            res = upload_video(api_url, 'sendDocument', data, files, file_name)
                        movieo_file_id = res['result']['document']['file_id']
                    elif file_size > 1985 and file_size < 4000:
                        try:
                            loop = asyncio.get_event_loop()
                        except RuntimeError:
                            loop = asyncio.new_event_loop()
                            asyncio.set_event_loop(loop)
                        if username:
                            userbot_message_id = loop.run_until_complete(upload_document_via_userbot(f'{file_path}', file_name, username, file_name))
                        else:
                            userbot_message_id = loop.run_until_complete(upload_document_via_userbot(f'{file_path}', file_name, user_id, file_name))
                        movieo_file_id = 'None'
                        upload_with_userbot = True

                    if title_id:
                        if title_type == 1:
                            caption = f'ARCHIVE_MOVIE,{title_id},{quality},{release_type},{encoder},{btn},{1},{movieo_file_id}'
                        else:
                            caption = f'ARCHIVE_SERIES,{title_id},{quality},{release_type},{encoder},{btn},{ep_s},{se},{1},{movieo_file_id}'

                        if not upload_with_userbot:
                            data = {
                                'chat_id': MOVIEO_CLI,
                                'document': movieo_file_id,
                                'caption': caption
                            }
                            send_request(MOVIEO_TELEGRAM_API, 'sendDocument', data)
                        else:
                            try:
                                loop = asyncio.get_event_loop()
                            except RuntimeError:
                                loop = asyncio.new_event_loop()
                                asyncio.set_event_loop(loop)
                            loop.run_until_complete(copy_message_via_userbot(userbot_message_id, '@amin_morty', user_id, caption))
                    os.remove(file_path)
            return upload_data
        except:
            return {'status': False}
    else:
        return {'status': False}
