import argparse
import pathlib

import pytest

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

########
# wire #
########


def test_wire_lxml_extraction_service():
    args = argparse.Namespace()
    args.xml_file_path = pathlib.Path().cwd()  # any value will do
    args.create_db_at = None
    app = load.LoadApp()
    app.wire(args)
    assert type(app.extraction_service) == extraction.LXMLExtractionService
    assert app.extraction_service.xml_file_path == pathlib.Path().cwd()


def test_wire_null_extraction_service():
    args = argparse.Namespace()
    args.xml_file_path = None
    args.create_db_at = None
    app = load.LoadApp()
    app.wire(args)
    assert type(app.extraction_service) == extraction.NullExtractionService


def test_wire_sqlite_persistence_service():
    args = argparse.Namespace()
    args.xml_file_path = None
    args.create_db_at = pathlib.Path().cwd()  # any value will do
    app = load.LoadApp()
    app.wire(args)
    assert type(app.persistence_service) == persistence.SQLitePersistenceService
    assert app.persistence_service.db_file_path == pathlib.Path().cwd()


def test_wire_null_persistence_service():
    args = argparse.Namespace()
    args.xml_file_path = None
    args.create_db_at = None
    app = load.LoadApp()
    app.wire(args)
    assert type(app.persistence_service) == persistence.NullPersistenceService


#######
# run #
#######


def test_run_extraction_check_should_fail():
    app = load.LoadApp()
    app.extraction_service = extraction.LXMLExtractionService(pathlib.Path().cwd())
    app.persistence_service = persistence.NullPersistenceService()

    with pytest.raises(SystemExit):
        app.run()


def test_run_persistence_check_should_fail():
    app = load.LoadApp()
    app.extraction_service = extraction.LXMLExtractionService(pathlib.Path().cwd())
    app.persistence_service = persistence.NullPersistenceService()

    with pytest.raises(SystemExit):
        app.run()


def test_run_bad_xml(tmp_path: pathlib.Path):
    file_contents = libxml.build_file("<tttttt<<<<")
    file_path = tmp_path / "lib.xml"
    with file_path.open(mode="w", encoding="UTF-8") as f:
        f.write(file_contents)
    app = load.LoadApp()
    app.extraction_service = extraction.LXMLExtractionService(file_path)
    app.persistence_service = persistence.NullPersistenceService()

    with pytest.raises(SystemExit):
        app.run()


def test_run_should_succeed(
    single_track_file: pathlib.Path,
    bc_album_single_track: data.Album,
    dub_techno_genre_tree: dict[str, data.Genre],
    sqlite_persistence_service: persistence.SQLitePersistenceService,
    sqlite_retrieval_service: retrieval.SQLiteRetrievalService,
):
    app = load.LoadApp()
    app.extraction_service = extraction.LXMLExtractionService(single_track_file)
    app.persistence_service = sqlite_persistence_service
    app.run()

    albums = sqlite_retrieval_service.get_albums()
    assert len(albums) == 1
    validate.validate_retrieved_album_matches_source(albums[0], bc_album_single_track)

    genres = sqlite_retrieval_service.get_genres()
    assert len(genres) == len(dub_techno_genre_tree.values())
    validate.validate_retrieved_genres(genres, dub_techno_genre_tree)
