import requests
from requests.exceptions import ChunkedEncodingError, ConnectionError
import sys
import os
import urllib.parse
import hashlib
import subprocess
from celery.exceptions import MaxRetriesExceededError
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from celery_tasks.celery import app
from base.utils.funcs import identify_encoder_and_release, identify_quality, identify_seasons, identify_episodes, concat_ws, identify_seasons_from_irregular_filename, identify_episodes_from_irregular_filename
from base.utils import MovieoDatabase
from config import DOWNLOAD_DIR

@app.task(queue='downloads',bind=True,max_retries=5,default_retry_delay=2)
def download_from_url(self, second_step_res):
    status = second_step_res['status']
    try:
        if status:
            source = second_step_res['source']
            dl_links = second_step_res['dl_links']
            title_id = second_step_res['title_id']
            title_type = second_step_res['title_type']
            en_name = second_step_res['en_name']
            name = en_name.split('(')
            name = name[0]
            upload_list = []
            for dl_url in dl_links[0:70]:
                file_name = dl_url.split('/')[-1].split('?')[0]
                permission, quality = identify_quality(file_name)
                release_type, encoder = identify_encoder_and_release(file_name)
                if title_type == 1:
                    se = None
                    ep_s = None
                    if release_type != str():
                        release_type = f' {release_type}'
                    if encoder != str():
                        encoder = f' {encoder}'
                    if permission:
                        btn = f'📥 {quality}{release_type}{encoder}'
                        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, 1, 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)
                else:
                    se = identify_seasons(file_name)
                    if not se:
                        se = identify_seasons_from_irregular_filename(file_name)
                    permission, episodes, ep_s = identify_episodes(file_name)
                    if not permission:
                        episode = identify_episodes_from_irregular_filename(file_name)
                        permission = episodes = ep_s = episode
                    if permission:
                        if se < 10:
                            btn = urllib.parse.quote(f'📥 {name}S0{se}{episodes}')
                        else:
                            btn = urllib.parse.quote(f'📥 {name}S{se}{episodes}')
                        qu = ' '.join([p for p in [quality.strip(), release_type.strip(), encoder.strip()] if p])
                        combo_str = f"{title_id}|{se}|{1}|{qu}"
                        combo_hash = hashlib.sha256(combo_str.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:
                    new_file_name = file_name.replace('_', '.').replace('30NAMA', '').replace('30nama', '')
                    new_file_name = new_file_name.replace('_', '.').replace('-zarfilm', '').replace('-ZarFilm', '').replace('-ZARFILM', '').replace('zarfilm', '').replace('ZarFilm', '').replace('ZARFILM', '')
                    new_file_name = new_file_name.replace('_', '.').replace('EBTV', '').replace('ebtv', '').replace('empirebesttv','').replace('SoftSub','').replace('softsub','')
                    new_file_name = f'{new_file_name[0:-4]}@movieo_bot{new_file_name[-4:]}'
                    filename = f'{DOWNLOAD_DIR}{new_file_name}'
                    if not os.path.exists(filename):
                        print(f'\n***********************\nstart downloading {filename}\n***********************')
                        MAX_RETRIES = 5

                        for attempt in range(MAX_RETRIES):
                            try:
                                headers = {}
                                mode = "wb"

                                if os.path.exists(filename):
                                    size = os.path.getsize(filename)
                                    if size > 0:
                                        headers["Range"] = f"bytes={size}-"
                                        mode = "ab"
                                if source == 'zarfilm':
                                    proxies = {
                                        "http": "http://samy:samy@85.133.221.6:58871",
                                        "https": "http://samy:samy@85.133.221.6:58871"
                                    }

                                    r = requests.get(
                                        dl_url,
                                        stream=True,
                                        headers=headers,
                                        timeout=(15, 600),
                                        proxies=proxies
                                    )
                                    r.raise_for_status()
                                else:
                                    r = requests.get(
                                        dl_url,
                                        stream=True,
                                        headers=headers,
                                        timeout=(15, 600),
                                    )
                                    r.raise_for_status()
                                with open(filename, mode) as f:
                                    for chunk in r.iter_content(1024 * 1024):
                                        if chunk:
                                            f.write(chunk)
                                break

                            except (ChunkedEncodingError, ConnectionError):
                                if attempt == MAX_RETRIES - 1:
                                    raise
                        print('----- trying to remove possible soft subtitles... -----')
                        command = f"ffmpeg -i {filename} -map 0 -map -0:s -c copy {DOWNLOAD_DIR}temp_{new_file_name}"
                        subprocess.run(command, shell=True, capture_output=True, text=True)
                        os.remove(filename)
                        os.rename(f'{DOWNLOAD_DIR}temp_{new_file_name}', filename)
                    upload_list.append({filename: {'btn': btn, 'quality': quality, 'release_type': release_type.strip(), 'encoder': encoder.strip(), 'season': se, 'episode': ep_s}})
            if upload_list:
                second_step_res['status'] = True
                second_step_res['qu'] = qu
                second_step_res['combo_hash'] = combo_hash
                second_step_res['upload_list'] = upload_list
                return second_step_res
            else:
                second_step_res['status'] = False
                return second_step_res
    except MaxRetriesExceededError:
        return {'status': False}
    except Exception as exc:
        print(f"Error occurred: {exc}")
        raise self.retry(exc=exc)