# typed: false
# frozen_string_literal: true

require "rails_helper"
require "fileutils"
require "securerandom"

RSpec.describe LoadedMedia do
  let(:gif_fixture_path) do
    Rails.root.join("test/fixtures/files/images/e621-5418755-animated.gif").to_s
  end
  let(:jpeg_fixture_path) do
    Rails
      .root
      .join("test/fixtures/files/images/thumb-ac63d9d7-low-quality.jpeg")
      .to_s
  end
  let(:webm_fixture_path) do
    Rails
      .root
      .join("test/fixtures/files/images/e621-5421402-animated.webm")
      .to_s
  end

  let(:thumbnail_options) do
    LoadedMedia::ThumbnailOptions.new(
      width: 100,
      height: 100,
      quality: 95,
      size: :down,
      interlace: true,
      for_frames: [0],
    )
  end

  describe ".from_file" do
    context "with a gif file" do
      it "creates a LoadedMedia::Gif instance" do
        media = LoadedMedia.from_file("image/gif", gif_fixture_path)

        expect(media).to be_a(LoadedMedia::Gif)
        expect(media.num_frames).to eq(37)
      end
    end

    context "with a jpeg file" do
      it "creates a LoadedMedia::StaticImage instance" do
        media = LoadedMedia.from_file("image/jpeg", jpeg_fixture_path)

        expect(media).to be_a(LoadedMedia::StaticImage)
        expect(media.num_frames).to eq(1)
      end
    end

    context "with a webm file" do
      it "creates a LoadedMedia::Webm instance" do
        media = LoadedMedia.from_file("video/webm", webm_fixture_path)

        expect(media).to be_a(LoadedMedia::Webm)
        expect(media.num_frames).to eq(908)
      end
    end

    context "with an unsupported file type" do
      it "returns nil" do
        media = LoadedMedia.from_file("application/pdf", jpeg_fixture_path)

        expect(media).to be_nil
      end
    end
  end

  describe "#write_frame_thumbnail" do
    let(:output_dir) do
      File.join(BlobFile::TMP_DIR, "loaded_media_spec-#{SecureRandom.uuid}")
    end
    before { FileUtils.mkdir_p(output_dir) }
    after { FileUtils.rm_rf(output_dir) }

    def make_output_path(frame)
      File.join(output_dir, "thumbnail-#{frame}-#{SecureRandom.uuid}.jpg")
    end

    context "with a gif file" do
      it "can extract and save a thumbnail" do
        media = LoadedMedia.from_file("image/gif", gif_fixture_path)

        output_path = make_output_path(0)
        media.write_frame_thumbnail(0, output_path, thumbnail_options)

        expect(File.exist?(output_path)).to be true
        expect(File.size(output_path)).to be > 0
      end
    end

    context "with a jpeg file" do
      it "can create and save a thumbnail" do
        media = LoadedMedia.from_file("image/jpeg", jpeg_fixture_path)

        output_path = make_output_path(0)
        media.write_frame_thumbnail(0, output_path, thumbnail_options)

        expect(File.exist?(output_path)).to be true
        expect(File.size(output_path)).to be > 0
      end
    end

    context "with a webm file" do
      it "can extract a frame and save a thumbnail" do
        media = LoadedMedia.from_file("video/webm", webm_fixture_path)

        output_path = make_output_path(0)
        media.write_frame_thumbnail(0, output_path, thumbnail_options)

        expect(File.exist?(output_path)).to be true
        expect(File.size(output_path)).to be > 0
      end

      it "creates different frames" do
        media = LoadedMedia.from_file("video/webm", webm_fixture_path)

        paths =
          [0, 453, media.num_frames - 1].map do |frame|
            output_path = make_output_path(frame)
            media.write_frame_thumbnail(frame, output_path, thumbnail_options)
            output_path
          end

        expect(paths.uniq.length).to eq(3)
        expect(FileUtils.compare_file(paths[0], paths[1])).to be false
        expect(FileUtils.compare_file(paths[0], paths[2])).to be false
        expect(FileUtils.compare_file(paths[1], paths[2])).to be false
      end

      it "works with files that have a strange last frame" do
        media =
          LoadedMedia.from_file(
            "video/webm",
            Rails
              .root
              .join("test/fixtures/files/images/last-frame-weird-ts.webm")
              .to_s,
          )

        paths =
          [0, 50, media.num_frames - 1].map do |frame|
            output_path = make_output_path(frame)
            media.write_frame_thumbnail(frame, output_path, thumbnail_options)
            output_path
          end

        expect(paths.uniq.length).to eq(3)
        expect(FileUtils.compare_file(paths[0], paths[1])).to be false
        expect(FileUtils.compare_file(paths[0], paths[2])).to be false
        expect(FileUtils.compare_file(paths[1], paths[2])).to be false
      end
    end
  end
end
