import string
import uuid
import time
import os
import random
import aiofiles
from datetime import datetime


def generate_order_id(min_length: int = 12, max_length: int = 16) -> str:
    length = random.randint(min_length, max_length)
    if length < 1 or length > 128:
        raise ValueError("Длина order_id должна быть от 1 до 128 символов.")

    characters = string.ascii_letters + string.digits + '_-'
    return ''.join(random.choice(characters) for _ in range(length))

def convert_iso_time(date: str) -> str:
    dt_object = datetime.fromisoformat(date.replace("Z", "+00:00"))
    return dt_object.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]

async def generate_proxy_list(proxies: list, base_path: str, plan: str):
    try:
        # Ensure the directory exists
        os.makedirs(base_path, exist_ok=True)
        
        unique_name = f"{plan}_{uuid.uuid4().hex}.txt"
        file_path = os.path.join(base_path, unique_name)

        async with aiofiles.open(file_path, mode='w') as file:
            for proxy in proxies:
                await file.write(f"{proxy}\n")

        return file_path
    except Exception as e:
        print(f"Произошла ошибка при записи файла: {e}")
        # Return None explicitly so we can handle it in the caller
        return None

async def generate_file_with_users_hyperlink(users: list, base_path: str):
    try:
        # Ensure the directory exists
        os.makedirs(base_path, exist_ok=True)
        
        unique_name = f"{uuid.uuid4().hex}_{int(time.time())}.txt"
        file_path = os.path.join(base_path, unique_name)

        async with aiofiles.open(file_path, mode='w') as file:
            for user in users:
                await file.write(f"{user['user_id']} | @{user['username']}\n")
        return file_path
    except Exception as e:
        print(f"Произошла ошибка при записи файла: {e}")
        # Return None explicitly so we can handle it in the caller
        return None

def get_country_by_tag(tag_country: str):
    countries = [
        ("United Kingdom 🇬🇧", "virm"),
        ("Germany 🇩🇪", "dtag"),
        ("United States 🇺🇸", "juic"),
        ("Australia 🇦🇺", "vocu"),
        ("Netherlands 🇳🇱", "dtag_nl"),
        ("Poland 🇵🇱", "pol"),
        ("Brazil 🇧🇷", "bra"),
        ("Latvia 🇱🇻", "lva"),
        ("France 🇫🇷", "fra"),
        ("Romania 🇷🇴", "rou"),
        ("Canada 🇨🇦", "can"),
        ("Norway 🇳🇴", "nor"),
        ("Austria 🇦🇹", "aut"),
        ("Ukraine 🇺🇦", "ukr"),
        ("Turkey 🇹🇷", "tur"),
        ("Japan 🇯🇵", "jpn"),
        ("Israel 🇮🇱", "isr"),
        ("Taiwan 🇹🇼", "twn"),
        ("South Korea 🇰🇷", "kor"),
        ("Spain 🇪🇸", "esp"),
        ("Singapore 🇸🇬", "sgp"),
        ("Hong Kong 🇭🇰", "hkn"),
        ("Thailand 🇹🇭", "tha"),
        ("India 🇮🇳", "ind"),
        ("Italy 🇮🇹", "ita"),
    ]

    for country, key in countries:
        if key == tag_country:
            return country
    return None


def generate_username(min_length=8, max_length=16):
    length = random.randint(min_length, max_length)
    username = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
    return username

def generate_password(min_length=8, max_length=16):
    length = random.randint(min_length, max_length)
    password = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
    return password


def validate_username(username: str) -> bool:
    if len(username) < 8:
        return False
    if not username.isalnum():
        return False
    return True

def validate_password(password: str) -> bool:
    if len(password) < 8:
        return False
    if not password.isalnum():
        return False
    return True

def is_number(s: str) -> bool:
    try:
        float(s)
        return True
    except ValueError:
        return False


def iso2_to_flag(iso2_code: str) -> str:
    if len(iso2_code) != 2:
        raise ValueError("ISO2 код должен содержать 2 буквы.")

    return ''.join(
        chr(0x1F1E6 + ord(c) - ord('a')) for c in iso2_code.lower()
    )

def get_asn_pairs_by_iso2(data, iso2):
    for country in data:
        if country.get("iso2") == iso2:
            geo_asns = country.get("geo_asns", [])
            asn_data = country.get("asnData", [])

            pairs = [{"name": asn, "asn": geo_asn} for asn, geo_asn in zip(asn_data, geo_asns)]
            return pairs
    return []


def search_asn_pairs(asn_pairs, search_term):
    filtered_pairs = [pair for pair in asn_pairs if search_term.lower() in pair['name'].lower()]
    return filtered_pairs

def generate_unique_session_names(count, length=8):
    possible_chars = string.ascii_letters + string.digits  # a-z, A-Z, 0-9
    session_names = set()

    max_combinations = len(possible_chars) ** length
    if count > max_combinations:
        raise ValueError("Невозможно сгенерировать такое количество уникальных session-name с заданной длиной.")

    while len(session_names) < count:
        session = ''.join(random.choices(possible_chars, k=length))
        session_names.add(session)

    return list(session_names)

def get_ipv_countries():
    countries = [
        {
            "id": 233,
            "name": "United States",
            "iso2": "US"
        },
        {
            "id": 232,
            "name": "United Kingdom",
            "iso2": "GB"
        },
        {
            "id": 82,
            "name": "Germany",
            "iso2": "DE"
        },
        {
            "id": 75,
            "name": "France",
            "iso2": "FR"
        },
        {
            "id": 39,
            "name": "Canada",
            "iso2": "CA"
        },
        {
            "id": 1,
            "name": "Netherlands",
            "iso2": "NL"
        },
        {
            "id": 70,
            "name": "Russia",
            "iso2": "RU"
        },
        {
            "id": 107,
            "name": "Japan",
            "iso2": "JP"
        },
        {
            "id": 96,
            "name": "Italy",
            "iso2": "IT"
        },
        {
            "id": 205,
            "name": "Spain",
            "iso2": "ES"
        },
        {
            "id": 179,
            "name": "Romania",
            "iso2": "RO"
        },
        {
            "id": 13,
            "name": "Austria",
            "iso2": "AT"
        },
        {
            "id": 45,
            "name": "China",
            "iso2": "CN"
        },
        {
            "id": 36,
            "name": "Australia",
            "iso2": "AU"
        },
        {
            "id": 174,
            "name": "Poland",
            "iso2": "PL"
        },
        {
            "id": 103,
            "name": "India",
            "iso2": "IN"
        },
        {
            "id": 197,
            "name": "Singapore",
            "iso2": "SG"
        },
        {
            "id": 30,
            "name": "Brazil",
            "iso2": "BR"
        },
        {
            "id": 982,
            "name": "Vietnam",
            "iso2": "VN"
        },
        {
            "id": 621,
            "name": "Switzerland",
            "iso2": "CH"
        },
        {
            "id": 374,
            "name": "Ukraine",
            "iso2": "UA"
        },
        {
            "id": 813,
            "name": "Sweden",
            "iso2": "SE"
        },
        {
            "id": 957,
            "name": "Portugal",
            "iso2": "PT"
        },
        {
            "id": 563,
            "name": "Denmark",
            "iso2": "DK"
        },
        {
            "id": 384,
            "name": "Pakistan",
            "iso2": "PK"
        },
    ]
    return countries

def get_residential_regions():
    regions = [
        ('Asia', 'rsa'),
        ('Europe', 'eu'),
        ('Africa', 'africa'),
        ('North America', 'north_america'),
        ('South America', 'south_america')
    ]
    return regions

def get_region_by_short_name(short_name: str):
    regions = get_residential_regions()
    for region, code in regions:
        if short_name == code:
            return region


def format_string_proxy(login, password, hostname, port, format_type):
    if format_type == 1:
        # формат: login:password:hostname:port
        return f"{login}:{password}:{hostname}:{port}"
    elif format_type == 2:
        # формат: login:password@hostname:port
        return f"{login}:{password}@{hostname}:{port}"
    elif format_type == 3:
        # формат: hostname:port@login:password
        return f"{hostname}:{port}@{login}:{password}"
    elif format_type == 4:
        # формат: hostname:port:login:password
        return f"{hostname}:{port}:{login}:{password}"
    else:
        raise ValueError("Invalid format type. Please use 1, 2, 3, or 4.")


def get_discount(discounts, value):
    value = int(value)

    for size in sorted(discounts.keys(), key=int, reverse=True):
        if value >= int(size):
            return discounts[size]
    return 0