# frozen_string_literal: true

describe "Uploading files in the composer", type: :system do
  fab!(:current_user) { Fabricate(:user, refresh_auto_groups: true) }

  let(:modal) { PageObjects::Modals::Base.new }
  let(:composer) { PageObjects::Components::Composer.new }
  let(:topic) { PageObjects::Pages::Topic.new }
  let(:cdp) { PageObjects::CDP.new }

  before { sign_in(current_user) }

  it "uploads multiple files at once" do
    visit "/new-topic"
    expect(composer).to be_opened

    file_path_1 = file_from_fixtures("logo.png", "images").path
    file_path_2 = file_from_fixtures("logo.jpg", "images").path
    attach_file([file_path_1, file_path_2]) { composer.click_toolbar_button("upload") }

    expect(composer).to have_no_in_progress_uploads
    expect(composer.preview).to have_css(".image-wrapper", count: 2)
  end

  it "allows cancelling uploads" do
    visit "/new-topic"
    expect(composer).to be_opened

    file_path_1 = file_from_fixtures("huge.jpg", "images").path
    cdp.with_slow_upload do
      attach_file(file_path_1) { composer.click_toolbar_button("upload") }
      expect(composer).to have_in_progress_uploads
      find("#cancel-file-upload").click

      expect(composer).to have_no_in_progress_uploads
      expect(composer.preview).to have_no_css(".image-wrapper")
    end
  end

  context "when video thumbnails are enabled" do
    before do
      SiteSetting.video_thumbnails_enabled = true
      SiteSetting.authorized_extensions += "|mp4"
    end

    it "generates a topic preview thumbnail from the video" do
      visit "/new-topic"
      expect(composer).to be_opened
      topic.fill_in_composer_title("Video upload test")

      file_path_1 = file_from_fixtures("small.mp4", "media").path
      attach_file(file_path_1) { composer.click_toolbar_button("upload") }

      expect(composer).to have_no_in_progress_uploads
      expect(composer.preview).to have_css(".onebox-placeholder-container")

      composer.submit

      expect(find("#topic-title")).to have_content("Video upload test")
      expect(Topic.last.image_upload_id).to eq(Upload.last.id)
    end

    it "generates a thumbnail from the video" do
      visit "/new-topic"
      expect(composer).to be_opened
      topic.fill_in_composer_title("Video upload test")

      file_path_1 = file_from_fixtures("small.mp4", "media").path
      attach_file(file_path_1) { composer.click_toolbar_button("upload") }

      expect(composer).to have_no_in_progress_uploads
      expect(composer.preview).to have_css(".onebox-placeholder-container")

      expect(page).to have_css(
        '.onebox-placeholder-container[style*="background-image"]',
        wait: Capybara.default_max_wait_time,
      )

      composer.submit

      expect(find("#topic-title")).to have_content("Video upload test")

      selector = topic.post_by_number_selector(1)

      expect(page).to have_css(selector)
      within(selector) do
        expect(page).to have_css(".video-placeholder-container[data-thumbnail-src]")
      end
    end

    it "handles a video where dimensions can't be read gracefully" do
      visit "/new-topic"
      expect(composer).to be_opened
      topic.fill_in_composer_title("Zero Width Video Test")

      # Inject JavaScript to mock video dimensions
      page.execute_script <<-JS
        HTMLVideoElement.prototype.__defineGetter__('videoWidth', function() { return 0; });
        HTMLVideoElement.prototype.__defineGetter__('videoHeight', function() { return 0; });
      JS

      file_path_1 = file_from_fixtures("small.mp4", "media").path
      attach_file(file_path_1) { composer.click_toolbar_button("upload") }

      expect(composer).to have_no_in_progress_uploads
      expect(composer.preview).to have_css(".onebox-placeholder-container")

      composer.submit

      expect(find("#topic-title")).to have_content("Zero Width Video Test")

      selector = topic.post_by_number_selector(1)

      expect(page).to have_css(selector)
      within(selector) do
        expect(page).to have_no_css(".video-placeholder-container[data-thumbnail-src]")
      end
    end

    it "handles a video load error gracefully" do
      visit "/new-topic"
      expect(composer).to be_opened
      topic.fill_in_composer_title("Video Load Error Test")

      # Inject JavaScript to simulate an invalid video file that triggers onerror
      page.execute_script <<-JS
        const originalCreateObjectURL = URL.createObjectURL;
        URL.createObjectURL = function(blob) {
          // Simulate an invalid video source by returning a fake object URL
          return 'invalid_video_source.mp4';
        };
      JS

      file_path_1 = file_from_fixtures("small.mp4", "media").path
      attach_file(file_path_1) { composer.click_toolbar_button("upload") }

      expect(composer).to have_no_in_progress_uploads
      expect(composer.preview).to have_css(".onebox-placeholder-container")
    end

    it "shows video player in composer" do
      SiteSetting.enable_diffhtml_preview = true

      visit "/new-topic"
      expect(composer).to be_opened
      topic.fill_in_composer_title("Video upload test")

      file_path_1 = file_from_fixtures("small.mp4", "media").path
      attach_file(file_path_1) { composer.click_toolbar_button("upload") }

      expect(composer).to have_no_in_progress_uploads
      expect(composer.preview).to have_css(".video-container video")

      expect(page).to have_css(
        ".video-container video source[src]",
        visible: false,
        wait: Capybara.default_max_wait_time,
      )
    end
  end

  context "when multiple images are uploaded" do
    it "automatically wraps images in [grid] tags on 3 or more images" do
      visit "/new-topic"
      expect(composer).to be_opened

      file_path_1 = file_from_fixtures("logo.png", "images").path
      file_path_2 = file_from_fixtures("logo.jpg", "images").path
      file_path_3 = file_from_fixtures("downsized.png", "images").path
      attach_file([file_path_1, file_path_2, file_path_3]) do
        composer.click_toolbar_button("upload")
      end

      expect(composer).to have_no_in_progress_uploads
      expect(composer.composer_input.value).to match(
        %r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
      )
    end

    it "does not wrap [grid] tags on less than 3 images" do
      visit "/new-topic"
      expect(composer).to be_opened

      file_path_1 = file_from_fixtures("logo.png", "images").path
      file_path_2 = file_from_fixtures("logo.jpg", "images").path
      attach_file([file_path_1, file_path_2]) { composer.click_toolbar_button("upload") }

      expect(composer).to have_no_in_progress_uploads
      expect(composer.composer_input.value).to match(
        %r{!\[.*?\]\(upload://.*?\).*?!\[.*?\]\(upload://.*?\)}m,
      )
    end

    it "automatically wraps images in [grid] tags even after clearing previous uploads" do
      visit "/new-topic"
      expect(composer).to be_opened

      file_path_1 = file_from_fixtures("logo.png", "images").path
      file_path_2 = file_from_fixtures("logo.jpg", "images").path
      file_path_3 = file_from_fixtures("downsized.png", "images").path
      file_path_4 = file_from_fixtures("logo-dev.png", "images").path
      file_path_5 = file_from_fixtures("large_icon_correct.png", "images").path
      file_path_6 = file_from_fixtures("large_icon_incorrect.png", "images").path

      attach_file([file_path_1, file_path_2, file_path_3]) do
        composer.click_toolbar_button("upload")
      end

      expect(composer).to have_no_in_progress_uploads

      expect(composer.composer_input.value).to match(
        %r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
      )

      composer.clear_content

      attach_file([file_path_4, file_path_5, file_path_6]) do
        composer.click_toolbar_button("upload")
      end

      expect(composer).to have_no_in_progress_uploads
      expect(composer.composer_input.value).to match(
        %r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
      )
    end

    it "does not automatically wrap images in [grid] tags when setting is disabled" do
      visit "/new-topic"
      expect(composer).to be_opened

      file_path_1 = file_from_fixtures("logo.png", "images").path
      file_path_2 = file_from_fixtures("logo.jpg", "images").path
      file_path_3 = file_from_fixtures("downsized.png", "images").path
      attach_file([file_path_1, file_path_2, file_path_3]) do
        composer.click_toolbar_button("upload")
      end

      expect(composer).to have_no_in_progress_uploads
      expect(composer.composer_input.value).to match(
        %r{!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\)}m,
      )
    end

    it "does not automatically wrap images in [grid] tags when uploading inside an existing [grid]" do
      visit "/new-topic"
      expect(composer).to be_opened

      composer.fill_content("[grid]\n\n[/grid]")
      composer.move_cursor_after("[grid]\n")

      file_path_1 = file_from_fixtures("logo.png", "images").path
      file_path_2 = file_from_fixtures("logo.jpg", "images").path
      file_path_3 = file_from_fixtures("downsized.png", "images").path
      attach_file([file_path_1, file_path_2, file_path_3]) do
        composer.click_toolbar_button("upload")
      end
      expect(composer).to have_no_in_progress_uploads
      expect(composer.composer_input.value).to match(
        %r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
      )
    end

    it "automatically wraps images in [grid] when site language is different" do
      SiteSetting.default_locale = "es"

      visit "/new-topic"
      expect(composer).to be_opened

      file_path_1 = file_from_fixtures("logo.png", "images").path
      file_path_2 = file_from_fixtures("logo.jpg", "images").path
      file_path_3 = file_from_fixtures("downsized.png", "images").path
      attach_file([file_path_1, file_path_2, file_path_3]) do
        composer.click_toolbar_button("upload")
      end

      expect(composer).to have_no_in_progress_uploads
      expect(composer.composer_input.value).to match(
        %r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
      )
    end
  end
end