import csv
import random
import time
from spravochnik import *

COUNT = 10000
REPEATS = 5

def make_records():
    records = []
    for i in range(COUNT):
        name = f"User_{i:05d}"
        phone = str(89000000000 + i)
        records.append((name, phone))
    shuffled = records[:]
    random.shuffle(shuffled)
    ordered = sorted(records, key=lambda item: item[0])
    return shuffled, ordered

def make_search_names(records):
    existing = [item[0] for item in random.sample(records, 100)]
    missing = [f"None_{i}" for i in range(10)]
    return existing + missing

def make_delete_names(records):
    return [item[0] for item in random.sample(records, 50)]

def average(values):
    return sum(values) / len(values)

def test_list(records):
    insert_times = []
    find_times = []
    delete_times = []
    for _ in range(REPEATS):
        head = None
        start = time.perf_counter()
        for name, phone in records:
            head = ll_insert(head, name, phone)
        insert_times.append(time.perf_counter() - start)

        search_names = make_search_names(records)
        start = time.perf_counter()
        for name in search_names:
            ll_find(head, name)
        find_times.append(time.perf_counter() - start)

        delete_names = make_delete_names(records)
        start = time.perf_counter()
        for name in delete_names:
            head = ll_delete(head, name)
        delete_times.append(time.perf_counter() - start)

    return insert_times, find_times, delete_times

def test_hash(records):
    insert_times = []
    find_times = []
    delete_times = []
    for _ in range(REPEATS):
        table = ht_create()
        start = time.perf_counter()
        for name, phone in records:
            ht_insert(table, name, phone)
        insert_times.append(time.perf_counter() - start)

        search_names = make_search_names(records)
        start = time.perf_counter()
        for name in search_names:
            ht_find(table, name)
        find_times.append(time.perf_counter() - start)

        delete_names = make_delete_names(records)
        start = time.perf_counter()
        for name in delete_names:
            ht_delete(table, name)
        delete_times.append(time.perf_counter() - start)

    return insert_times, find_times, delete_times

def test_bst(records):
    insert_times = []
    find_times = []
    delete_times = []
    for _ in range(REPEATS):
        root = None
        start = time.perf_counter()
        for name, phone in records:
            root = bst_insert(root, name, phone)
        insert_times.append(time.perf_counter() - start)

        search_names = make_search_names(records)
        start = time.perf_counter()
        for name in search_names:
            bst_find(root, name)
        find_times.append(time.perf_counter() - start)

        delete_names = make_delete_names(records)
        start = time.perf_counter()
        for name in delete_names:
            root = bst_delete(root, name)
        delete_times.append(time.perf_counter() - start)

    return insert_times, find_times, delete_times

def add_rows(rows, structure, mode, result):
    names = ["Вставка", "Поиск", "Удаление"]
    for operation, times in zip(names, result):
        for number, value in enumerate(times, 1):
            rows.append([structure, mode, operation, number, value])
        rows.append([structure, mode, operation, "Среднее", average(times)])

def main():
    shuffled, ordered = make_records()
    rows = [["Структура", "Режим", "Операция", "Замер", "Время (сек)"]]

    print("Связный список, случайный порядок")
    add_rows(rows, "Связный список", "Случайный", test_list(shuffled))

    print("Связный список, отсортированный порядок")
    add_rows(rows, "Связный список", "Отсортированный", test_list(ordered))

    print("Хеш-таблица, случайный порядок")
    add_rows(rows, "Хеш-таблица", "Случайный", test_hash(shuffled))

    print("Хеш-таблица, отсортированный порядок")
    add_rows(rows, "Хеш-таблица", "Отсортированный", test_hash(ordered))

    print("BST, случайный порядок")
    add_rows(rows, "BST", "Случайный", test_bst(shuffled))

    print("BST, отсортированный порядок")
    add_rows(rows, "BST", "Отсортированный", test_bst(ordered))

    with open("raskatovia/docs/data/task1/results.csv", "w", newline="", encoding="utf-8") as file:
        writer = csv.writer(file)
        writer.writerows(rows)

    print("Результаты сохранены в results.csv")

main()