# frozen_string_literal: true

RSpec.describe Admin::SiteTextsController do
  fab!(:admin)
  fab!(:moderator)
  fab!(:user)
  let(:default_locale) { I18n.locale }

  after do
    TranslationOverride.delete_all
    I18n.reload!
  end

  describe "#index" do
    context "when logged in as an admin" do
      before { sign_in(admin) }

      it "returns json" do
        get "/admin/customize/site_texts.json", params: { q: "title", locale: default_locale }
        expect(response.status).to eq(200)
        expect(response.parsed_body["site_texts"]).to include(include("id" => "title"))
      end

      it "sets has_more to true if more than 50 results were found" do
        get "/admin/customize/site_texts.json", params: { q: "e", locale: default_locale }
        expect(response.status).to eq(200)
        expect(response.parsed_body["site_texts"].size).to eq(50)
        expect(response.parsed_body["extras"]["has_more"]).to be_truthy
      end

      it "works with pages" do
        texts = Set.new

        get "/admin/customize/site_texts.json", params: { q: "e", locale: default_locale }
        response.parsed_body["site_texts"].each { |text| texts << text["id"] }
        expect(texts.size).to eq(50)

        get "/admin/customize/site_texts.json", params: { q: "e", page: 1, locale: default_locale }
        response.parsed_body["site_texts"].each { |text| texts << text["id"] }
        expect(texts.size).to eq(100)
      end

      it "works with locales" do
        get "/admin/customize/site_texts.json", params: { q: "yes_value", locale: default_locale }
        value =
          response.parsed_body["site_texts"].find { |text| text["id"] == "js.yes_value" }["value"]
        expect(value).to eq(I18n.t("js.yes_value", locale: default_locale))

        get "/admin/customize/site_texts.json", params: { q: "yes_value", locale: "de" }
        value =
          response.parsed_body["site_texts"].find { |text| text["id"] == "js.yes_value" }["value"]
        expect(value).to eq(I18n.t("js.yes_value", locale: :de))
      end

      it "can return the value of the translation in the selected locale rather than English if specified" do
        SiteSetting.default_locale = "it"
        get "/admin/customize/site_texts.json",
            params: {
              q: "all tags",
              locale: "it",
              only_selected_locale: true,
            }
        value =
          response.parsed_body["site_texts"].find do |text|
            text["id"] == "js.topic.browse_all_tags_or_latest"
          end[
            "value"
          ]
        expect(value).to eq(I18n.t("js.topic.browse_all_tags_or_latest", locale: "it"))
      end

      it "returns an error on invalid locale" do
        get "/admin/customize/site_texts.json", params: { locale: "?" }
        expect(response.status).to eq(400)
      end

      it "returns an error on empty locale" do
        get "/admin/customize/site_texts.json"
        expect(response.status).to eq(400)
      end

      it "normalizes quotes during search" do
        value = "“That’s a ‘magic’ sock.”"
        put "/admin/customize/site_texts/title.json",
            params: {
              site_text: {
                value: value,
                locale: default_locale,
              },
            }

        [
          "That's a 'magic' sock.",
          "That’s a ‘magic’ sock.",
          "“That's a 'magic' sock.”",
          %q|"That's a 'magic' sock."|,
          "«That's a 'magic' sock.»",
          "„That’s a ‚magic‘ sock.“",
        ].each do |search_term|
          get "/admin/customize/site_texts.json", params: { q: search_term, locale: default_locale }
          expect(response.status).to eq(200)
          expect(response.parsed_body["site_texts"]).to include(
            include("id" => "title", "value" => value),
          )
        end
      end

      it "normalizes ellipsis" do
        value = "Loading Discussion…"
        put "/admin/customize/site_texts/embed.loading.json",
            params: {
              site_text: {
                value: value,
                locale: default_locale,
              },
            }

        ["Loading Discussion", "Loading Discussion...", "Loading Discussion…"].each do |search_term|
          get "/admin/customize/site_texts.json", params: { q: search_term, locale: default_locale }
          expect(response.status).to eq(200)
          expect(response.parsed_body["site_texts"]).to include(
            include("id" => "embed.loading", "value" => value),
          )
        end
      end

      it "does not return overrides for keys that do not exist in English" do
        allow_missing_translations do
          SiteSetting.default_locale = :ru
          TranslationOverride.create!(
            locale: :ru,
            translation_key: "missing_plural_key.one",
            value: "ONE",
          )
          TranslationOverride.create!(
            locale: :ru,
            translation_key: "another_missing_key",
            value: "foo",
          )

          get "/admin/customize/site_texts.json",
              params: {
                q: "missing_plural_key",
                locale: default_locale,
              }
          expect(response.status).to eq(200)
          expect(response.parsed_body["site_texts"]).to be_empty

          get "/admin/customize/site_texts.json",
              params: {
                q: "another_missing_key",
                locale: default_locale,
              }
          expect(response.status).to eq(200)
          expect(response.parsed_body["site_texts"]).to be_empty
        end
      end

      it "returns site text from fallback locale if current locale doesn't have a translation" do
        TranslationOverride.upsert!(
          :en,
          "js.summary.description_time_MF",
          "description_time_MF override",
        )
        TranslationOverride.upsert!(:en, "education.new-topic", "education.new-topic override")

        get "/admin/customize/site_texts.json",
            params: {
              q: "js.summary.description_time_MF",
              locale: "en_GB",
            }
        expect(response.status).to eq(200)
        value =
          response.parsed_body["site_texts"].find do |text|
            text["id"] == "js.summary.description_time_MF"
          end[
            "value"
          ]
        expect(value).to eq("description_time_MF override")

        get "/admin/customize/site_texts.json",
            params: {
              q: "education.new-topic",
              locale: "en_GB",
            }
        expect(response.status).to eq(200)
        value =
          response.parsed_body["site_texts"].find { |text| text["id"] == "education.new-topic" }[
            "value"
          ]
        expect(value).to eq("education.new-topic override")
      end

      it "returns only overridden translations" do
        TranslationOverride.upsert!(:en, "education.new-topic", "education.new-topic override")

        get "/admin/customize/site_texts.json", params: { locale: "en", overridden: true }
        expect(response.status).to eq(200)

        site_texts = response.parsed_body["site_texts"]
        expect(site_texts.size).to eq(1)

        value = site_texts.find { |text| text["id"] == "education.new-topic" }["value"]
        expect(value).to eq("education.new-topic override")
      end

      it "returns only untranslated (english) strings" do
        available_locales = I18n.config.available_locales
        I18n.config.available_locales = %i[en test]

        I18n.backend.store_translations(:en, { shrubbery: "Shrubbery" })
        I18n.backend.store_translations(:en, { shrubbery2: "Shrubbery2" })

        params = { q: "shrubbery", locale: "test", untranslated: "true" }

        get "/admin/customize/site_texts.json", params: params
        expect(response.status).to eq(200)
        expect(response.parsed_body["site_texts"].size).to eq(2)

        I18n.backend.store_translations(:test, { shrubbery: "Arbusto" })

        get "/admin/customize/site_texts.json", params: params
        expect(response.status).to eq(200)
        expect(response.parsed_body["site_texts"].size).to eq(1)

        TranslationOverride.upsert!(:test, "shrubbery2", "Arbusto2")

        get "/admin/customize/site_texts.json", params: params
        expect(response.status).to eq(200)
        expect(response.parsed_body["site_texts"].size).to eq(0)
      ensure
        I18n.config.available_locales = nil
      end

      context "with plural keys" do
        before do
          I18n.backend.store_translations(
            :en,
            colour: {
              one: "%{count} colour",
              other: "%{count} colours",
            },
          )
        end

        shared_examples "finds correct plural keys" do
          it "finds the correct plural keys for the locale" do
            SiteSetting.default_locale = locale

            get "/admin/customize/site_texts.json", params: { q: "colour", locale: locale }
            expect(response.status).to eq(200)

            json = ::JSON.parse(response.body, symbolize_names: true)
            expect(json).to be_present

            site_texts = json[:site_texts]
            expect(site_texts).to be_present

            expected_search_result =
              expected_translations.map do |key, value|
                overridden =
                  defined?(expected_overridden) ? expected_overridden[key] || false : false
                interpolation_keys =
                  (
                    if defined?(expected_interpolation_keys)
                      expected_interpolation_keys[key] || []
                    else
                      []
                    end
                  )
                {
                  id: "colour.#{key}",
                  value: value,
                  status: "up_to_date",
                  old_default: nil,
                  new_default: nil,
                  can_revert: overridden,
                  overridden: overridden,
                  interpolation_keys: interpolation_keys,
                  has_interpolation_keys: interpolation_keys.present?,
                }
              end

            expect(site_texts).to match_array(expected_search_result)
          end
        end

        context "with English" do
          let(:locale) { :en }
          let(:expected_translations) { { one: "%{count} colour", other: "%{count} colours" } }
          let(:expected_interpolation_keys) { { one: ["count"], other: ["count"] } }

          include_examples "finds correct plural keys"
        end

        context "with language with different plural keys and missing translations" do
          let(:locale) { :ru }
          let(:expected_translations) do
            {
              one: "%{count} colour",
              few: "%{count} colours",
              many: "%{count} colours",
              other: "%{count} colours",
            }
          end
          let(:expected_interpolation_keys) do
            { one: ["count"], few: ["count"], many: ["count"], other: ["count"] }
          end

          include_examples "finds correct plural keys"
        end

        context "with language with different plural keys and partial translation" do
          before do
            I18n.backend.store_translations(
              :ru,
              colour: {
                few: "%{count} цвета",
                many: "%{count} цветов",
              },
            )
          end

          let(:locale) { :ru }
          let(:expected_translations) do
            {
              one: "%{count} colour",
              few: "%{count} цвета",
              many: "%{count} цветов",
              other: "%{count} colours",
            }
          end
          let(:expected_interpolation_keys) do
            { one: ["count"], few: ["count"], many: ["count"], other: ["count"] }
          end

          include_examples "finds correct plural keys"
        end

        context "with overridden translation not in original translation" do
          before do
            I18n.backend.store_translations(
              :ru,
              colour: {
                few: "%{count} цвета",
                many: "%{count} цветов",
              },
            )
            TranslationOverride.create!(locale: :ru, translation_key: "colour.one", value: "ONE")
            TranslationOverride.create!(locale: :ru, translation_key: "colour.few", value: "FEW")
          end

          let(:locale) { :ru }
          let(:expected_translations) do
            { one: "ONE", few: "FEW", many: "%{count} цветов", other: "%{count} colours" }
          end
          let(:expected_interpolation_keys) do
            { one: ["count"], few: ["count"], many: ["count"], other: ["count"] }
          end
          let(:expected_overridden) { { one: true, few: true } }

          include_examples "finds correct plural keys"
        end
      end
    end

    shared_examples "site texts inaccessible" do
      it "denies access with a 404 response" do
        get "/admin/customize/site_texts.json", params: { q: "title", locale: default_locale }

        expect(response.status).to eq(404)
        expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
      end
    end

    context "when logged in as a moderator" do
      before { sign_in(moderator) }

      include_examples "site texts inaccessible"
    end

    context "when logged in as a non-staff user" do
      before { sign_in(user) }

      include_examples "site texts inaccessible"
    end
  end

  describe "#show" do
    context "when logged in as an admin" do
      before { sign_in(admin) }

      it "returns a site text for a key that exists" do
        get "/admin/customize/site_texts/js.topic.list.json", params: { locale: default_locale }
        expect(response.status).to eq(200)

        json = response.parsed_body

        site_text = json["site_text"]

        expect(site_text["id"]).to eq("js.topic.list")
        expect(site_text["value"]).to eq(I18n.t("js.topic.list"))
      end

      it "returns a site text for a key with ampersand" do
        get "/admin/customize/site_texts/js.emoji_picker.food_&_drink.json",
            params: {
              locale: default_locale,
            }
        expect(response.status).to eq(200)

        json = response.parsed_body

        site_text = json["site_text"]

        expect(site_text["id"]).to eq("js.emoji_picker.food_&_drink")
        expect(site_text["value"]).to eq(I18n.t("js.emoji_picker.food_&_drink"))
      end

      it "returns not found for missing keys" do
        get "/admin/customize/site_texts/made_up_no_key_exists.json",
            params: {
              locale: default_locale,
            }
        expect(response.status).to eq(404)
      end

      it "returns overridden = true if there is a translation_overrides record for the key" do
        key = "js.topic.list"
        put "/admin/customize/site_texts/#{key}.json",
            params: {
              site_text: {
                value: I18n.t(key, locale: default_locale),
                locale: default_locale,
              },
            }
        expect(response.status).to eq(200)

        get "/admin/customize/site_texts/#{key}.json", params: { locale: default_locale }
        expect(response.status).to eq(200)
        json = response.parsed_body
        expect(json["site_text"]["overridden"]).to eq(true)

        TranslationOverride.destroy_all

        get "/admin/customize/site_texts/#{key}.json", params: { locale: default_locale }
        expect(response.status).to eq(200)
        json = response.parsed_body
        expect(json["site_text"]["overridden"]).to eq(false)
      end

      it "returns a site text in the given locale" do
        get "/admin/customize/site_texts/js.topic.list.json", params: { locale: "es" }
        expect(response.status).to eq(200)

        json = response.parsed_body
        site_text = json["site_text"]

        expect(site_text["id"]).to eq("js.topic.list")
        expect(site_text["value"]).to eq(I18n.t("js.topic.list", locale: :es))
      end

      it "fails if locale is not given" do
        get "/admin/customize/site_texts/js.topic.list.json"
        expect(response.status).to eq(400)
      end

      it "returns site text from fallback locale if current locale doesn't have a translation" do
        TranslationOverride.upsert!(
          :en,
          "js.summary.description_time_MF",
          "description_time_MF override",
        )
        TranslationOverride.upsert!(:en, "education.new-topic", "education.new-topic override")

        get "/admin/customize/site_texts/js.summary.description_time_MF.json",
            params: {
              locale: "en_GB",
            }
        expect(response.status).to eq(200)

        json = response.parsed_body
        site_text = json["site_text"]

        expect(site_text["id"]).to eq("js.summary.description_time_MF")
        expect(site_text["value"]).to eq("description_time_MF override")

        get "/admin/customize/site_texts/education.new-topic.json", params: { locale: "en_GB" }
        expect(response.status).to eq(200)

        json = response.parsed_body
        site_text = json["site_text"]

        expect(site_text["id"]).to eq("education.new-topic")
        expect(site_text["value"]).to eq("education.new-topic override")
      end

      it "includes custom interpolation keys" do
        TranslationOverride.upsert!(
          :en,
          "system_messages.welcome_user.title",
          "system_messages.welcome_user.title override",
        )

        get "/admin/customize/site_texts/system_messages.welcome_user.title.json",
            params: {
              locale: "en_GB",
            }
        expect(response.status).to eq(200)
        json = response.parsed_body

        expect(json["site_text"]["interpolation_keys"]).to include(
          "username",
          "name",
          "name_or_username",
        )
      end

      context "with plural keys" do
        before do
          I18n.backend.store_translations(
            :en,
            colour: {
              one: "%{count} colour",
              other: "%{count} colours",
            },
          )
        end

        shared_examples "has correct plural keys" do
          it "returns the correct plural keys for the locale" do
            expected_translations.each do |key, value|
              id = "colour.#{key}"

              get "/admin/customize/site_texts/#{id}.json", params: { locale: locale }
              expect(response.status).to eq(200)

              json = response.parsed_body
              expect(json).to be_present

              site_text = json["site_text"]
              expect(site_text).to be_present

              expect(site_text["id"]).to eq(id)
              expect(site_text["value"]).to eq(value)
            end
          end
        end

        context "with English" do
          let(:locale) { :en }
          let(:expected_translations) { { one: "%{count} colour", other: "%{count} colours" } }

          include_examples "has correct plural keys"
        end

        context "with language with different plural keys and missing translations" do
          let(:locale) { :ru }
          let(:expected_translations) do
            { one: "%{count} colour", few: "%{count} colours", other: "%{count} colours" }
          end

          include_examples "has correct plural keys"
        end

        context "with language with different plural keys and partial translation" do
          before { I18n.backend.store_translations(:ru, colour: { few: "%{count} цвета" }) }

          let(:locale) { :ru }
          let(:expected_translations) do
            { one: "%{count} colour", few: "%{count} цвета", other: "%{count} colours" }
          end

          include_examples "has correct plural keys"
        end
      end
    end

    shared_examples "site text inaccessible" do
      it "denies access with a 404 response" do
        get "/admin/customize/site_texts/js.topic.list.json", params: { locale: default_locale }

        expect(response.status).to eq(404)
        expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
      end
    end

    context "when logged in as a moderator" do
      before { sign_in(moderator) }

      include_examples "site text inaccessible"
    end

    context "when logged in as a non-staff user" do
      before { sign_in(user) }

      include_examples "site text inaccessible"
    end
  end

  describe "#update & #revert" do
    context "when logged in as an admin" do
      before { sign_in(admin) }

      it "returns 'not found' when an unknown key is used" do
        put "/admin/customize/site_texts/some_key.json",
            params: {
              site_text: {
                value: "foo",
                locale: default_locale,
              },
            }

        expect(response.status).to eq(404)

        json = response.parsed_body
        expect(json["error_type"]).to eq("not_found")
      end

      it "works as expected with correct keys" do
        put "/admin/customize/site_texts/js.emoji_picker.animals_%26_nature.json",
            params: {
              site_text: {
                value: "foo",
                locale: default_locale,
              },
            }

        expect(response.status).to eq(200)

        json = response.parsed_body
        site_text = json["site_text"]

        expect(site_text["id"]).to eq("js.emoji_picker.animals_&_nature")
        expect(site_text["value"]).to eq("foo")
      end

      it "does not update restricted keys" do
        put "/admin/customize/site_texts/user_notifications.confirm_old_email.title.json",
            params: {
              site_text: {
                value: "foo",
                locale: default_locale,
              },
            }

        expect(response.status).to eq(403)

        json = response.parsed_body
        expect(json["error_type"]).to eq("invalid_access")
        expect(json["errors"].size).to eq(1)
        expect(json["errors"].first).to eq(I18n.t("email_template_cant_be_modified"))
      end

      it "returns the right error message" do
        I18n.backend.store_translations(SiteSetting.default_locale, some_key: "%{first} %{second}")

        put "/admin/customize/site_texts/some_key.json",
            params: {
              site_text: {
                value: "hello %{key} %{omg}",
                locale: default_locale,
              },
            }

        expect(response.status).to eq(422)

        body = response.parsed_body

        expect(body["message"]).to eq(
          I18n.t(
            "activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
            keys: "key, omg",
            count: 2,
          ),
        )
      end

      it "logs the change" do
        original_title = I18n.t(:title)

        put "/admin/customize/site_texts/title.json",
            params: {
              site_text: {
                value: "yay",
                locale: default_locale,
              },
            }
        expect(response.status).to eq(200)

        log = UserHistory.last

        expect(log.previous_value).to eq(original_title)
        expect(log.new_value).to eq("yay")
        expect(log.action).to eq(UserHistory.actions[:change_site_text])

        delete "/admin/customize/site_texts/title.json", params: { locale: default_locale }
        expect(response.status).to eq(200)

        log = UserHistory.last

        expect(log.previous_value).to eq("yay")
        expect(log.new_value).to eq(original_title)
        expect(log.action).to eq(UserHistory.actions[:change_site_text])
      end

      it "updates and reverts the key" do
        orig_title = I18n.t(:title)

        put "/admin/customize/site_texts/title.json",
            params: {
              site_text: {
                value: "hello",
                locale: default_locale,
              },
            }
        expect(response.status).to eq(200)

        json = response.parsed_body

        site_text = json["site_text"]

        expect(site_text["id"]).to eq("title")
        expect(site_text["value"]).to eq("hello")

        # Revert
        delete "/admin/customize/site_texts/title.json", params: { locale: default_locale }
        expect(response.status).to eq(200)

        json = response.parsed_body

        site_text = json["site_text"]

        expect(site_text["id"]).to eq("title")
        expect(site_text["value"]).to eq(orig_title)
      end

      it "returns site texts for the correct locale" do
        locale = :ru

        ru_title = "title ru"
        ru_mf_text = "ru {NUM_RESULTS, plural, one {1 result} other {many} }"

        put "/admin/customize/site_texts/title.json",
            params: {
              site_text: {
                value: ru_title,
                locale: locale,
              },
            }
        expect(response.status).to eq(200)
        put "/admin/customize/site_texts/js.topic.read_more_MF.json",
            params: {
              site_text: {
                value: ru_mf_text,
                locale: locale,
              },
            }
        expect(response.status).to eq(200)

        get "/admin/customize/site_texts/title.json", params: { locale: locale }
        expect(response.status).to eq(200)
        json = response.parsed_body
        expect(json["site_text"]["value"]).to eq(ru_title)

        get "/admin/customize/site_texts/js.topic.read_more_MF.json", params: { locale: locale }
        expect(response.status).to eq(200)
        json = response.parsed_body
        expect(json["site_text"]["value"]).to eq(ru_mf_text)

        en_locale = :en

        get "/admin/customize/site_texts/title.json", params: { locale: en_locale }
        expect(response.status).to eq(200)
        json = response.parsed_body
        expect(json["site_text"]["value"]).to_not eq(ru_title)

        get "/admin/customize/site_texts/js.topic.read_more_MF.json", params: { locale: en_locale }
        expect(response.status).to eq(200)
        json = response.parsed_body
        expect(json["site_text"]["value"]).to_not eq(ru_mf_text)
      end

      context "when updating a translation override for a system badge" do
        fab!(:user_with_badge_title) { Fabricate(:active_user) }
        let(:badge) { Badge.find(Badge::Regular) }

        before do
          BadgeGranter.grant(badge, user_with_badge_title)
          user_with_badge_title.update(title: "Regular")
        end

        it "updates matching user titles to the override text in a job" do
          expect_enqueued_with(
            job: :bulk_user_title_update,
            args: {
              new_title: "Terminator",
              granted_badge_id: badge.id,
              action: Jobs::BulkUserTitleUpdate::UPDATE_ACTION,
            },
          ) do
            put "/admin/customize/site_texts/badges.regular.name.json",
                params: {
                  site_text: {
                    value: "Terminator",
                    locale: default_locale,
                  },
                }
          end

          # Revert
          expect_enqueued_with(
            job: :bulk_user_title_update,
            args: {
              granted_badge_id: badge.id,
              action: Jobs::BulkUserTitleUpdate::RESET_ACTION,
            },
          ) do
            delete "/admin/customize/site_texts/badges.regular.name.json",
                   params: {
                     locale: default_locale,
                   }
          end
        end

        it "does not update matching user titles when overriding non-title badge text" do
          expect_not_enqueued_with(job: :bulk_user_title_update) do
            put "/admin/customize/site_texts/badges.regular.long_description.json",
                params: {
                  site_text: {
                    value: "Terminator",
                    locale: default_locale,
                  },
                }
          end
        end
      end
    end

    shared_examples "site text update not allowed" do
      it "prevents updates with a 404 response" do
        put "/admin/customize/site_texts/js.emoji_picker.animals_%26_nature.json",
            params: {
              site_text: {
                value: "foo",
                locale: default_locale,
              },
            }

        expect(response.status).to eq(404)
        expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
      end
    end

    context "when logged in as a moderator" do
      before { sign_in(moderator) }

      include_examples "site text update not allowed"
    end

    context "when logged in as a non-staff user" do
      before { sign_in(user) }

      include_examples "site text update not allowed"
    end
  end

  describe "#dismiss_outdated" do
    before { sign_in(admin) }

    context "when using a key which isn't overridden" do
      it "returns a not found error" do
        put "/admin/customize/site_texts/title/dismiss_outdated.json",
            params: {
              locale: default_locale,
            }

        expect(response.status).to eq(404)

        json = response.parsed_body
        expect(json["error_type"]).to eq("not_found")
      end
    end

    context "when the override isn't outdated" do
      before do
        Fabricate(
          :translation_override,
          locale: default_locale,
          translation_key: "title",
          value: "My Forum",
        )
      end

      it "returns an unprocessable entity error" do
        put "/admin/customize/site_texts/title/dismiss_outdated.json",
            params: {
              locale: default_locale,
            }

        expect(response.status).to eq(422)

        json = response.parsed_body
        expect(json["failed"]).to eq("FAILED")
        expect(json["message"]).to eq("Can only dismiss outdated translations")
      end
    end

    context "when the override is outdated" do
      before do
        Fabricate(
          :translation_override,
          locale: default_locale,
          translation_key: "title",
          value: "My Forum",
          status: "outdated",
        )
      end

      it "returns success" do
        put "/admin/customize/site_texts/title/dismiss_outdated.json",
            params: {
              locale: default_locale,
            }

        expect(response.status).to eq(200)
        expect(response.parsed_body["success"]).to eq("OK")
      end
    end
  end

  context "when reseeding" do
    before do
      staff_category = Fabricate(:category, name: "Staff EN", user: Discourse.system_user)
      SiteSetting.staff_category_id = staff_category.id

      guidelines_topic =
        Fabricate(
          :topic,
          title: "The English Guidelines",
          category: @staff_category,
          user: Discourse.system_user,
        )
      Fabricate(:post, topic: guidelines_topic, user: Discourse.system_user)
      SiteSetting.guidelines_topic_id = guidelines_topic.id
    end

    describe "#get_reseed_options" do
      context "when logged in as an admin" do
        before { sign_in(admin) }

        it "returns correct json" do
          get "/admin/customize/reseed.json"
          expect(response.status).to eq(200)

          expected_reseed_options = {
            categories: [
              {
                id: "uncategorized_category_id",
                name: I18n.t("uncategorized_category_name"),
                selected: true,
              },
              { id: "staff_category_id", name: "Staff EN", selected: true },
            ],
            topics: [{ id: "guidelines_topic_id", name: "The English Guidelines", selected: true }],
          }

          expect(JSON.parse(response.body, symbolize_names: true)).to eq(expected_reseed_options)
        end
      end

      shared_examples "reseed options inaccessible" do
        it "denies access with a 404 response" do
          get "/admin/customize/reseed.json"

          expect(response.status).to eq(404)
          expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
        end
      end

      context "when logged in as a moderator" do
        before { sign_in(moderator) }

        include_examples "reseed options inaccessible"
      end

      context "when logged in as a non-staff user" do
        before { sign_in(user) }

        include_examples "reseed options inaccessible"
      end
    end

    describe "#reseed" do
      context "when logged in as an admin" do
        before { sign_in(admin) }

        it "reseeds categories and topics" do
          SiteSetting.default_locale = :de

          post "/admin/customize/reseed.json",
               params: {
                 category_ids: ["staff_category_id"],
                 topic_ids: ["guidelines_topic_id"],
               }
          expect(response.status).to eq(200)

          expect(Category.find(SiteSetting.staff_category_id).name).to eq(
            I18n.t("staff_category_name", locale: :de),
          )
          expect(Topic.find(SiteSetting.guidelines_topic_id).title).to eq(
            I18n.t("guidelines_topic.title", locale: :de),
          )
        end
      end

      shared_examples "reseed not allowed" do
        it "prevents reseeds with a 404 response" do
          post "/admin/customize/reseed.json",
               params: {
                 category_ids: ["staff_category_id"],
                 topic_ids: ["guidelines_topic_id"],
               }

          expect(response.status).to eq(404)
          expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
        end
      end

      context "when logged in as a moderator" do
        before { sign_in(moderator) }

        include_examples "reseed not allowed"
      end

      context "when logged in as a non-staff user" do
        before { sign_in(user) }

        include_examples "reseed not allowed"
      end
    end
  end
end