import urllib.parse
import HelperFunctions
import Conversions
import FilterSkins
import urllib.parse
# from sniper.models import cs2snipe_users
import concurrent.futures
import threading
import psycopg2
import DBStuff

lock = threading.Lock()


def findSkin(result_json, steamid, queryid, ReqManager):
    inspect_server_url = "http://23.88.122.57:1337/"
    weapon_listings_url_list = buildSkinURLs(result_json=result_json)
    if not isinstance(weapon_listings_url_list, list):
        if weapon_listings_url_list[0] is False:
            DBStuff.updateQuery(
                queryid, True, "Not possible", weapon_listings_url_list[1]
            )
            DBStuff.updateFreeSnipes(steamid, "plus")
            return None

    inspect_link_list = []
    with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
        futures = []
        for url in weapon_listings_url_list:
            futures.append(
                executor.submit(
                    HelperFunctions.singleBuildInspectList,
                    result_json=result_json,
                    listing=url,
                    ReqManager=ReqManager,
                )
            )

        for future in concurrent.futures.as_completed(futures):
            with lock:
                inspect_link_list += future.result()

    if len(inspect_link_list) == 0:
        query_message = str(0) + " matching skins found."
        DBStuff.updateQuery(queryid, False, "Done", query_message)
        print("Done with " + str(result_json))
        return None
    count_found_skins = FilterSkins.filterSkins(
        result_json, inspect_link_list, inspect_server_url, ReqManager, steamid, queryid
    )
    if count_found_skins == 0:
        query_message = "No matching skins found."
    else:
        if int(count_found_skins) == 1:
            query_message = str(count_found_skins) + " matching skin found."
        else:
            query_message = str(count_found_skins) + " matching skins found."
    DBStuff.updateQuery(queryid, False, "Done", query_message)
    print("Done with " + str(result_json))
    return None


def buildSkinURLs(result_json):
    # "https://steamcommunity.com/market/listings/730/" + urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8")) + urllib.parse.quote(str(getConditionForSkin(result_json))) + "/render/?query="
    conn = psycopg2.connect(
        database="postgres",  # enter your database name
        user="postgres",  # enter your postgres username
        password="Berufsorientierung1!",  # enter your password
        host="23.88.122.57",  # enter your host name
        port="5432",  # port number
    )
    cursor = conn.cursor()

    checked_conditions = []
    if "condition" in result_json:
        if "all" in result_json["condition"]:
            checked_conditions = getPossibleConditions(
                result_json=result_json, cursor=cursor
            )

        elif "minmax" in result_json["condition"]:
            cursor.execute(
                "SELECT float FROM full_floats_low WHERE market_hash_name LIKE %(name)s",
                {"name": "%{}%".format(str(result_json["skin_name"]))},
            )
            min_float = cursor.fetchone()[0]

            cursor.execute(
                "SELECT float FROM full_floats_high WHERE market_hash_name LIKE %(name)s",
                {"name": "%{}%".format(str(result_json["skin_name"]))},
            )
            max_float = cursor.fetchone()[0]

            # condition = " (" + str(cond) + ")"

            checked_conditions.append(
                " " + str(Conversions.floatToConditionConversion(float(min_float)))
            )
            checked_conditions.append(
                " " + str(Conversions.floatToConditionConversion(float(max_float)))
            )

        else:
            for cond in result_json["condition"]:
                checked_cond = checkIfConditionIsPossible(result_json, cond, cursor)
                if not isinstance(checked_cond, str):
                    return False, "There are no " + str(cond) + " skins for " + str(
                        result_json["skin_name"]
                    )
                checked_conditions.append(checked_cond)

    else:
        checked_conditions = getConditionForSkin(result_json, cursor)
        if not isinstance(checked_conditions, str):
            return False, str(checked_conditions[1])
        else:
            checked_conditions = [checked_conditions]

    weapon_listings_url_list = []
    for checked_condition in checked_conditions:

        if str(result_json["skin_name"]).startswith("★"):
            stattrak = "★ StatTrak™"
            # if result_json["type"] == "stat_only" or result_json["type"] == "stat_and_non_stat" or result_json["type"] == "all":
            #     result_json["skin_name"] = str(result_json["skin_name"]).replace("★ ", "")
        else:
            stattrak = "StatTrak™"

        if result_json["type"] == "stat_only":
            stat_available = checkIfStatAvailable(result_json, stattrak, cursor)

            if stat_available is False:
                cursor.close()
                conn.close()
                return False, "No StatTrak version available for " + str(
                    result_json["skin_name"]
                )

            weapon_listings_url_list.append(
                "https://steamcommunity.com/market/listings/730/"
                + stattrak
                + " "
                + getNameWithoutStarIfNeeded(result_json=result_json)
                + urllib.parse.quote(str(checked_condition))
                + "/render/?query="
            )

        if result_json["type"] == "non_stat_only":
            weapon_listings_url_list.append(
                "https://steamcommunity.com/market/listings/730/"
                + urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8"))
                + urllib.parse.quote(str(checked_condition))
                + "/render/?query="
            )

        if result_json["type"] == "stat_and_non_stat":
            weapon_listings_url_list.append(
                "https://steamcommunity.com/market/listings/730/"
                + urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8"))
                + urllib.parse.quote(str(checked_condition))
                + "/render/?query="
            )

            stat_available = checkIfStatAvailable(result_json, stattrak, cursor)
            if stat_available is True:
                print("IS EH DO")
                print(str(stattrak))
                weapon_listings_url_list.append(
                    "https://steamcommunity.com/market/listings/730/"
                    + stattrak
                    + "%20"
                    + getNameWithoutStarIfNeeded(result_json=result_json)
                    + urllib.parse.quote(str(checked_condition))
                    + "/render/?query="
                )
            else:
                print("WO IS AS??????????")

        if result_json["type"] == "souvenir":
            souv_available = checkIfSouvAvailable(result_json, cursor)
            if souv_available is True:
                weapon_listings_url_list.append(
                    "https://steamcommunity.com/market/listings/730/"
                    + urllib.parse.quote("Souvenir")
                    + "%20"
                    + urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8"))
                    + urllib.parse.quote(str(checked_condition))
                    + "/render/?query="
                )
            else:
                cursor.close()
                conn.close()
                return False, "No Souvenir version available for " + str(
                    result_json["skin_name"]
                )

        if result_json["type"] == "all":
            weapon_listings_url_list.append(
                "https://steamcommunity.com/market/listings/730/"
                + urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8"))
                + urllib.parse.quote(str(checked_condition))
                + "/render/?query="
            )
            souv_available = checkIfSouvAvailable(result_json, cursor)
            if souv_available is True:
                weapon_listings_url_list.append(
                    "https://steamcommunity.com/market/listings/730/"
                    + urllib.parse.quote("Souvenir")
                    + "%20"
                    + urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8"))
                    + urllib.parse.quote(str(checked_condition))
                    + "/render/?query="
                )

            stat_available = checkIfStatAvailable(result_json, stattrak, cursor)
            if stat_available is True:
                weapon_listings_url_list.append(
                    "https://steamcommunity.com/market/listings/730/"
                    + stattrak
                    + "%20"
                    + getNameWithoutStarIfNeeded(result_json=result_json)
                    + urllib.parse.quote(str(checked_condition))
                    + "/render/?query="
                )
    cursor.close()
    conn.close()
    # print(weapon_listings_url_list)
    return weapon_listings_url_list


def getNameWithoutStarIfNeeded(result_json):
    if str(result_json["skin_name"]).startswith("★"):
        return urllib.parse.quote(
            str(result_json["skin_name"]).replace("★ ", "").encode("utf-8")
        )
    else:
        return urllib.parse.quote(str(result_json["skin_name"]).encode("utf-8"))


def checkIfStatAvailable(result_json, stattrak, cursor):
    cursor.execute(
        "SELECT float FROM full_floats_low WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(stattrak + " " + str(result_json["skin_name"]))},
    )
    min_float = cursor.fetchone()
    if min_float is None:
        cursor.execute(
            "SELECT float FROM full_floats_high WHERE market_hash_name LIKE %(name)s",
            {"name": "%{}%".format(stattrak + " " + str(result_json["skin_name"]))},
        )
        max_float = cursor.fetchone()
        if max_float is None:
            return False
    return True


def checkIfSouvAvailable(result_json, cursor):
    cursor.execute(
        "SELECT float FROM full_floats_low WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format("Souvenir " + str(result_json["skin_name"]))},
    )
    min_float = cursor.fetchone()
    if min_float is None:
        cursor.execute(
            "SELECT float FROM full_floats_high WHERE market_hash_name LIKE %(name)s",
            {"name": "%{}%".format("Souvenir " + str(result_json["skin_name"]))},
        )
        max_float = cursor.fetchone()
        if max_float is None:
            return False
    return True


def getPossibleConditions(result_json, cursor):
    cursor.execute(
        "SELECT float FROM full_floats_low WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(str(result_json["skin_name"]))},
    )
    min_float = cursor.fetchone()[0]

    cursor.execute(
        "SELECT float FROM full_floats_high WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(str(result_json["skin_name"]))},
    )
    max_float = cursor.fetchone()[0]

    possible_conditions = Conversions.floatToConditionList(
        min_float=float(min_float), max_float=float(max_float)
    )
    possible_conditions = list(possible_conditions)
    for i in range(len(possible_conditions)):
        possible_conditions[i] = " (" + possible_conditions[i] + ")"

    return possible_conditions


def checkIfConditionIsPossible(result_json, cond, cursor):
    cursor.execute(
        "SELECT float FROM full_floats_low WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(str(result_json["skin_name"]))},
    )
    min_float = cursor.fetchone()[0]

    cursor.execute(
        "SELECT float FROM full_floats_high WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(str(result_json["skin_name"]))},
    )
    max_float = cursor.fetchone()[0]

    if result_json["filter_options"] == "other_filter":
        if "condition" in result_json:
            possible_conditions = Conversions.floatToConditionList(
                min_float=float(min_float), max_float=float(max_float)
            )
            if str(cond) in possible_conditions:
                condition = " (" + str(cond) + ")"
                return condition
            else:
                return False, "There are no " + str(cond) + " skins for " + str(
                    result_json["skin_name"]
                )
        else:
            return False, "idk what happened"


def getConditionForSkin(result_json, cursor):
    # re.close()
    cursor.execute(
        "SELECT float FROM full_floats_low WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(str(result_json["skin_name"]))},
    )
    min_float = cursor.fetchone()[0]

    cursor.execute(
        "SELECT float FROM full_floats_high WHERE market_hash_name LIKE %(name)s",
        {"name": "%{}%".format(str(result_json["skin_name"]))},
    )
    max_float = cursor.fetchone()[0]

    if result_json["filter_options"] == "other_filter":
        if "condition" in result_json:
            possible_conditions = Conversions.floatToConditionList(
                min_float=float(min_float), max_float=float(max_float)
            )
            if str(result_json["condition"]) in possible_conditions:
                condition = " (" + str(result_json["condition"]) + ")"
            else:
                return False, "There are no " + str(
                    result_json["condition"]
                ) + " skins for " + str(result_json["skin_name"])
        else:
            return False, "idk what happened"
    if result_json["filter_options"] == "exact_float":
        if float(result_json["exact_float"]) >= float(min_float) and float(
            result_json["exact_float"]
        ) <= float(max_float):
            condition = " " + Conversions.floatToConditionConversion(
                result_json["exact_float"]
            )
        else:
            return False, "The exact float " + str(
                result_json["exact_float"]
            ) + " is not in the range for possible floatvalues for the skin " + str(
                result_json["skin_name"]
            )
    if result_json["filter_options"] == "float_restrictions":
        if float(result_json["float_for_restriction"]) >= float(min_float) and float(
            result_json["float_for_restriction"]
        ) <= float(max_float):
            condition = " " + Conversions.floatToConditionConversion(
                result_json["float_for_restriction"]
            )
        else:
            return False, "The restriction float " + str(
                result_json["float_for_restriction"]
            ) + " is not in the range for possible floatvalues for the skin " + str(
                result_json["skin_name"]
            )
    return condition
