defmodule Bright.StreamsTest do
  use Bright.DataCase

  alias Bright.Streams
  require Logger

  describe "streams" do
    alias Bright.Streams.Stream

    import Bright.StreamsFixtures

    @invalid_attrs %{date: nil, title: nil, notes: nil}

    test "list_streams/0 returns all streams" do
      stream = stream_fixture()
      assert Streams.list_streams() == [stream]
    end

    test "get_stream!/1 returns the stream with given id" do
      stream = stream_fixture()
      assert Streams.get_stream!(stream.id) == stream
    end

    test "create_stream/1 with valid data creates a stream" do
      valid_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}

      assert {:ok, %Stream{} = stream} = Streams.create_stream(valid_attrs)
      assert stream.date == ~U[2024-12-28 03:31:00Z]
      assert stream.title == "some title"
      assert stream.notes == "some notes"
    end

    test "create_stream/1 with invalid data returns error changeset" do
      assert {:error, %Ecto.Changeset{}} = Streams.create_stream(@invalid_attrs)
    end

    test "update_stream/2 with valid data updates the stream" do
      stream = stream_fixture()

      update_attrs = %{
        date: ~U[2024-12-29 03:31:00Z],
        title: "some updated title",
        notes: "some updated notes"
      }

      assert {:ok, %Stream{} = stream} = Streams.update_stream(stream, update_attrs)
      assert stream.date == ~U[2024-12-29 03:31:00Z]
      assert stream.title == "some updated title"
      assert stream.notes == "some updated notes"
    end

    test "update_stream/2 with invalid data returns error changeset" do
      stream = stream_fixture()
      assert {:error, %Ecto.Changeset{}} = Streams.update_stream(stream, @invalid_attrs)
      assert stream == Streams.get_stream!(stream.id)
    end

    test "delete_stream/1 deletes the stream" do
      stream = stream_fixture()
      assert {:ok, %Stream{}} = Streams.delete_stream(stream)
      assert_raise Ecto.NoResultsError, fn -> Streams.get_stream!(stream.id) end
    end

    test "change_stream/1 returns a stream changeset" do
      stream = stream_fixture()
      assert %Ecto.Changeset{} = Streams.change_stream(stream)
    end
  end

  describe "vods" do
    alias Bright.Streams.Vod

    import Bright.StreamsFixtures
    import Bright.TorrentsFixtures

    @invalid_attrs %{
      stream_id: "this is very invalid",
      s3_cdn_url: nil,
      s3_key: nil,
      s3_bucket: nil,
      torrent: nil
    }

    test "list_vods/0 returns all vods" do
      stream = stream_fixture()
      vod = vod_fixture(%{stream_id: stream.id})
      assert Streams.list_vods() == [vod]
    end

    test "get_vod!/1 returns the vod with given id" do
      torrent = torrent_fixture()
      stream = stream_fixture()
      vod = vod_fixture(%{stream_id: stream.id, torrent_id: torrent.id})
      assert Streams.get_vod!(vod.id) == vod
    end

    test "create_vod/1 with valid data creates a vod" do
      stream = stream_fixture()

      valid_attrs = %{
        stream_id: stream.id,
        s3_cdn_url: "some s3_cdn_url",
        s3_key: "some s3_key",
        s3_bucket: "some s3_bucket",
        torrent: "some torrent"
      }

      assert {:ok, %Vod{} = vod} = Streams.create_vod(valid_attrs)
      Logger.debug("just created vod and the vod is vod=#{inspect(vod)}")
      assert vod.s3_cdn_url == "some s3_cdn_url"
    end

    test "create_vod/1 with invalid data returns error changeset" do
      assert {:error, %Ecto.Changeset{}} = Streams.create_vod(@invalid_attrs)
    end

    test "update_vod/2 with valid data updates the vod" do
      stream = stream_fixture()
      vod = vod_fixture(%{stream_id: stream.id})

      update_attrs = %{
        s3_cdn_url: "some updated s3_cdn_url",
        s3_upload_id: "some updated s3_upload_id",
        s3_key: "some updated s3_key",
        s3_bucket: "some updated s3_bucket"
      }

      assert {:ok, %Vod{} = vod} = Streams.update_vod(vod, update_attrs)
      Logger.debug("Streams.update_vod just ran, and the vod is vod=#{inspect(vod)}")
      assert vod.s3_cdn_url == "some updated s3_cdn_url"
    end

    test "update_vod/2 with invalid data returns error changeset" do
      stream = stream_fixture()
      vod = vod_fixture(%{stream_id: stream.id})
      assert {:error, %Ecto.Changeset{}} = Streams.update_vod(vod, @invalid_attrs)
      assert vod == Streams.get_vod!(vod.id)
    end

    test "delete_vod/1 deletes the vod" do
      stream = stream_fixture()
      vod = vod_fixture(%{stream_id: stream.id})
      assert {:ok, %Vod{}} = Streams.delete_vod(vod)
      assert_raise Ecto.NoResultsError, fn -> Streams.get_vod!(vod.id) end
    end

    test "change_vod/1 returns a vod changeset" do
      stream = stream_fixture()
      vod = vod_fixture(%{stream_id: stream.id})
      assert %Ecto.Changeset{} = Streams.change_vod(vod)
    end
  end

  describe "processing" do
    alias Bright.Streams

    import Bright.StreamsFixtures

    # test "get_duration/1" do
    #   playlist_url = "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8"
    #   stream = stream_fixture()
    #   vod = vod_fixture(%{playlist_url: playlist_url, stream_id: stream.id})
    #   {:ok, duration } = Bright.Streams.get_duration(vod)
    #   assert :ok
    #   assert duration == 3
    # end

    @tag :integration
    @tag :slow
    @tag timeout: 120_000
    test "transmux_to_hls/2" do
      stream = stream_fixture()

      vod =
        vod_fixture(%{
          stream_id: stream.id,
          playlist_url: nil,
          origin_temp_input_url: "https://futureporn-b2.b-cdn.net/test-fixture.ts"
        })

      callback = fn progress -> send(self(), {:progress, progress}) end
      {:ok, updated_vod} = Streams.transmux_to_hls(vod, callback)

      assert :ok
      assert updated_vod.local_path != nil
      # assert_received {:progress, %{stage: :transmuxing, done: 1, total: 1}}
      # assert_received {:progress, %{stage: :persisting, done: 1, total: _}}
      # assert_received {:progress, %{stage: :generating_thumbnail, done: 1, total: 1}}
    end
  end
end