#!/usr/bin/env python3

import os
import httpx
import logging
import time
from lib import constants
from lib import local
from lib import remote


logging.basicConfig(filename=constants.LOG_FILENAME, level=logging.ERROR, format="\n\n\n>>>%(asctime)s %(message)s")
check_logs = False


if __name__ == '__main__':
    print(f"[i] Running e621dl version {constants.VERSION}.")

    print("[i] Getting config...")
    try:
        config = local.get_config()
        blacklist = config.get('blacklist', [])
        search_defaults = config.get('search_defaults')
    except Exception:
        print("[✗] Error in Config File. Check error log for error details")
        logging.exception('Config File Error \n')
        input("Press Enter to continue...")
        raise SystemExit

    searches = []
    for key, value in config.get('searches').items():
        if len(value.get('tags')) > constants.MAX_SEARCH_TAGS:
            print(f"[i] Too many tags in search '{key}'. No more than {constants.MAX_SEARCH_TAGS} can be used. Additional tags will be discarded.")
            value['tags'] = value['tags'][:constants.MAX_SEARCH_TAGS]
    
        searches.append({
            'directory': key,
            'tags': value.get('tags'),
            'start_date': local.get_start_date(value.get('days', search_defaults.get('days', 1))),
            'min_score': value.get('min_score', search_defaults.get('min_score', 0)),
            'min_fav_count': value.get('min_fav_count', search_defaults.get('min_fav_count', 0)),
            'allowed_ratings': value.get('allowed_ratings', search_defaults.get('allowed_ratings', ['s']))
        })

    with httpx.Client(
        headers = {'user-agent': f"e621dl.py/{constants.VERSION} (by Wulfre)"},
    ) as client:
        for search in searches:
            print(f"[i] Getting posts for search '{search['directory']}'.")

            last_id = None
            while True:
                
                while True:
                    try:
                        posts = remote.get_posts(client, ' '.join(search['tags']), search['start_date'], last_id)
                        break
                    except TimeoutError:
                        print("[✗] TimeoutError. retrying.")
                        logging.exception('TimeoutError \n')
                        check_logs = True
                        time.sleep(3)
                    except httpx._exceptions.NetworkError:
                        print("[✗] NetworkError. retrying.")
                        logging.exception('NetworkError \n')
                        check_logs = True
                        time.sleep(3)
                    except urllib3.exceptions.ReadTimeoutError:
                        print("[✗] ReadTimeoutError. retrying.")
                        logging.exception('ReadTimeoutError \n')
                        check_logs = True
                        time.sleep(3)

                for post in posts:
                    path = local.make_path(search['directory'], post['id'], post['file']['ext'])

                    if os.path.isfile(path):
                        print(f"[i] Post {post['id']} was already downloaded.")
                    elif post['rating'] not in search['allowed_ratings']: 
                        print(f"[✗] Post {post['id']} was skipped for having an unwanted rating.")
                    elif any(x in [x for y in post['tags'].values() for x in y] for x in blacklist):
                        print(f"[✗] Post {post['id']} was skipped for having a blacklisted tag.")
                    elif post['score']['total'] < search['min_score']:
                        print(f"[✗] Post {post['id']} was skipped for having a low score.")
                    elif post['fav_count'] < search['min_fav_count']:
                        print(f"[✗] Post {post['id']} was skipped for having a low favorite count.")
                    else:
                        print(f"[✓] Post {post['id']} is being downloaded.")
                        remote.download_post(client, local.make_url(post['file']['md5'], post['file']['ext']), path)

                if (last_id := posts[-1]['id'] if posts else None) is None:
                    break

    print('[i] All searches complete.')
    if check_logs == True:
        print("[i] Check error log for error details")
    input("Press Enter to continue...")
    raise SystemExit
