import time
import csv
import random
import os

def create_node(name, phone):
    """Создает узел BST"""
    return {'name': name, 'phone': phone, 'left': None, 'right': None}

def bst_insert(root, name, phone):
    """Вставляет запись в BST"""
    if root is None:
        return create_node(name, phone)
    
    current = root
    while True:
        if name < current['name']:
            if current['left'] is None:
                current['left'] = create_node(name, phone)
                break
            current = current['left']
        elif name > current['name']:
            if current['right'] is None:
                current['right'] = create_node(name, phone)
                break
            current = current['right']
        else:
            current['phone'] = phone
            break
    
    return root

def bst_find(root, name):
    """Ищет запись в BST"""
    current = root
    while current:
        if name == current['name']:
            return current['phone']
        elif name < current['name']:
            current = current['left']
        else:
            current = current['right']
    return None

def bst_find_min(root):
    """Находит минимальный узел"""
    if root is None:
        return None
    current = root
    while current['left']:
        current = current['left']
    return current

def bst_delete(root, name):
    """Удаляет запись из BST"""
    if root is None:
        return None
    
    if name < root['name']:
        root['left'] = bst_delete(root['left'], name)
    elif name > root['name']:
        root['right'] = bst_delete(root['right'], name)
    else:
        if root['left'] is None:
            return root['right']
        elif root['right'] is None:
            return root['left']
        
        min_node = bst_find_min(root['right'])
        root['name'] = min_node['name']
        root['phone'] = min_node['phone']
        root['right'] = bst_delete(root['right'], min_node['name'])
    
    return root

def generate_test_data(n=300):
    """Генерирует тестовые данные"""
    records = [(f"User_{i:05d}", f"123-456-{i%10000:04d}") for i in range(n)]
    records_shuffled = records.copy()
    random.shuffle(records_shuffled)
    records_sorted = sorted(records, key=lambda x: x[0])
    return records_shuffled, records_sorted

def run_experiment():
    print("BST ТЕЛЕФОННЫЙ СПРАВОЧНИК")
    
    os.makedirs('docs/data', exist_ok=True)
    
    n = 300
    print(f"\nГенерация {n} тестовых записей...")
    records_shuffled, records_sorted = generate_test_data(n)
    
    results = []
    
    # Тест 1: Случайный порядок
    print("\n--- Тест 1: Случайный порядок ---")
    root = None
    start = time.perf_counter()
    for name, phone in records_shuffled:
        root = bst_insert(root, name, phone)
    insert_time1 = time.perf_counter() - start
    print(f"Вставка: {insert_time1:.4f} сек")
    
    names_to_find = [records_shuffled[i][0] for i in range(30)]
    start = time.perf_counter()
    for name in names_to_find:
        bst_find(root, name)
    find_time1 = time.perf_counter() - start
    print(f"Поиск 30 записей: {find_time1:.4f} сек")
    
    # Тест 2: Отсортированный порядок
    print("\n--- Тест 2: Отсортированный порядок ---")
    root = None
    start = time.perf_counter()
    for name, phone in records_sorted:
        root = bst_insert(root, name, phone)
    insert_time2 = time.perf_counter() - start
    print(f"Вставка: {insert_time2:.4f} сек")
    
    # Сохраняем результаты
    results.append(['BST', 'случайный', insert_time1, find_time1, 0])
    results.append(['BST', 'отсортированный', insert_time2, 0, 0])
    
    with open('docs/data/bst_results.csv', 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(['Структура', 'Режим', 'Время_вставки', 'Время_поиска', 'Время_удаления'])
        writer.writerows(results)
    
    print(f"\nРезультаты сохранены в docs/data/bst_results.csv")
    print(f"\nСравнение:")
    print(f"Случайный порядок вставки: {insert_time1:.4f} сек")
    print(f"Отсортированный порядок вставки: {insert_time2:.4f} сек")
    print(f"Разница: {insert_time2/insert_time1:.1f} раз")

if __name__ == "__main__":
    run_experiment()