defmodule Mix.Tasks.Scrobble.AuditTest do
  use MusicLibrary.DataCase

  import ExUnit.CaptureIO
  import MusicLibrary.ScrobbledTracksFixtures

  alias Mix.Tasks.Scrobble.Audit

  describe "run/1" do
    test "generates audit report with no tracks" do
      output =
        capture_io(fn ->
          Audit.run([])
        end)

      assert output =~ "Scrobbled Tracks Data Quality Audit"
      assert output =~ "Total scrobbled tracks: 0"
    end

    test "raises error for invalid type" do
      assert_raise Mix.Error, ~r/Invalid type/, fn ->
        capture_io(fn ->
          Audit.run(["--type", "invalid"])
        end)
      end
    end

    test "raises error for invalid format" do
      assert_raise Mix.Error, ~r/Invalid format/, fn ->
        capture_io(fn ->
          Audit.run(["--format", "invalid"])
        end)
      end
    end

    test "generates audit report with tracks having missing artist musicbrainz_ids" do
      # Create tracks with empty artist musicbrainz_id
      track_fixture(%{
        artist_name: "Test Artist 1",
        artist_musicbrainz_id: "",
        title: "Track 1"
      })

      track_fixture(%{
        artist_name: "Test Artist 1",
        artist_musicbrainz_id: "",
        title: "Track 2"
      })

      track_fixture(%{
        artist_name: "Test Artist 2",
        artist_musicbrainz_id: "",
        title: "Track 3"
      })

      output =
        capture_io(fn ->
          Audit.run([])
        end)

      assert output =~ "Artists with Missing MusicBrainz IDs"
      assert output =~ "Unique artists: 2"
      assert output =~ "Affected tracks: 3"
      assert output =~ "Test Artist 1"
      assert output =~ "Test Artist 2"
    end

    test "generates audit report with tracks having missing album musicbrainz_ids" do
      # Create tracks with empty album musicbrainz_id
      track_fixture(%{
        album_title: "Test Album 1",
        album_musicbrainz_id: "",
        artist_name: "Test Artist",
        title: "Track 1"
      })

      track_fixture(%{
        album_title: "Test Album 1",
        album_musicbrainz_id: "",
        artist_name: "Test Artist",
        title: "Track 2"
      })

      output =
        capture_io(fn ->
          Audit.run([])
        end)

      assert output =~ "Albums with Missing MusicBrainz IDs"
      assert output =~ "Unique albums: 1"
      assert output =~ "Affected tracks: 2"
      assert output =~ "Test Album 1"
    end

    test "generates audit report with --verbose flag" do
      track_fixture(%{
        artist_name: "Test Artist",
        artist_musicbrainz_id: "",
        title: "Test Track",
        album_title: "Test Album"
      })

      output =
        capture_io(fn ->
          Audit.run(["--verbose"])
        end)

      assert output =~ "Sample tracks:"
      assert output =~ "Test Artist"
      assert output =~ "Test Track"
    end

    test "generates audit report for artists only with --type artist" do
      track_fixture(%{
        artist_name: "Test Artist",
        artist_musicbrainz_id: "",
        album_musicbrainz_id: "",
        title: "Track 1"
      })

      output =
        capture_io(fn ->
          Audit.run(["--type", "artist"])
        end)

      assert output =~ "Artists with Missing MusicBrainz IDs"
      refute output =~ "Albums with Missing MusicBrainz IDs"
    end

    test "generates audit report for albums only with --type album" do
      track_fixture(%{
        album_title: "Test Album",
        album_musicbrainz_id: "",
        artist_musicbrainz_id: "",
        title: "Track 1"
      })

      output =
        capture_io(fn ->
          Audit.run(["--type", "album"])
        end)

      assert output =~ "Albums with Missing MusicBrainz IDs"
      refute output =~ "Artists with Missing MusicBrainz IDs"
    end

    test "generates JSON output with --format json" do
      track_fixture(%{
        artist_name: "Test Artist",
        artist_musicbrainz_id: "",
        title: "Track 1"
      })

      output =
        capture_io(fn ->
          Audit.run(["--format", "json"])
        end)

      assert output =~ ~s("total_tracks")
      assert output =~ ~s("artist_issues")
      assert output =~ ~s("album_issues")

      # Validate it's valid JSON
      assert {:ok, _parsed} = Jason.decode(output)
    end

    test "audit report shows summary with remediation steps" do
      track_fixture(%{
        artist_name: "Test Artist",
        artist_musicbrainz_id: "",
        title: "Track 1"
      })

      output =
        capture_io(fn ->
          Audit.run([])
        end)

      assert output =~ "Summary"
      assert output =~ "To fix these issues:"
      assert output =~ "Create scrobble rules"
      assert output =~ "MusicLibrary.ScrobbleRules.apply_all_rules()"
    end
  end
end
