import pytest
import sys
import os
import copy

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from linked_list import create_linked_list, ll_find, ll_insert, ll_list_all, ll_delete


@pytest.fixture
def test_records():
    return [
        {"name": "Анна", "phone": "89123456789"},
        {"name": "Михаил", "phone": "79223334455"},
        {"name": "Елена", "phone": "4951234567"},
        {"name": "Дмитрий", "phone": "9111112233"},
        {"name": "Ольга", "phone": "81234567890"},
        {"name": "Александр", "phone": "9219998877"},
        {"name": "Татьяна", "phone": "4955556666"},
        {"name": "Иван", "phone": "9034443322"},
        {"name": "Наталья", "phone": "9167778899"},
        {"name": "Павел", "phone": "9256665544"},
        {"name": "Мария", "phone": "4953332211"},
        {"name": "Андрей", "phone": "9264443322"},
        {"name": "Екатерина", "phone": "8125554433"},
        {"name": "Владимир", "phone": "9107778899"},
        {"name": "Юлия", "phone": "4951112233"},
        {"name": "Николай", "phone": "9215556677"},
        {"name": "Светлана", "phone": "9164443322"},
        {"name": "Артем", "phone": "9253334455"},
        {"name": "Ксения", "phone": "4952223344"},
    ]


@pytest.fixture
def linked_list(test_records):
    return create_linked_list(test_records)


def test_create_linked_list(test_records):
    linked_list = create_linked_list(test_records)
    assert linked_list is not None

    temp = linked_list
    index = 0

    while temp.get("next") is not None:
        assert temp.get("phone") == test_records[index].get("phone")
        assert temp.get("name") == test_records[index].get("name")

        temp = temp.get("next")
        index += 1


def test_ll_find(linked_list):
    assert linked_list is not None

    test_list = [
        {"name": "Анна", "phone": "89123456789"},
        {"name": "Андрей", "phone": "9264443322"},
        {"name": "Владимир", "phone": "9107778899"},
        {"name": "Сергей", "phone": None},
        {"name": "Ксения", "phone": "4952223344"},
    ]

    for test in test_list:
        assert ll_find(linked_list, test.get("name")) == test.get("phone")


def test_ll_insert_edit(linked_list, test_records):
    assert linked_list is not None

    test_list = [
        {"name": "Анна", "phone": "89123456745"},
        {"name": "Андрей", "phone": "926444332232"},
        {"name": "Владимир", "phone": "9107778899"},
        {"name": "Ксения", "phone": "4952223344"},
    ]

    for test in test_list:
        test_ll = copy.deepcopy(linked_list)
        result_insert = ll_insert(test_ll, test.get("name"), test.get("phone"))

        # Проверяем наличие изменения номера телефона
        assert ll_find(result_insert, test.get("name")) == test.get("phone")

        # Проверяем правильность места изменения
        for i, value in enumerate(test_records):
            if value.get("name") == test.get("name"):
                assert ll_list_all(result_insert)[i].get("phone") == test.get("phone")
                break


def test_ll_insert_new(linked_list):
    assert linked_list is not None

    new_name = "Новый контакт"
    new_phone = "99999999999"

    test_ll = copy.deepcopy(linked_list)

    result = ll_insert(test_ll, new_name, new_phone)

    assert ll_find(result, new_name) == new_phone

    # Проверяем, что новый элемент в конце
    all_items = ll_list_all(result)
    assert all_items[-1].get("name") == new_name

def test_ll_delete(linked_list, test_records):
    assert linked_list is not None
    
    tests = [
        test_records[0],
        test_records[1],
        test_records[len(test_records) // 2],
        test_records[-2],
        test_records[-1],
        {"name": "Сергей", "phone": "89290504426"},
    ]
    
    for test in tests:
        test_ll = copy.deepcopy(linked_list)
        
        result_delete = ll_delete(test_ll, test.get('name'))
        
        assert ll_find(result_delete, test.get('name')) is None