"""Tests for HomeIntegrationHelpers — all 8 integration checks + resolve_source."""

import pytest
from unittest.mock import MagicMock

from services.home.integration_helpers import HomeIntegrationHelpers


def _make_prefs(**overrides):
    prefs = MagicMock()

    lb = MagicMock()
    lb.enabled = overrides.get("lb_enabled", True)
    lb.username = overrides.get("lb_username", "testuser")
    lb.user_token = "tok"
    prefs.get_listenbrainz_connection.return_value = lb

    jf = MagicMock()
    jf.enabled = overrides.get("jf_enabled", False)
    jf.jellyfin_url = overrides.get("jf_url", "")
    jf.api_key = overrides.get("jf_api_key", "")
    prefs.get_jellyfin_connection.return_value = jf

    lidarr = MagicMock()
    lidarr.lidarr_url = overrides.get("lidarr_url", "")
    lidarr.lidarr_api_key = overrides.get("lidarr_api_key", "")
    prefs.get_lidarr_connection.return_value = lidarr

    yt = MagicMock()
    yt.enabled = overrides.get("yt_enabled", False)
    yt.api_enabled = overrides.get("yt_api_enabled", False)
    yt.has_valid_api_key = MagicMock(return_value=overrides.get("yt_valid_key", False))
    prefs.get_youtube_connection.return_value = yt

    lf = MagicMock()
    lf.enabled = overrides.get("lf_enabled", False)
    lf.music_path = overrides.get("lf_music_path", "")
    prefs.get_local_files_connection.return_value = lf

    nd = MagicMock()
    nd.enabled = overrides.get("nd_enabled", False)
    nd.navidrome_url = overrides.get("nd_url", "")
    nd.username = overrides.get("nd_username", "")
    nd.password = overrides.get("nd_password", "")
    prefs.get_navidrome_connection.return_value = nd

    lfm = MagicMock()
    lfm.enabled = overrides.get("lfm_enabled", False)
    lfm.username = overrides.get("lfm_username", "")
    prefs.get_lastfm_connection.return_value = lfm
    prefs.is_lastfm_enabled.return_value = overrides.get("lfm_enabled", False)

    source = MagicMock()
    source.source = overrides.get("primary_source", "listenbrainz")
    prefs.get_primary_music_source.return_value = source

    return prefs


class TestIntegrationFlags:
    def test_listenbrainz_enabled(self):
        h = HomeIntegrationHelpers(_make_prefs(lb_enabled=True, lb_username="u"))
        assert h.is_listenbrainz_enabled() is True

    def test_listenbrainz_disabled_no_username(self):
        h = HomeIntegrationHelpers(_make_prefs(lb_enabled=True, lb_username=""))
        assert h.is_listenbrainz_enabled() is False

    def test_jellyfin_enabled(self):
        h = HomeIntegrationHelpers(
            _make_prefs(jf_enabled=True, jf_url="http://jf", jf_api_key="key")
        )
        assert h.is_jellyfin_enabled() is True

    def test_jellyfin_disabled_missing_url(self):
        h = HomeIntegrationHelpers(
            _make_prefs(jf_enabled=True, jf_url="", jf_api_key="key")
        )
        assert h.is_jellyfin_enabled() is False

    def test_lidarr_configured(self):
        h = HomeIntegrationHelpers(
            _make_prefs(lidarr_url="http://l", lidarr_api_key="k")
        )
        assert h.is_lidarr_configured() is True

    def test_lidarr_not_configured(self):
        h = HomeIntegrationHelpers(_make_prefs())
        assert h.is_lidarr_configured() is False

    def test_youtube_enabled(self):
        h = HomeIntegrationHelpers(_make_prefs(yt_enabled=True))
        assert h.is_youtube_enabled() is True

    def test_youtube_api_enabled(self):
        h = HomeIntegrationHelpers(
            _make_prefs(yt_enabled=True, yt_api_enabled=True, yt_valid_key=True)
        )
        assert h.is_youtube_api_enabled() is True

    def test_local_files_enabled(self):
        h = HomeIntegrationHelpers(
            _make_prefs(lf_enabled=True, lf_music_path="/music")
        )
        assert h.is_local_files_enabled() is True

    def test_navidrome_enabled(self):
        h = HomeIntegrationHelpers(
            _make_prefs(
                nd_enabled=True, nd_url="http://nd", nd_username="u", nd_password="p"
            )
        )
        assert h.is_navidrome_enabled() is True

    def test_navidrome_disabled_missing_password(self):
        h = HomeIntegrationHelpers(
            _make_prefs(nd_enabled=True, nd_url="http://nd", nd_username="u", nd_password="")
        )
        assert h.is_navidrome_enabled() is False

    def test_lastfm_enabled(self):
        h = HomeIntegrationHelpers(_make_prefs(lfm_enabled=True))
        assert h.is_lastfm_enabled() is True


class TestResolveSource:
    def test_explicit_listenbrainz(self):
        h = HomeIntegrationHelpers(
            _make_prefs(lb_enabled=True, lb_username="u", primary_source="lastfm")
        )
        assert h.resolve_source("listenbrainz") == "listenbrainz"

    def test_explicit_lastfm(self):
        h = HomeIntegrationHelpers(
            _make_prefs(lfm_enabled=True, primary_source="listenbrainz")
        )
        assert h.resolve_source("lastfm") == "lastfm"

    def test_none_uses_global(self):
        h = HomeIntegrationHelpers(_make_prefs(primary_source="lastfm", lfm_enabled=True))
        assert h.resolve_source(None) == "lastfm"

    def test_fallback_to_lastfm_when_lb_disabled(self):
        h = HomeIntegrationHelpers(
            _make_prefs(
                lb_enabled=False, lb_username="", lfm_enabled=True, primary_source="listenbrainz"
            )
        )
        assert h.resolve_source(None) == "lastfm"

    def test_fallback_to_lb_when_lfm_disabled(self):
        h = HomeIntegrationHelpers(
            _make_prefs(
                lb_enabled=True, lb_username="u", lfm_enabled=False, primary_source="lastfm"
            )
        )
        assert h.resolve_source(None) == "listenbrainz"


class TestExecuteTasks:
    @pytest.mark.asyncio
    async def test_execute_tasks_returns_results(self):
        h = HomeIntegrationHelpers(_make_prefs())

        async def task_a():
            return "a_result"

        async def task_b():
            return "b_result"

        results = await h.execute_tasks({"a": task_a(), "b": task_b()})
        assert results["a"] == "a_result"
        assert results["b"] == "b_result"

    @pytest.mark.asyncio
    async def test_execute_tasks_handles_failures(self):
        h = HomeIntegrationHelpers(_make_prefs())

        async def good():
            return "ok"

        async def bad():
            raise ValueError("boom")

        results = await h.execute_tasks({"good": good(), "bad": bad()})
        assert results["good"] == "ok"
        assert results["bad"] is None

    @pytest.mark.asyncio
    async def test_execute_tasks_empty(self):
        h = HomeIntegrationHelpers(_make_prefs())
        results = await h.execute_tasks({})
        assert results == {}
