import logging
import pathlib

import pytest

from itunesdb.cli import data
from itunesdb.cli import load
from itunesdb.cli import main
from itunesdb.cli.service import extraction
from itunesdb.cli.service import persistence
from itunesdb.test import retrieval
from itunesdb.test import validate

##############
# parse_args #
##############


def test_parse_valid_args(tmp_path: pathlib.Path):
    xml_location = tmp_path / "a.xml"
    db_location = tmp_path / "b.db"
    raw_args = ["load", "-x", str(xml_location), "-d", str(db_location)]

    args = main.parse_args(raw_args)
    assert args.xml_file_path == xml_location
    assert args.create_db_at == db_location
    assert args.app == load.LoadApp
    assert not args.verbose


def test_parse_no_command_args():
    with pytest.raises(SystemExit):
        main.parse_args([])


########
# main #
########


def test_main(
    single_track_file: pathlib.Path,
    bc_album_single_track: data.Album,
    dub_techno_genre_tree: dict[str, data.Genre],
    tmp_path: pathlib.Path,
):
    db_path = tmp_path / "itunes.db"
    raw_args = ["load", "--from", str(single_track_file), "--to", str(db_path)]
    load_app: load.LoadApp = main.main(raw_args)
    assert isinstance(load_app, load.LoadApp)

    # Extraction
    assert isinstance(load_app.extraction_service, extraction.LXMLExtractionService)
    assert load_app.extraction_service.tracks == bc_album_single_track.tracks

    # Persistence
    assert isinstance(
        load_app.persistence_service, persistence.SQLitePersistenceService
    )
    retrieval_service = retrieval.SQLiteRetrievalService(db_path)
    retrieved_albums = retrieval_service.get_albums()
    assert len(retrieved_albums) == 1
    validate.validate_retrieved_album_matches_source(
        retrieved_albums[0], bc_album_single_track
    )
    retrieved_genres = retrieval_service.get_genres()
    validate.validate_retrieved_genres(retrieved_genres, dub_techno_genre_tree)


#####################
# configure_logging #
#####################


def test_configure_non_verbose_logging():
    # Should not affect formatting or verbosity.
    logger = logging.getLogger("non-verbose")
    formatter = logging.Formatter(fmt="%(asctime)s")

    handler_1 = logging.StreamHandler()
    handler_1.setLevel(logging.ERROR)
    handler_1.setFormatter(formatter)
    logger.addHandler(handler_1)

    handler_2 = logging.StreamHandler()
    handler_2.setLevel(logging.FATAL)
    handler_2.setFormatter(formatter)
    logger.addHandler(handler_2)

    main.configure_logging(False, logger)
    assert handler_1.formatter._fmt == "%(asctime)s"
    assert handler_2.formatter._fmt == "%(asctime)s"
    assert handler_1.level == logging.ERROR
    assert handler_2.level == logging.FATAL


def test_configure_verbose_logging():
    logger = logging.getLogger("verbose")

    handler_1 = logging.StreamHandler()
    handler_1.setLevel(logging.FATAL)
    logger.addHandler(handler_1)

    handler_2 = logging.StreamHandler()
    handler_2.setLevel(logging.FATAL)
    logger.addHandler(handler_2)

    main.configure_logging(True, logger)
    assert handler_1.level == logging.DEBUG
    assert handler_2.level == logging.DEBUG

import logging
import pathlib

import pytest

from itunesdb.cli import data
from itunesdb.cli import load
from itunesdb.cli import main
from itunesdb.cli.service import extraction
from itunesdb.cli.service import persistence
from itunesdb.test import retrieval
from itunesdb.test import validate

##############
# parse_args #
##############


def test_parse_valid_args(tmp_path: pathlib.Path):
    xml_location = tmp_path / "a.xml"
    db_location = tmp_path / "b.db"
    raw_args = ["load", "-x", str(xml_location), "-d", str(db_location)]

    args = main.parse_args(raw_args)
    assert args.xml_file_path == xml_location
    assert args.create_db_at == db_location
    assert args.app == load.LoadApp
    assert not args.verbose


def test_parse_no_command_args():
    with pytest.raises(SystemExit):
        main.parse_args([])


########
# main #
########


def test_main(
    single_track_file: pathlib.Path,
    bc_album_single_track: data.Album,
    dub_techno_genre_tree: dict[str, data.Genre],
    tmp_path: pathlib.Path,
):
    db_path = tmp_path / "itunes.db"
    raw_args = ["load", "--from", str(single_track_file), "--to", str(db_path)]
    load_app: load.LoadApp = main.main(raw_args)
    assert isinstance(load_app, load.LoadApp)

    # Extraction
    assert isinstance(load_app.extraction_service, extraction.LXMLExtractionService)
    assert load_app.extraction_service.tracks == bc_album_single_track.tracks

    # Persistence
    assert isinstance(
        load_app.persistence_service, persistence.SQLitePersistenceService
    )
    retrieval_service = retrieval.SQLiteRetrievalService(db_path)
    retrieved_albums = retrieval_service.get_albums()
    assert len(retrieved_albums) == 1
    validate.validate_retrieved_album_matches_source(
        retrieved_albums[0], bc_album_single_track
    )
    retrieved_genres = retrieval_service.get_genres()
    validate.validate_retrieved_genres(retrieved_genres, dub_techno_genre_tree)


#####################
# configure_logging #
#####################


def test_configure_non_verbose_logging():
    # Should not affect formatting or verbosity.
    logger = logging.getLogger("non-verbose")
    formatter = logging.Formatter(fmt="%(asctime)s")

    handler_1 = logging.StreamHandler()
    handler_1.setLevel(logging.ERROR)
    handler_1.setFormatter(formatter)
    logger.addHandler(handler_1)

    handler_2 = logging.StreamHandler()
    handler_2.setLevel(logging.FATAL)
    handler_2.setFormatter(formatter)
    logger.addHandler(handler_2)

    main.configure_logging(False, logger)
    assert handler_1.formatter._fmt == "%(asctime)s"
    assert handler_2.formatter._fmt == "%(asctime)s"
    assert handler_1.level == logging.ERROR
    assert handler_2.level == logging.FATAL


def test_configure_verbose_logging():
    logger = logging.getLogger("verbose")

    handler_1 = logging.StreamHandler()
    handler_1.setLevel(logging.FATAL)
    logger.addHandler(handler_1)

    handler_2 = logging.StreamHandler()
    handler_2.setLevel(logging.FATAL)
    logger.addHandler(handler_2)

    main.configure_logging(True, logger)
    assert handler_1.level == logging.DEBUG
    assert handler_2.level == logging.DEBUG

############## # parse_args # ############## ######## # main # ######## # Extraction # Persistence ##################### # configure_logging # ##################### # Should not affect formatting or verbosity.