# frozen_string_literal: true

RSpec.describe Onebox::Engine::YoutubeOnebox do
  before do
    stub_request(
      :get,
      "https://www.youtube.com/watch?feature=player_embedded&v=21Lk4YiASMo",
    ).to_return(status: 200, body: onebox_response("youtube"))
    stub_request(:get, "https://youtu.be/21Lk4YiASMo").to_return(
      status: 200,
      body: onebox_response("youtube"),
    )
    stub_request(:get, "https://www.youtube.com/embed/21Lk4YiASMo").to_return(
      status: 200,
      body: onebox_response("youtube"),
    )
    stub_request(:get, "http://www.youtube.com/watch?v=21Lk4YiASMo").to_return(
      status: 200,
      body: onebox_response("youtube"),
    )
    stub_request(:get, "https://www.youtube.com/watch?v=21Lk4YiASMo").to_return(
      status: 200,
      body: onebox_response("youtube"),
    )

    stub_request(:get, "https://www.youtube.com/channel/UCL8ZULXASCc1I_oaOT0NaOQ").to_return(
      status: 200,
      body: onebox_response("youtube-channel"),
    )
    stub_request(:get, "http://www.youtube.com/user/googlechrome").to_return(
      status: 200,
      body: onebox_response("youtube-channel"),
    )

    stub_request(:get, "https://www.youtube.com/playlist?list=PL5308B2E5749D1696").to_return(
      status: 200,
      body: onebox_response("youtube-playlist"),
    )

    stub_request(:get, "https://www.youtube.com/embed/KCyIfcevExE").to_return(
      status: 200,
      body: onebox_response("youtube-embed"),
    )

    stub_request(:get, "https://www.youtube.com/embed/VvoFuaLAslw").to_return(
      status: 200,
      body: onebox_response("youtube-shorts"),
    )
  end

  it "adds wmode=opaque" do
    expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo").to_s).to match(
      /wmode=opaque/,
    )
  end

  it "rewrites URLs for videos to be HTTPS" do
    # match: plain HTTP and protocol agnostic
    regex = %r{(http:|["']//)}

    expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo").to_s).not_to match(regex)
    expect(
      Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo").placeholder_html,
    ).not_to match(regex)
    expect(
      Onebox.preview("https://www.youtube.com/channel/UCL8ZULXASCc1I_oaOT0NaOQ").to_s,
    ).not_to match(regex)
  end

  it "can onebox a channel page" do
    expect(
      Onebox.preview("https://www.youtube.com/channel/UCL8ZULXASCc1I_oaOT0NaOQ").to_s,
    ).to match(/Google Chrome/)
  end

  it "can onebox a playlist" do
    expect(
      Onebox.preview("https://www.youtube.com/playlist?list=PL5308B2E5749D1696").to_s,
    ).to match(/iframe/)
    placeholder_html =
      Onebox.preview("https://www.youtube.com/playlist?list=PL5308B2E5749D1696").placeholder_html
    expect(placeholder_html).to match(/<img/)
    expect(placeholder_html).to include("The web is what you make of it")
  end

  it "does not make HTTP requests unless necessary" do
    # We haven't defined any fixture for requests associated with this ID, so if
    # any HTTP requests are made webmock will complain and the test will fail.
    Onebox.preview("http://www.youtube.com/watch?v=q39Ce3zDScI").to_s
  end

  it "does not fail if we cannot get the video ID from the URL" do
    expect(
      Onebox.preview("http://www.youtube.com/watch?feature=player_embedded&v=21Lk4YiASMo").to_s,
    ).to match(/embed/)
  end

  it "returns an image as the placeholder" do
    expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo").placeholder_html).to match(
      /<img/,
    )
    expect(Onebox.preview("https://youtu.be/21Lk4YiASMo").placeholder_html).to match(/<img/)
  end

  it "passes the playlist ID through" do
    expect(
      Onebox.preview(
        "https://www.youtube.com/watch?v=21Lk4YiASMo&list=UUQau-O2C0kGJpR3_CHBTGbw&index=1",
      ).to_s,
    ).to match(/UUQau-O2C0kGJpR3_CHBTGbw/)
  end

  it "filters out nonsense parameters" do
    expect(
      Onebox.preview(
        "https://www.youtube.com/watch?v=21Lk4YiASMo&potential[]=exploit&potential[]=fun",
      ).to_s,
    ).not_to match(/potential|exploit|fun/)
  end

  it "ignores video_id with unacceptable characters" do
    # (falls back to generic onebox)
    Onebox::Engine::AllowlistedGenericOnebox
      .any_instance
      .stubs(:to_html)
      .returns(+"allowlisted_html")
    expect(Onebox.preview("https://www.youtube.com/watch?v=%3C%3E21Lk4YiASMo").to_s).to eq(
      "allowlisted_html",
    )
  end

  it "ignores list_id with unacceptable characters" do
    # (falls back to video-only onebox)
    expect(
      Onebox.preview(
        "https://www.youtube.com/watch?v=21Lk4YiASMo&list=%3C%3EUUQau-O2C0kGJpR3_CHBTGbw",
      ).to_s,
    ).not_to include("UUQau-O2C0kGJpR3_CHBTGbw")
  end

  it "converts time strings into a &start= parameter" do
    expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo&start=3782").to_s).to match(
      /start=3782/,
    )
    expect(
      Onebox.preview("https://www.youtube.com/watch?start=1h3m2s&v=21Lk4YiASMo").to_s,
    ).to match(/start=3782/)
    expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo&t=1h3m2s").to_s).to match(
      /start=3782/,
    )
    expect(
      Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo&start=1h3m2s").to_s,
    ).to match(/start=3782/)
    expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo#t=1h3m2s").to_s).to match(
      /start=3782/,
    )
  end

  it "allows both start and end" do
    preview =
      expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo&start=2m&end=3m").to_s)
    preview.to match(/start=120/)
    preview.to match(/end=180/)
  end

  it "permits looping videos" do
    preview = expect(Onebox.preview("https://www.youtube.com/watch?v=21Lk4YiASMo&loop").to_s)
    preview.to match(/loop=1/)
    preview.to match(/playlist=21Lk4YiASMo/)
  end

  it "includes title in preview" do
    expect(Onebox.preview("https://youtu.be/21Lk4YiASMo").placeholder_html).to include(
      "96neko - orange",
    )
  end

  it "can parse youtube embed results" do
    preview = expect(Onebox.preview("https://www.youtube.com/watch?v=KCyIfcevExE").placeholder_html)
    preview.to match(/Delvon/)
    preview.to match(/hqdefault/)
  end

  it "can parse youtube shorts results" do
    preview = expect(Onebox.preview("https://youtube.com/shorts/VvoFuaLAslw").placeholder_html)
    preview.to match(/POMBO/)
    preview.to match(/hqdefault/)
  end
end