"""Unit tests for LogWriter."""

from os import listdir, remove
from os.path import isfile, join

from time import sleep

from uuid import uuid4
from file_manager.log_writer import LogWriter
from file_manager.log_reader import LogReader
import config

# Prefix for files generated by this function
TEST_ID = str(uuid4())
EMPTY_ID = str(uuid4())
HEADER = ["X", "Y", "pew"]


def test_writer_basic():
    """Basic test for LogWriter class."""
    lw1 = LogWriter(header=HEADER, prefix=TEST_ID)

    dict_to_write = {}
    dict_to_write["X"] = 10
    dict_to_write["pew"] = "pew"
    dict_to_write["Y"] = 20

    lw1.write_line(dict_to_write)
    lw1.write_line(dict_to_write)


def test_prefix_handling():
    """Test prefix validation for LogWriter."""
    # Invalid tab character
    catch_err_1 = False
    try:
        _ = LogWriter(header=["test"], prefix="\test")
    except AttributeError:
        catch_err_1 = True

    assert catch_err_1

    # Invalid backslash
    catch_err_2 = False
    try:
        _ = LogWriter(header=["test"], prefix="/test")
    except AttributeError:
        catch_err_2 = True
    assert catch_err_2

    # Invalid dot character
    catch_err_3 = False
    try:
        _ = LogWriter(header=["test"], prefix=".test")
    except AttributeError:
        catch_err_3 = True
    assert catch_err_3


def test_header_validation():
    """Test logic for checking header."""
    catch_err = False
    try:
        _ = LogWriter(header=[])
    except AttributeError:
        catch_err = True

    assert catch_err


def test_reader_basic():
    """Test basic attributes are set after successful read."""
    log_reader = LogReader(prefix=TEST_ID)

    # We have found a file
    assert log_reader.files
    # It matches the header we use
    assert log_reader.header == HEADER
    # The data has the same number of columns
    assert len(log_reader.data) == len(HEADER)


def test_reader_no_files():
    """Test that reader errors when no matching files are present."""
    try:
        LogReader(prefix=EMPTY_ID)
    except AttributeError:
        return

    assert False


def test_reader_data():
    """Test that the reader reads in the proper data."""
    log_reader = LogReader(prefix=TEST_ID)
    log_reader.read_data()

    assert len(log_reader.data["X0"]) == 2
    assert len(log_reader.data["Y0"]) == 2
    assert len(log_reader.data["pew0"]) == 2


def create_invalid_file():
    """
    Create invalid file to test reader logic.

    This file will have different headers, so it should
    cause LogReader to generate a warning message.
    """
    sleep(0.001)
    lw_invalid = LogWriter(header=HEADER + ["pew2"], prefix=TEST_ID)
    dict_to_write = {}
    dict_to_write["X"] = 10
    dict_to_write["pew"] = "pew"
    dict_to_write["pew2"] = "pew2"
    dict_to_write["Y"] = 20
    lw_invalid.write_line(dict_to_write)
    lw_invalid.write_line(dict_to_write)


def test_reader_data_err():
    """Test that LogReader catches invalid headers."""
    create_invalid_file()
    log_reader = LogReader(prefix=TEST_ID)

    try:
        log_reader.read_data()
    except RuntimeError:
        # Assert data was reset
        assert not log_reader.data["X0"]
        assert not log_reader.data["Y0"]
        assert not log_reader.data["pew0"]
        return

    assert False


def cleanup():
    """Clean up logs for this run."""
    log_files = [f for f in listdir(config.LOG_DIR)
                 if isfile(join(config.LOG_DIR, f))]
    for filename in log_files:
        if filename.startswith(TEST_ID) or filename.startswith(EMPTY_ID):
            remove(join(config.LOG_DIR, filename))


# Run writer test cases
test_writer_basic()
test_prefix_handling()
test_header_validation()

# Run reader test cases
test_reader_basic()
test_reader_no_files()
test_reader_data()
test_reader_data_err()

cleanup()
