# frozen_string_literal: true

shared_examples "sorted moderations" do
  let!(:moderations) do
    reportables.first(reportables.length - 1).map do |reportable|
      moderation = create(:moderation, reportable:, report_count: 1, reported_content: reportable.reported_searchable_content_text)
      create(:report, moderation:)
      moderation
    end
  end
  let!(:moderation) { moderations.first }
  let(:moderations_link_text) { "Moderations" }
  let(:moderations_link_in_admin_menu) { true }

  before do
    visit participatory_space_path
    if moderations_link_in_admin_menu
      within_admin_sidebar_menu { click_on(moderations_link_text) }
    else
      within("div.layout-nav") { click_on(moderations_link_text) }
    end
  end

  it "sorts the most recent first" do
    link_text = find("ul[data-pages]").text.split("\n")[-2]
    within "ul[data-pages]" do
      click_on link_text
    end
    all("tbody tr").each_with_index do |row, _index|
      expect(row.find("td:nth-child(2)")).to have_content(reportables.first.id)
    end
  end
end

shared_examples "manage moderations" do
  let!(:moderations) do
    reportables.first(reportables.length - 1).map do |reportable|
      moderation = create(:moderation, reportable:, report_count: 1, reported_content: reportable.reported_searchable_content_text)
      create(:report, moderation:)
      moderation
    end
  end
  let!(:moderation) { moderations.first }
  let!(:hidden_moderations) do
    reportables.last(1).map do |reportable|
      moderation = create(:moderation, reportable:, report_count: 3, reported_content: reportable.reported_searchable_content_text, hidden_at: Time.current)
      create_list(:report, 3, moderation:, reason: :spam)
      moderation
    end
  end
  let(:moderations_link_text) { "Moderations" }
  let(:moderations_link_in_admin_menu) { true }

  before do
    visit participatory_space_path
    if moderations_link_in_admin_menu
      within_admin_sidebar_menu { click_on(moderations_link_text) }
    else
      within("div.layout-nav") { click_on(moderations_link_text) }
    end
  end

  context "when listing moderations" do
    it "only lists moderations for the current organization" do
      external_reportable = create(:dummy_resource)
      external_moderation = create(:moderation, reportable: external_reportable, report_count: 1, reported_content: external_reportable.reported_searchable_content_text)
      create(:report, moderation: external_moderation)

      visit current_path

      expect(page).to have_no_css("tr[data-id=\"#{external_moderation.id}\"]")
    end

    it "user can review them" do
      moderations.each do |moderation|
        within "tr[data-id=\"#{moderation.id}\"]" do
          expect(page).to have_css("a[href='#{moderation.reportable.reported_content_url}']")
          expect(page).to have_content "Spam"
        end
      end
    end

    it "user can un-report a resource" do
      within "tr[data-id=\"#{moderation.id}\"]" do
        find("button[data-controller='dropdown']").click
        click_on "Undo the report"
      end

      expect(page).to have_admin_callout("Resource successfully unreported")
    end

    it "user can hide a resource" do
      within "tr[data-id=\"#{moderation.id}\"]" do
        find("button[data-controller='dropdown']").click
        click_on "Hide"
      end

      expect(page).to have_admin_callout("Resource successfully hidden")
      expect(page).to have_no_content(moderation.reportable.reported_content_url)
    end

    it "user can sort by report count" do
      moderations.each_with_index { |moderation, index| moderation.update(report_count: index + 1) }
      moderations_ordered_by_report_count_asc = moderations.sort_by(&:report_count)

      within "table" do
        click_on "Reports count"

        all("tbody tr").each_with_index do |row, index|
          reportable_id = moderations_ordered_by_report_count_asc[index].reportable.id
          expect(row.find("td:nth-child(2)")).to have_content(reportable_id)
        end
      end
    end

    it "user can filter by reportable type" do
      reportable_type = moderation.reportable.class.name.demodulize
      within ".filters__section" do
        click_on "Filter"
        click_on "Type"
        click_on reportable_type
      end
      expect(page).to have_css("tbody tr", count: moderations.length)
    end

    it "user can filter by reported content" do
      search = moderation.reportable.id
      within ".filters__section" do
        fill_in("Search moderation by reportable id or content", with: search)
        within(".input-group-button") { click_on(class: "text-secondary") }
      end
      expect(page).to have_css("tbody tr", count: 1)
    end

    it "user can see moderation details" do
      within "tr[data-id=\"#{moderation.id}\"]" do
        find("button[data-controller='dropdown']").click
        click_on "Expand"
      end

      reported_content_slice = moderation.reportable.reported_searchable_content_text.split("\n").first
      expect(page).to have_content(reported_content_slice)
    end

    context "when the reported content does not exist" do
      it "still renders the page" do
        moderation.reportable.destroy
        visit current_path

        expect(page).to have_no_css("tr[data-id=\"#{moderation.id}\"]")
      end
    end

    context "when the user changes language" do
      around do |example|
        previous_backend = I18n.backend
        I18n.backend = I18n::Backend::Simple.new
        example.run
        I18n.backend = previous_backend
      end

      before do
        I18n.backend.store_translations(
          :ca,
          activerecord: {
            models: {
              moderation.reportable.class.name.underscore.to_sym => {
                one: "Objecte informable",
                other: "Objectes informables"
              }
            }
          }
        )

        within_language_menu(admin: true) do
          click_on "Català"
        end
      end

      it "renders the reportable types in the selected language" do
        within "tr[data-id=\"#{moderation.id}\"]" do
          expect(page).to have_content("Objecte informable")
        end
      end
    end
  end

  context "when listing hidden resources" do
    before do
      click_on "Hidden"
    end

    it "user cannot unreport them" do
      within "tr[data-id=\"#{hidden_moderations.first.id}\"]" do
        find("button[data-controller='dropdown']").click
        expect(page).to have_no_css("a", text: "Undo the report")
      end
    end

    it "user can review them" do
      hidden_moderations.each do |moderation|
        within "tr[data-id=\"#{moderation.id}\"]" do
          expect(page).to have_css("a[href='#{moderation.reload.reportable.reported_content_url}']")
        end
      end
    end
  end

  context "when listing comments for deleted resources" do
    let(:comments) do
      reportables.first(reportables.length - 1).map do |resource|
        create(:comment, commentable: resource)
      end
    end
    let!(:moderations) do
      comments.map do |reportable|
        space = reportable.is_a?(Decidim::Participable) ? reportable : reportable.participatory_space
        moderation = create(:moderation, reportable:, report_count: 1, participatory_space: space, reported_content: reportable.reported_searchable_content_text)
        create(:report, moderation:)

        reportable.root_commentable.destroy!
        reportable.reload

        moderation
      end
    end

    it "user can review them" do
      moderations.each do |moderation|
        within "tr[data-id=\"#{moderation.id}\"]" do
          expect(page).to have_content "Deleted resource"
          expect(page).to have_content "Spam"
        end
      end
    end

    it "user can hide them" do
      moderation_id = moderations.first.id
      within "tr[data-id=\"#{moderation_id}\"]" do
        find("button[data-controller='dropdown']").click
        click_on "Hide"
      end

      expect(page).to have_admin_callout("Resource successfully hidden")
      expect(page).to have_no_css("tr[data-id=\"#{moderation_id}\"]")
    end
  end
end
