require "rails_helper"

RSpec.describe "preview navigation", type: :system do
  before do
    visit lookbook_home_path
  end

  context "preview without annotations" do
    context "with multiple scenarios" do
      let(:preview) { Lookbook::Engine.previews.find_by_id(:unannotated) }
      let(:scenarios) { preview.scenarios }
      let(:preview_item_selector) { "#previews-nav-unannotated" }
      let(:ordered_preview) { Lookbook::Engine.previews.find_by_id(:ordered) }
      let(:ordered_scenarios) { preview.scenarios }

      context "has preview link" do
        it "rendered as a group" do
          within("#previews-nav") do
            expect(page).to have_css("#{preview_item_selector}[data-entity-type=preview]")
          end
        end

        it "with an autogenerated label" do
          expect(page).to have_css(preview_item_selector, text: "Unannotated")
        end

        it "is closed by default" do
          expect(page).to have_css("#{preview_item_selector} > [x-ref=items]", visible: false)
        end

        it "can be toggled to hide/show the scenarios links" do
          button = find("#{preview_item_selector} button")

          [true, false].each do |visible|
            button.click
            expect(page).to have_css("#{preview_item_selector} > [x-ref=items]", visible: visible)
          end
        end
      end

      context "has scenarios" do
        it "with links within the preview item" do
          within(preview_item_selector) do
            scenarios.each do |scenario|
              expect(page).to have_css("#previews-nav-#{scenario.id}[data-entity-type=scenario] a", visible: false)
            end
          end
        end

        it "with autogenerated labels" do
          scenarios.each do |scenario|
            expect(page).to have_css("#previews-nav-#{scenario.id}", text: scenario.name.titleize, visible: false)
          end
        end

        it "which each link to the appropriate scenario" do
          find("#{preview_item_selector} button").click
          scenarios.each do |scenario|
            find("#previews-nav-#{scenario.id} a").click
            expect(page).to have_css("[data-preview-target=#{scenario.id}]")
          end
        end

        context "when scenario sorting is disabled" do
          before { Lookbook.config.preview_sort_scenarios = true }
          after { Lookbook.config.preview_sort_scenarios = false }

          it "that are displayed in the same order as the scenario methods in the preview class" do
            within("#previews-nav") do
              scenario_ids = ordered_scenarios.map { |e| "#previews-nav-#{e.id}" }
              expect(page).to have_css(scenario_ids.join(" + ").to_s, visible: false)
            end
          end
        end

        context "when scenario sorting is enabled" do
          before { Lookbook.config.preview_sort_scenarios = true }
          after { Lookbook.config.preview_sort_scenarios = false }

          it "that are displayed in alphabetical order" do
            within("#previews-nav") do
              scenario_ids = ordered_scenarios.sort_by(&:label).map { |e| "#previews-nav-#{e.id}" }
              expect(page).to have_css(scenario_ids.join(" + ").to_s, visible: false)
            end
          end
        end
      end
    end

    context "with a single scenario" do
      let(:preview) { Lookbook::Engine.previews.find_by_id(:single_unannotated_example) }
      let(:preview_item_selector) { "#previews-nav-single-unannotated-example" }

      context "has preview link" do
        it "rendered as a scenario" do
          within("#previews-nav") do
            expect(page).to have_css("#{preview_item_selector}[data-entity-type=scenario]")
          end
        end

        it "with an autogenerated label based on the preview name" do
          expect(page).to have_css(preview_item_selector.to_s, text: "Unannotated")
        end

        it "which links to the scenario" do
          find("#{preview_item_selector} a").click

          expect(page).to have_css("[data-preview-target=#{preview.default_scenario.id}]")
        end
      end

      it "does not display the scenario as a child item" do
        within(preview_item_selector) do
          expect(page).not_to have_css("[x-ref=items]", visible: false)
          expect(page).not_to have_css("[x-ref=items]", visible: true)
          expect(page).not_to have_css("#previews-nav-#{preview.default_scenario.id}", visible: false)
        end
      end
    end
  end

  context "annotated preview" do
    let(:preview) { Lookbook::Engine.previews.find_by_id(:annotated_test) }
    let(:scenarios) { preview.scenarios }
    let(:preview_item_selector) { "#previews-nav-annotated-test" }

    before do
      click_on("Foo")
      click_on("Bar")
    end

    context "has preview link" do
      it "with an custom label" do
        expect(page).to have_css(preview_item_selector, text: "Annotated Label")
      end
    end

    context "has visible scenarios" do
      let(:visible_scenarios) { scenarios.select { |scenario| !scenario.hidden? } }

      it "with links within the preview item" do
        within(preview_item_selector) do
          visible_scenarios.each do |scenario|
            expect(page).to have_css("#previews-nav-#{scenario.id}[data-entity-type=scenario] a", visible: false)
          end
        end
      end

      it "with labels set by the label tag when present" do
        visible_scenarios.each do |scenario|
          expect(page).to have_css("#{preview_item_selector}-#{scenario.name.tr("_", "-")}",
            text: scenario.tag(:label)&.value || scenario.name.titleize,
            visible: false)
        end
      end

      it "which each link to the appropriate scenario" do
        find("#{preview_item_selector} button").click
        visible_scenarios.each do |scenario|
          find("#previews-nav-#{scenario.id} a").click
          expect(page).to have_css("[data-preview-target=#{scenario.id}]")
        end
      end
    end

    it "does not display hidden scenarios" do
      hidden_scenarios = scenarios.select { |scenario| scenario.hidden? }

      hidden_scenarios.each do |scenario|
        expect(page).not_to have_css("#previews-nav-#{scenario.id}", visible: false)
        expect(page).not_to have_css("#previews-nav-#{scenario.id}", visible: true)
      end
    end
  end
end
