import random
import re
import urllib3
import requests

from . import helpers, ai, config
from .imdb import imdb
from bs4 import BeautifulSoup
from collections import defaultdict
from datetime import datetime
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies = helpers.get_proxies()
post_ids = helpers.read_json_file('ids')
themoviedb_ids = helpers.read_json_file('themoviedb')
_overrides = helpers.read_json_file('overrides')
session = requests.Session()


def login2():
    login_url = 'https://teamlink.top/download.php'

    username = '8w9fsybw'
    password = '1375'

    headers = {
        "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
        "Referer": 'https://teamlink.top/download.php'
    }

    data = {
        "username": username,
        "password": password,
        "login": 'ورود'
    }

    login_response = session.post(login_url, headers=headers, data=data)
    if 'اشتراک ویژه' in login_response.text:
        print('Login failed')
    else:
        print('Login successful!')


def login():
    login_url = 'https://clink5202.top/download.php'

    username = '8w9fsybw'
    password = '1375'

    headers = {
        "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
        "Referer": 'https://clink5202.top/download.php'
    }

    data = {
        "username": username,
        "password": password,
        "login": 'ورود'
    }

    login_response = session.post(login_url, headers=headers, data=data)
    if 'اشتراک ویژه' in login_response.text:
        print('Login failed')
    else:
        print('Login successful!')


login2()
login()


def has_subtitle_keyword(link: str) -> bool:
    link_lower = link.lower()
    return any(keyword.lower() in link_lower for keyword in config.subtitle_keywords)


def safe_get(url, retries=5, connect_timeout=30, read_timeout=120, verify_ssl=False):
    # _session = requests.Session()

    retry_strategy = Retry(
        total=retries,
        backoff_factor=2,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["HEAD", "GET", "OPTIONS"]
    )
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("http://", adapter)
    session.mount("https://", adapter)

    headers = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/127.0 Safari/537.36"
        )
    }

    try:
        response = session.get(
            url,
            headers=headers,
            timeout=(connect_timeout, read_timeout),
            verify=verify_ssl
        )
        response.raise_for_status()
        return response
    except requests.exceptions.ConnectTimeout:
        print(f"[Timeout] Connection to {url} failed.")
    except requests.exceptions.ReadTimeout:
        print(f"[Timeout] Server took too long to send data from {url}.")
    except requests.exceptions.SSLError:
        print(f"[SSL Error] Problem with SSL certificate at {url}.")
    except requests.exceptions.RequestException as e:
        print(f"[Error] {e}")

    return None


def get_pages():
    url = config.api_url

    error = False

    for i in range(0, 4):

        error = True

        proxy = random.choice(proxies)

        try:

            if config.proxy_enabled:

                response = requests.get(url, proxies=proxy)

            else:

                response = requests.get(url)

            if response.status_code != 200:
                print('page error code: {}'.format(response.status_code))

                continue

            error = False

            break


        except Exception as e:

            print(e)

    if error:
        print('get_pages passed 4 time try')

        exit(1)

    soup = BeautifulSoup(response.text, 'html.parser')

    match = re.search(r'/(\d+)', soup.find(class_='pagenavi').find(class_='last').attrs['href'])

    if match:

        total_pages = int(match.group(1))
    else:

        print('Total number of pages not found.')

        exit(1)

    pages = []

    total_pages = total_pages + 1

    for page_number in range(config.start_page, total_pages):

        if page_number == 1:

            pages.append(url)

        else:

            pages.append('{}page/{}/'.format(url, page_number))

    return pages


def get_posts(url):
    error = False

    for i in range(0, 4):

        error = True

        proxy = random.choice(proxies)

        try:

            if config.proxy_enabled:

                response = requests.get(url, proxies=proxy)

            else:

                response = requests.get(url)

            if response.status_code != 200:
                print('posts error code: {}'.format(response.status_code))

                continue

            error = False

            break


        except Exception as e:

            print(e)

    if error:
        print('get_posts passed 4 time try')

        return []

    soup = BeautifulSoup(response.text, 'html.parser')

    posts = []

    for post in soup.find_all(class_='posts'):
        posts.append({
            'title': post.find('h2').find('a').text.strip(),
            'href': post.find(class_='more').attrs['href'],
        })

    return posts


def get_post_raw_links(url):
    error = False

    for i in range(0, 4):

        error = True

        proxy = random.choice(proxies)

        try:

            if config.proxy_enabled:

                response = requests.get(url, proxies=proxy)

            else:

                response = requests.get(url)

            if response.status_code != 200:
                print('post error code: {}'.format(response.status_code))

                continue

            error = False

            break


        except Exception as e:

            print(e)

    if error:
        print('get_post passed 4 time try')

        return {}

    soup = BeautifulSoup(response.text, 'html.parser')

    raw_download_links = []

    for element in soup.find(class_='posts').find(class_='body').find_all('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if not is_link_valid(link):
            continue

        raw_download_links.append(link)

    # directory links
    for element in soup.find(class_='posts').find(class_='body').find_all('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if ('.mkv' not in link and '.mp4' not in link) and 'download.php' in link:
            raw_download_links.extend(get_directory_links(link))

    return raw_download_links


def get_post(url):
    error = False

    for i in range(0, 4):

        error = True

        proxy = random.choice(proxies)

        try:

            if config.proxy_enabled:

                response = requests.get(url, proxies=proxy)

            else:

                response = requests.get(url)

            if response.status_code != 200:
                print('post error code: {}'.format(response.status_code))

                continue

            error = False

            break


        except Exception as e:

            print(e)

    if error:
        print('get_post passed 4 time try')

        return {}

    soup = BeautifulSoup(response.text, 'html.parser')

    post = soup.find(class_='posts')

    script_content = soup.find('script', id="wp-postviews-cache-js-extra").string
    match = re.search(r'"post_id":"(\d+)"', script_content)
    post_id = match.group(1) if match else None

    imdb_id = ''

    type = 'series'
    ai_data = {}
    once = False

    if post_ids.get(post_id):
        imdb_id = post_ids.get(post_id)
        if 'فیلم' in post.text:
            type = 'movies'
    else:
        once = True
        ai_data = ai.get_post_data(post.text)

        if not ai_data.get('type'):
            return {'post_id': post_id, 'imdb_id': ''}

        type = ai_data.get('type')

    image = post.find('img', attrs={"decoding": "async"}).attrs['src'].strip()

    en_title = ai_data.get('tr_title')
    fa_title = ai_data.get('fa_title')
    update_date = ai_data.get('date')
    release_date = ai_data.get('release_date')
    genres = ai_data.get('genres')
    directors = ai_data.get('directors')
    fa_summary = ai_data.get('fa_summary')

    comments = get_comments(soup)

    broadcast_days = {
        'Saturday': '',
        'Sunday': '',
        'Monday': '',
        'Tuesday': '',
        'Wednesday': '',
        'Thursday': '',
        'Friday': ''
    }

    for key, value in broadcast_days.items():

        if key in ai_data.get('broadcast_days', []):
            broadcast_days[key] = 'on'

    if en_title:
        imdb_id = imdb.find_id_by_title(en_title)

    if type == 'movies':
        post_title = 'فیلم ترکی {}'.format(en_title)
    else:
        post_title = 'سریال ترکی {}'.format(en_title)

    if not imdb_id:
        return {'post_id': post_id, 'imdb_id': ''}

    if type in ['فیلم', 'movie', 'film', 'movies', 'ceremony', 'special', 'event']:
        type = 'movies'

    elif type in ['سریال', 'serie', 'series']:
        type = 'series'

    data = {
        'once': once,
        'post_id': post_id,
        'type': type,
        'post_title': post_title,
        'title': en_title,
        'fa_title': fa_title,
        'image': image,
        'imdb_id': imdb_id,
        'genres': genres,
        'update_date': update_date,
        'has_dubbed': '0',
        'has_subtitle': '0',
        'broadcast_days': broadcast_days,
        'fa_summary': fa_summary,
        'en_summary': '',
        'background_image': '',
        'release': '',
        'rating': '',
        'metacritic_rate': '',
        'actors': [],
        'directors': [],
        'votes': '',
        'age': '',
        'rank': '',
        'awards': '',
        'trailer': '',
        'comments': comments,
        'download_links': [],
        'raw_download_links': []
    }

    if imdb_id:
        if post_ids.get(post_id):

            imdb_info = imdb.get_info(imdb_id, disable_actors=True, disable_translate=True)

            print(imdb_info)

            data['trailer'] = imdb_info['trailer']

        else:
            imdb_info = imdb.get_info(imdb_id)

            if imdb_info:

                themoviedb_info = get_themoviedb_info_by_imdb_id(imdb_id)

                if themoviedb_info:
                    data['background_image'] = themoviedb_info['background_image']
                    # data['trailer'] = themoviedb_info['trailer']

                data['image'] = imdb_info['image']
                data['rating'] = imdb_info['rating']
                data['metacritic_rate'] = imdb_info['metacritic_rate']
                data['summary'] = imdb_info['summary']
                data['actors'] = imdb_info['actors']
                data['directors'] = imdb_info['directors']
                data['votes'] = imdb_info['votes']
                data['rank'] = imdb_info['rank']
                data['en_summary'] = imdb_info['summary']
                data['age'] = imdb_info['age']
                data['awards'] = imdb_info['awards']
                data['runtime'] = imdb_info['runtime']
                data['release'] = imdb_info['release']
                data['trailer'] = imdb_info['trailer']

                if not data['genres']:
                    data['genres'] = imdb_info['genres']

    if not data['directors']:
        data['directors'] = directors

    if not data['release']:
        data['release'] = release_date

    for element in soup.find(class_='posts').find(class_='body').find_all('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if not is_link_valid(link):
            continue

        passed = False

        for exclude_key in config.link_exclude_keywords:

            if exclude_key.lower() in link.lower():
                passed = True

        if passed:
            continue

        data['raw_download_links'].append(link)

        # directory links
    for element in soup.find(class_='posts').find(class_='body').find_all('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if '.zip' in link:
            continue

        if ('.mkv' not in link and '.mp4' not in link) and 'download.php' in link:
            print(link)

            data['raw_download_links'].extend(get_directory_links(link))

    if type == 'series':
        data['download_links'] = sort_serie_links(data['raw_download_links'])

    elif type == 'movies':
        data['download_links'] = sort_movie_links(data['raw_download_links'])

    if not data['raw_download_links']:
        print(url)

        print('no link found')

    data['has_dubbed'] = links_dub_type(type, data['download_links'])
    data['has_subtitle'] = links_sub_type(type, data['download_links'])

    return data


def get_post_imdb(url, imdb_id):
    error = False

    print('get post using get_post_imdb method imdb id:{}'.format(imdb_id))

    for i in range(0, 4):

        error = True

        proxy = random.choice(proxies)

        try:

            if config.proxy_enabled:

                response = requests.get(url, proxies=proxy)

            else:

                response = requests.get(url)

            if response.status_code != 200:
                print('post error code: {}'.format(response.status_code))

                continue

            error = False

            break


        except Exception as e:

            print(e)

    if error:
        print('get_post_imdb passed 4 time try')

        return {}

    soup = BeautifulSoup(response.text, 'html.parser')

    post = soup.find(class_='posts')

    script_content = soup.find('script', id="wp-postviews-cache-js-extra").string
    match = re.search(r'"post_id":"(\d+)"', script_content)
    post_id = match.group(1) if match else None

    once = True
    ai_data = ai.get_post_data(post.text)
    type = ai_data.get('type')

    image = post.find('img', attrs={"decoding": "async"}).attrs['src'].strip()

    en_title = ai_data.get('tr_title')
    fa_title = ai_data.get('fa_title')
    update_date = ai_data.get('date')
    release_date = ai_data.get('release_date')
    genres = ai_data.get('genres')
    directors = ai_data.get('directors')
    fa_summary = ai_data.get('fa_summary')
    comments = get_comments(soup)

    broadcast_days = {
        'Saturday': '',
        'Sunday': '',
        'Monday': '',
        'Tuesday': '',
        'Wednesday': '',
        'Thursday': '',
        'Friday': ''
    }

    for key, value in broadcast_days.items():

        if key in ai_data.get('broadcast_days', []):
            broadcast_days[key] = 'on'

    if type == 'movies':
        post_title = 'فیلم ترکی {}'.format(en_title)
    else:
        post_title = 'سریال ترکی {}'.format(en_title)

    if type in ['فیلم', 'movie', 'film', 'movies', 'ceremony', 'special', 'event']:
        type = 'movies'

    elif type in ['سریال', 'serie', 'series']:
        type = 'series'

    data = {
        'once': once,
        'post_id': post_id,
        'type': type,
        'post_title': post_title,
        'title': en_title,
        'fa_title': fa_title,
        'image': image,
        'imdb_id': imdb_id,
        'genres': genres,
        'update_date': update_date,
        'has_dubbed': '0',
        'has_subtitle': '0',
        'broadcast_days': broadcast_days,
        'fa_summary': fa_summary,
        'en_summary': '',
        'background_image': '',
        'release': '',
        'rating': '',
        'metacritic_rate': '',
        'actors': [],
        'directors': [],
        'votes': '',
        'age': '',
        'rank': '',
        'awards': '',
        'trailer': '',
        'comments': comments,
        'download_links': [],
        'raw_download_links': []
    }

    if imdb_id:
        if post_ids.get(post_id):

            imdb_info = imdb.get_info(imdb_id, disable_actors=True, disable_translate=True)

            data['trailer'] = imdb_info['trailer']

        else:
            imdb_info = imdb.get_info(imdb_id)

            if imdb_info:

                themoviedb_info = get_themoviedb_info_by_imdb_id(imdb_id)

                if themoviedb_info:
                    data['background_image'] = themoviedb_info['background_image']
                    # data['trailer'] = themoviedb_info['trailer']

                data['image'] = imdb_info['image']
                data['rating'] = imdb_info['rating']
                data['metacritic_rate'] = imdb_info['metacritic_rate']
                data['summary'] = imdb_info['summary']
                data['actors'] = imdb_info['actors']
                data['directors'] = imdb_info['directors']
                data['votes'] = imdb_info['votes']
                data['rank'] = imdb_info['rank']
                data['en_summary'] = imdb_info['summary']
                data['age'] = imdb_info['age']
                data['awards'] = imdb_info['awards']
                data['runtime'] = imdb_info['runtime']
                data['release'] = imdb_info['release']
                data['trailer'] = imdb_info['trailer']

                if not data['genres']:
                    data['genres'] = imdb_info['genres']

    if not data['directors']:
        data['directors'] = directors

    if not data['release']:
        data['release'] = release_date

    for element in soup.find(class_='posts').find(class_='body').find_all('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if not is_link_valid(link):
            continue

        passed = False

        for exclude_key in config.link_exclude_keywords:

            if exclude_key.lower() in link.lower():
                passed = True

        if passed:
            continue

        data['raw_download_links'].append(link)

    # directory links
    for element in soup.find(class_='posts').find(class_='body').find_all('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if '.zip' in link:
            continue

        if ('.mkv' not in link and '.mp4' not in link) and 'download.php' in link:
            print(link)

            data['raw_download_links'].extend(get_directory_links(link))

    if type == 'series':
        data['download_links'] = sort_serie_links(data['raw_download_links'])

    elif type == 'movies':
        data['download_links'] = sort_movie_links(data['raw_download_links'])

    if not data['raw_download_links']:
        print(url)

        print('no link found')

    data['has_dubbed'] = links_dub_type(type, data['download_links'])
    data['has_subtitle'] = links_sub_type(type, data['download_links'])

    return data


def get_post_override(post_id, args):
    error = False
    imdb_id = args['imdb_id']
    themoviedb_link = args['themoviedb_link']

    url = 'https://google-crawler.appversion6.workers.dev/?p={}'.format(post_id)

    for i in range(0, 4):

        error = True

        proxy = random.choice(proxies)

        try:

            if config.proxy_enabled:

                response = requests.get(url, proxies=proxy)

            else:

                response = requests.get(url)

            if response.status_code != 200:
                print('post error code: {}'.format(response.status_code))

                continue

            error = False

            break

        except Exception as e:

            print(e)

    if error:
        print('get_post_override passed 4 time try')

        return {}

    soup = BeautifulSoup(response.text, 'html.parser')
    comments = get_comments(soup)
    post = soup.find(class_='posts')

    image = post.find('img', attrs={"decoding": "async"}).attrs['src'].strip()
    imdb_info = imdb.get_info(imdb_id)
    type = imdb_info['type']
    themoviedb_info = get_themoviedb_info_by_imdb_id(imdb_id)

    if themoviedb_info is None:

        if themoviedb_link:

            themoviedb_info = get_themoviedb_info_by_link(themoviedb_link)

            if not themoviedb_info:
                themoviedb_ids[post_id] = imdb_id
                helpers.save_json_file('themoviedb', themoviedb_ids)

                del _overrides[post_id]
                helpers.save_json_file('overrides', _overrides)

                return {}

        else:

            themoviedb_ids[post_id] = imdb_id
            helpers.save_json_file('themoviedb', themoviedb_ids)

            del _overrides[post_id]
            helpers.save_json_file('overrides', _overrides)

            return {}

    ai_data = ai.get_post_data(post.text)

    en_title = themoviedb_info['title']
    fa_title = ai.translate(en_title)
    en_summary = themoviedb_info['summary']
    fa_summary = ''

    if not en_summary and ai_data.get('fa_summary'):
        fa_summary = ai_data.get('fa_summary')

    if en_summary:
        fa_summary = ai.translate(en_summary)

    broadcast_days = {
        'Saturday': '',
        'Sunday': '',
        'Monday': '',
        'Tuesday': '',
        'Wednesday': '',
        'Thursday': '',
        'Friday': ''
    }

    for key, value in broadcast_days.items():

        if key in ai_data.get('broadcast_days', []):
            broadcast_days[key] = 'on'

    if type == 'movies':
        post_title = 'فیلم ترکی {}'.format(en_title)
    else:
        post_title = 'سریال ترکی {}'.format(en_title)

    background_image = ''
    if themoviedb_info:
        background_image = themoviedb_info['background_image']

    data = {
        'once': True,
        'post_id': post_id,
        'type': type,
        'post_title': post_title,
        'title': en_title,
        'fa_title': fa_title,
        'image': image,
        'imdb_id': imdb_id,
        'genres': imdb_info['genres'],
        'has_dubbed': '0',
        'has_subtitle': '0',
        'broadcast_days': broadcast_days,
        'fa_summary': fa_summary,
        'en_summary': en_summary,
        'background_image': background_image,
        'release': imdb_info['release'],
        'rating': imdb_info['rating'],
        'metacritic_rate': imdb_info['metacritic_rate'],
        'actors': imdb_info['actors'],
        'directors': imdb_info['directors'],
        'votes': imdb_info['votes'],
        'age': imdb_info['age'],
        'runtime': imdb_info['runtime'],
        'rank': imdb_info['rank'],
        'awards': imdb_info['awards'],
        'trailer': imdb_info['trailer'],
        'comments': comments,
        'download_links': [],
        'raw_download_links': []
    }

    if 'زیرنویس چسبیده' in post.text or 'دوبله' in post.text or 'زیرنویس چسپیده' in post.text:

        for element in soup.find(class_='posts').find(class_='body').find_all('a'):

            if not element.has_attr('href'):
                continue

            link = element.attrs['href']

            if not is_link_valid(link):
                continue

            passed = False

            for exclude_key in config.link_exclude_keywords:

                if exclude_key.lower() in link.lower():
                    passed = True

            if passed:
                continue

            data['raw_download_links'].append(link)

        # directory links
        for element in soup.find(class_='posts').find(class_='body').find_all('a'):

            if not element.has_attr('href'):
                continue

            link = element.attrs['href']

            if '.zip' in link:
                continue

            if ('.mkv' not in link and '.mp4' not in link) and 'download.php' in link:
                print(link)

                data['raw_download_links'].extend(get_directory_links(link))

        if type == 'series':
            data['download_links'] = sort_serie_links(data['raw_download_links'])

        elif type == 'movies':
            data['download_links'] = sort_movie_links(data['raw_download_links'])

    if not data['raw_download_links']:
        print(url)

        print('no link found')

    data['has_dubbed'] = links_dub_type(type, data['download_links'])
    data['has_subtitle'] = links_sub_type(type, data['download_links'])

    return data


def links_dub_type(type, links):
    result = '0'

    if type == 'series':
        for item in links:
            for entry in links[item]:
                if entry['type'] == 'dub':
                    result = '1'

    elif type == 'movies':
        for item in links:
            if item['type'] == 'dub':
                result = '1'

    return result

def links_sub_type(type, links):
    result = '0'

    if type == 'series':
        for item in links:
            for entry in links[item]:
                if entry['type'] == 'sub':
                    result = '1'

    elif type == 'movies':
        for item in links:
            if item['type'] == 'sub':
                result = '1'

    return result


def sort_serie_links(links):
    episodes = defaultdict(lambda: defaultdict(list))

    season_sub_dub_type = {}
    for link in links:
        season = 1
        episode = None
        type = ''

        season_match = re.search(r'[Ss](\d{1,2})', link)
        episode_match = re.search(r'[Ee](\d{1,4})', link)
        episode_match2 = re.search(r'[Ee]\((\d{1,4})\)', link)
        episode_match3 = re.search(r'[Bb](\d{1,4})', link)
        episode_match4 = re.search(r'[BL]\((\d{1,4})\)', link)

        if season_match:
            season = int(season_match.group(1))
        if episode_match:
            episode = int(episode_match.group(1))
        elif episode_match2:
            episode = int(episode_match2.group(1))
        elif episode_match3:
            episode = int(episode_match3.group(1))
        elif episode_match4:
            episode = int(episode_match4.group(1))

        for sub in config.subtitle_keywords:
            if sub.lower() in link.lower():
                type = 'sub'

        for dub in config.dub_keywords:
            if dub.lower() in link.lower():
                type = 'dub'

        quality_match = re.search(r'(\d{3,4}p)', link)
        if quality_match:
            quality = quality_match.group(1)
        else:
            continue

        if episode is None or quality not in config.allowed_qualities:
            continue

        episodes[season][episode].append({
            'link': link,
            'type': type,
            'quality': quality,
            'episode': episode
        })

    for season, eps in episodes.items():
        found_type = None
        for ep_links in eps.values():
            for l in ep_links:
                if l['type']:
                    found_type = l['type']
                    break
            if found_type:
                break
        if found_type:
            season_sub_dub_type[season] = found_type

    final_links_by_season = defaultdict(list)

    for season, eps in episodes.items():
        for ep, links_list in eps.items():
            grouped = defaultdict(list)
            for l in links_list:
                grouped[l['quality']].append(l)

            for quality, lgroup in grouped.items():
                if len(lgroup) == 1:
                    final_links_by_season[season].append(lgroup[0])
                else:

                    types = list({item["type"] for item in lgroup if item["type"]})

                    print(types)

                    if len(types) == 1:

                        working_links = []

                        for lnk in lgroup:
                            print(lnk['link'])
                            if is_link_working(lnk['link']):
                                print('is working')
                                working_links.append(lnk)
                            else:
                                print('not working')

                        sorted_links = sorted(
                            working_links,
                            key=lambda ___link: (not has_subtitle_keyword(___link['link']))
                        )

                        if len(sorted_links) > 0:
                            final_links_by_season[season].append(sorted_links[0])

                    else:
                        for lnk in lgroup:
                            final_links_by_season[season].append(lnk)

    _final = defaultdict(list)

    for season, eps in final_links_by_season.items():
        if season not in season_sub_dub_type:
            continue

        for episode in eps:
            if not episode['type']:
                episode['type'] = season_sub_dub_type[season]

        eps.sort(key=lambda x: (x['episode'], config.allowed_qualities.get(x['quality'], 0)))

        _final[season] = eps

    _final = dict(sorted(_final.items(), key=lambda x: x[0]))

    return _final


def sort_movie_links(links):
    list = []

    for link in links:

        _list = {
            'link': link,
            'type': ''
        }

        for sub in config.subtitle_keywords:

            if sub.lower() in link.lower():
                _list['type'] = 'sub'

        for dub in config.dub_keywords:

            if dub.lower() in link.lower():
                _list['type'] = 'dub'

        quality_match = re.search(r'(\d{3,4}p)', link)
        if quality_match:
            _list['quality'] = quality_match.group(1)

        if 'quality' not in _list:
            continue

        if _list['quality'] not in config.allowed_qualities:
            continue

        if not _list['type']:
            continue

        list.append(_list)

    list.sort(key=lambda x: (x['type'] != 'sub', config.allowed_qualities[x['quality']]))

    return list


def get_directory_links(_url):
    url = None
    for key, domain in config.server_domains.items():
        if key in _url and 'teamlink.top' not in _url:
            url = domain.format(_url.split('&url=')[1])
            link_status = is_link_working(url)
            if not link_status:
                for key, domain2 in config.server_domains2.items():
                    if key in _url and 'teamlink.top' not in _url:
                        url = domain2.format(_url.split('&url=')[1])
                        break
            break

    if url is None:
        url = _url

    response = safe_get(url)

    if not response:
        return []

    soup = BeautifulSoup(response.text, 'html.parser')

    links = []

    if not url.endswith('/'):
        url = '{}/'.format(url)

    for element in soup.findAll('a'):

        if not element.has_attr('href'):
            continue

        link = element.attrs['href']

        if not is_link_valid(link):
            continue

        passed = False

        for exclude_key in config.link_exclude_keywords:

            if exclude_key.lower() in link.lower():
                passed = True

        if passed:
            continue

        links.append(url + link)

    return links


def is_link_valid(link):
    if '.mp4' not in link and '.mkv' not in link:
        return False

    quality_match = re.search(r'(\d{3,4}p)', link)
    if not quality_match:
        return False

    quality = quality_match.group(1)

    if quality not in config.allowed_qualities:
        return False

    if quality_match.group(1) not in config.allowed_qualities:
        return False

    return True


def get_themoviedb_info_by_title(title):
    url = 'https://themoviedb-api.appversion6.workers.dev/3/search/multi'
    params = {
        'api_key': config.themoviedb_apikey,
        'query': title,
        'language': 'en-US',
        'page': 1,
        'include_adult': False
    }

    response = requests.get(url, params=params)

    if response.status_code == 200:
        json = response.json()

        if not json['results']:
            print('get_themoviedb_info result: {}'.format(response.text))

            return False

        for item in json['results']:

            background_image = ''
            if 'backdrop_path' in item:
                background_image = 'https://image.tmdb.org/t/p/w1280{}'.format(item['backdrop_path'])

            if 'title' in item:
                title = item['original_title']

            if 'name' in item:
                title = item['original_name']

            return {
                'title': title,
                'summary': item['overview'],
                'background_image': background_image,
                'trailer': ''
                # 'trailer': get_trailer(response['results'][0]['id'], response['results'][0]['media_type'])
            }

    print('get_themoviedb_info error: {}'.format(response.text))

    return False


def get_themoviedb_info_by_imdb_id(imdb_id):
    url = f'https://themoviedb-api.appversion6.workers.dev/3/find/{imdb_id}'
    params = {
        'api_key': config.themoviedb_apikey,
        'external_source': 'imdb_id',
    }

    response = requests.get(url, params=params)

    if response.status_code != 200:
        print(f'get_themoviedb_info_by_imdb_id status error: {response.text}')
        return False

    json_data = response.json()

    if all(not json_data.get(key) for key in
           ['movie_results', 'person_results', 'tv_results', 'tv_episode_results', 'tv_season_results']):
        print('get_themoviedb_info_by_imdb_id empty results')
        return None

    if json_data.get('tv_results'):
        for item in json_data['tv_results']:
            background_image = ''
            if item.get('backdrop_path'):
                background_image = f"https://image.tmdb.org/t/p/w1280{item['backdrop_path']}"
            return {
                'title': item.get('original_name', ''),
                'summary': item.get('overview', ''),
                'background_image': background_image,
            }

    elif json_data.get('movie_results'):
        for item in json_data['movie_results']:
            background_image = ''
            if item.get('backdrop_path'):
                background_image = f"https://image.tmdb.org/t/p/w1280{item['backdrop_path']}"
            return {
                'title': item.get('original_title', ''),
                'summary': item.get('overview', ''),
                'background_image': background_image,
            }

    print(f'get_themoviedb_info_by_imdb_id error: {response.text}')

    exit(0)


def get_themoviedb_info_by_link(url):
    response = requests.get(url)

    if response.status_code != 200:
        print(f'get_themoviedb_info_by_link status error: {response.text}')
        return False

    soup = BeautifulSoup(response.text, 'html.parser')

    styles = soup.find_all('style')

    background_image = ''

    for style in styles:
        css_text = style.get_text()
        match = re.search(r"div\.header\.large\.first\s*{[^}]*background-image:\s*url\(['\"]?(.*?)['\"]?\)", css_text)
        if match:
            background_image = match.group(1)
            break

    return {
        'title': soup.select_one('.title h2 a').get_text(strip=True),
        'summary': soup.select_one('.overview').get_text(strip=True),
        'background_image': background_image,
    }


def get_trailer(id, media_type):
    url = 'https://themoviedb-api.appversion6.workers.dev/3/{}/{}/videos'.format(media_type, id)
    params = {
        'api_key': config.themoviedb_apikey,
        'language': 'en-US'
    }

    response = requests.get(url, params=params)

    if response.status_code == 200:
        response = response.json()

        print(response['results'])

        for video in response['results']:
            if video['type'] == 'Trailer' and video['site'] == 'YouTube':
                return "https://www.youtube.com/watch?v={}".format(video['key'])

    return ''


def get_comments(soup):
    all_comments = soup.find_all("div", class_="comment")

    stack = []
    tree = []

    for div in all_comments:
        depth_classes = [cls for cls in div.get("class", []) if cls.startswith("depth-")]
        depth = int(depth_classes[0].split("-")[1]) if depth_classes else 1

        author = div.find("cite", class_="cm_author").get_text(strip=True)
        text = div.find("div", class_="comment_text").get_text(strip=True)
        date = div.find("div", class_="comment_date").get_text(strip=True).split(',')[1].strip()

        date = convert_to_gregorian(date)

        if author.lower().startswith('admin') or author.startswith('مدیر'):
            continue

        if 'http' in text or 'moviebaz' in text or 'مووی باز' in text or 'موی باز' in text:
            continue

        comment = {
            "author": author,
            "text": text,
            "date": date,
            "replies": []
        }

        if depth == 1:
            tree.append(comment)
            stack = [(comment, depth)]
        else:
            while stack and stack[-1][1] >= depth:
                stack.pop()

            if stack:
                stack[-1][0]["replies"].append(comment)

            stack.append((comment, depth))

    return tree


def convert_to_gregorian(date):
    parts = date.split()
    day = int(parts[0])
    month_persian = parts[1]
    year = int(parts[2])

    month_map = {
        'ژانویه': 'January',
        'فوریه': 'February',
        'مارس': 'March',
        'آوریل': 'April',
        'مه': 'May',
        'می': 'May',
        'ژوئن': 'June',
        'جولای': 'July',
        'ژوئیه': 'July',
        'آگوست': 'August',
        'سپتامبر': 'September',
        'اکتبر': 'October',
        'نوامبر': 'November',
        'دسامبر': 'December'
    }

    month = month_map.get(month_persian, None)

    date_obj = datetime.strptime(f'{day} {month} {year}', '%d %B %Y')

    return date_obj.strftime('%Y-%m-%d')


def is_link_working(url):
    headers = {"User-Agent": "Mozilla/5.0"}
    try:
        with session.get(url, headers=headers, stream=True, timeout=200) as r:
            return r.status_code == 200
    except requests.exceptions.ConnectionError as e:
        print(f"[Connection Error] Could not connect to {url} -> {e}")
        return False
    except requests.exceptions.RequestException as e:
        print(f"[Error] {e}")
        return False
