Проанализируй данный класс. Есть ли советы по улучшению? Как бы ты произвёл рефакторинг?

```kotlin
class VillagerQuestManager(private val plugin: QuestIntelligence) {

    private val professionItems: MutableMap<Profession, Map<Material, Pair<Int, Int>>> = mutableMapOf()

    init {
        this.initializeProfessionItems()
    }

    private fun initializeProfessionItems() {
        Registry.VILLAGER_PROFESSION.forEach { profession ->

            if (profession == Profession.NONE)
                return@forEach

            // Создаем карту для хранения предметов
            val items = mutableMapOf<Material, Pair<Int, Int>>()

            // Извлекаем и обрабатываем список предметов
            plugin.config.getStringList("profession.$profession.item-priority").forEach { line ->

                val (materialName, amountRange) = line.split("~")
                val (min, max) = amountRange.split("-").map(String::toInt).let { range ->
                    if (range.size == 1) range[0] to range[0] else range[0] to range[1]
                }

                val amount = min to max
                if (materialName.contains('@')) {
                    Material.entries.filter { material: Material -> material.toString().contains(materialName.removePrefix("@")) }.forEach {
                        items[it] = amount
                    }
                } else items[Material.valueOf(materialName)] = amount
            }

            professionItems[profession] = items
        }
    }

    fun prepareQuest() {

        plugin.debug("=== --- === --- === --- === --- === --- === --- === --- === --- ===")
        plugin.debug("Time for a new quest! Generating...")

        if (enabledWorlds.isEmpty()) {
            plugin.logger.severe("No target worlds in config.yml! Disabling the plugin.")
            plugin.server.pluginManager.disablePlugin(plugin)
        }

        plugin.debug("Looking for a random villager...")
        val villager = this.getRandomVillager() ?: run {
            plugin.debug("Can't find a villager. Cancelling.")
            return
        }

        plugin.debug("Found a villager! Randomizing quest type...")
        val questType = this.determineQuestType(villager)

        plugin.debug("Quest type is $questType. Selecting the quest item!")
        val questItem = when (questType) {
            QuestType.DISC -> ItemStack(discs[Random.nextInt(discs.size)])
            QuestType.PERSONAL_VILLAGER_DATA -> ItemStack(Material.AIR)
            QuestType.OMINOUS_BANNER -> ominousBanner;
            else -> villager.prioritizedItem
        }

        plugin.debug("Quest item is ${questItem.type}. Building a quest...")
        val quest = this.buildQuest(questType, villager, questItem) ?: return
        this.requestQuestInfo(villager, quest)
    }

    private fun buildQuest(questType: QuestType, villager: Villager, questItem: ItemStack): VillagerQuest.Builder? {

        val quest = VillagerQuest.Builder().setQuestType(questType).setQuestItem(questItem)

        plugin.debug("Generating a quest reward...")
        val questReward = when (questType) {

            QuestType.DISC, QuestType.PROFESSION_ITEM_GATHERING, QuestType.OMINOUS_BANNER -> {

                val itemPrice = when (questType) {
                    QuestType.OMINOUS_BANNER -> plugin.configurationClip.promptsConfig.getInt("ominous-banner.reward-points")
                    else -> this.calculateItemPrice(questItem)
                }

                val villagerItems  = villager.quillInventory.filterNotNull().filter { item -> this.calculateItemPrice(item) > 0 && !this.isProfessionItem(villager.profession, item) }
                val inventoryPrice = this.calculateItemListPrice(villagerItems)

                plugin.debug("Item price: $itemPrice.")
                plugin.debug("Inventory price: $inventoryPrice.")

                if (itemPrice > inventoryPrice) {
                    plugin.debug("Item price is bigger than inventory price. Cancelling quest generation.")
                    return null
                }

                // Если наград больше одной, используется мешочек
                val barterItems = this.gatherBarterItems(questType, questItem, inventoryPrice, villagerItems)
                if (barterItems.size > 1) this.bundle(barterItems) else {
                    // Если нет предметов, которые житель мог бы отдать в качестве награды за квест
                    if (barterItems.isEmpty()) {
                        plugin.debug("Villager have no items to use them as a reward. Cancelling quest generation.")
                        return null
                    }
                    else barterItems[0]
                }

            }

            else -> ItemStack(Material.AIR)

        }

        plugin.debug("Quest item is: [${questReward.type}, amount is ${questReward.amount}]!")
        return quest.setRewardItem(questReward)
    }

    private val ominousBanner: ItemStack by lazy {
        CraftItemStack.asBukkitCopy(Raid.getLeaderBannerInstance((enabledWorlds[0] as CraftWorld).handle.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)))
    }

    private val enabledWorlds: List<World> by lazy {
        mutableListOf<World>().apply {
            plugin.config.getStringList("core-settings.enabled-worlds").forEach {
                world -> add(Bukkit.getWorld(world)!!)
            }
        }
    }

    fun getRandomVillager(): Villager? {
        val villagers = enabledWorlds.random().entities.filterIsInstance<Villager>().filter { this.canGenerateQuest(it) }
        return villagers.randomOrNull()
    }

    private fun determineQuestType(villager: Villager): QuestType {

        val availableQuests = arrayOf( /* QuestType.PROFESSION_ITEM_GATHERING, QuestType.DISC, */ QuestType.OMINOUS_BANNER)

        return if (villager.personalData == null) {
            QuestType.PERSONAL_VILLAGER_DATA
        } else {
            availableQuests.random()
        }
    }

    private fun canGenerateQuest(villager: Villager): Boolean {
        return villager.currentQuest == null && villager.profession != Villager.Profession.NONE
    }

    private fun requestQuestInfo(villager: Villager, quest: VillagerQuest.Builder) {
        plugin.server.scheduler.runTaskAsynchronously(plugin) { _ ->
            val placeholders = createPlaceholders(villager, quest.questItem, quest.rewardItem)
            val filledPrompt = fillPromptWithPlaceholders(quest.questType, placeholders)
            plugin.questGenerator.generateQuestData(villager, quest, filledPrompt)
        }
    }

    private fun createPlaceholders(villager: Villager, questItem: ItemStack, rewardItem: ItemStack): Map<String, String> {

        val args = if (villager.personality == VillagerPersonality.ANGRY || villager.personality == VillagerPersonality.DRUNKARD) ", '15% of words are swearing'" else ""

        return mapOf(
            "villagerName"         to if (villager.customName() != null) (villager.customName() as TextComponent).content() else "Anonymous",
            "villagerType"         to "${villager.villagerType}",
            "villagerProfession"   to "${villager.profession}",
            "villagerPersonality"  to "${villager.personality}",
            "villagerLevel"        to "${villager.villagerLevel}",
            "questItem"            to questItem.type.name.replace('_', ' ').lowercase(),
            "rewardItems"          to "${if (rewardItem.type == Material.BUNDLE) (rewardItem.itemMeta as BundleMeta).items.format() else rewardItem.type}",
            "promptRules"          to "['Use ${plugin.config.getString("core-settings.language")} language'$args]",
            "language"             to "${plugin.config.getString("core-settings.language")}",
            "randomLetter"         to this.getRandomLetter()
        )
    }

    private fun fillPromptWithPlaceholders(questType: QuestType, placeholders: Map<String, String>): String {
        return placeholders.entries.fold(plugin.configurationClip.promptsConfig.getString(questType.promptConfigPath)!!) { acc, entry ->
            acc.replace("{${entry.key}}", entry.value)
        }
    }

    private fun getRandomLetter(): String {
        val letters = 'A'..'Z'
        val randomIndex = Random.nextInt(letters.count())
        return letters.elementAt(randomIndex).toString()
    }

    private fun isProfessionItem(profession: Profession, item: ItemStack): Boolean =
        item.type in professionItems[profession]?.keys.orEmpty()

    /**
     * Создает мешочек с заданным списком итемов внутри.
     *
     * @param items Список предметов, которые будут упакованы в мешочек.
     */
    private fun bundle(items: List<ItemStack>): ItemStack {
        return ItemStack(Material.BUNDLE, 1).apply {
            itemMeta = (itemMeta as BundleMeta).apply {
                items.forEach(::addItem)
            }
        }
    }

    private fun gatherBarterItems(
        questType: QuestType,
        questItem: ItemStack,
        inventoryPrice: Int,
        villagerItems: List<ItemStack>
    ): MutableList<ItemStack> {

        val questItemPrice = when (questType) {
            QuestType.OMINOUS_BANNER -> plugin.configurationClip.promptsConfig.getInt("ominous-banner.reward-points")
            else -> this.getMaterialPrice(questItem.type)
        }

        // Emeralds are first
        val sortedInventory = villagerItems.sortedBy { if (it.type == Material.EMERALD) 0 else 1 }

        if (this.calculateItemPrice(questItem) <= 0) {
            plugin.logger.severe("${questItem.type} price is zero! Fix it and reload the plugin!")
            return mutableListOf()
        }

        val possibleAmount      = inventoryPrice / questItemPrice
        val requiredRewardPrice = minOf(questItem.amount, possibleAmount) * questItemPrice
        val rewardItems         = mutableListOf<ItemStack>()

        // Проходимся по инвентарю с целью найти предметы которыми можно заплатить за questItem
        for (iterableItem in sortedInventory) {

            // Пропускаем не подходящие по цене предметы и исключаем "одинаковые сделки"
            if (this.getMaterialPrice(iterableItem.type) > requiredRewardPrice || iterableItem.type == questItem.type)
                continue

            // Считаем поштучно
            for (i in 1..iterableItem.amount) {

                val currentRewardPrice = this.calculateItemListPrice(rewardItems)
                if (currentRewardPrice >= requiredRewardPrice)
                    return rewardItems

                val existingItem = rewardItems.find { it.type == iterableItem.type }
                if (existingItem != null) {
                    existingItem.amount = i
                } else {
                    rewardItems.add(iterableItem.clone().apply { amount = i })
                }

            }

        }

        return rewardItems
    }

    /**
     * Вычисляет общую цену списка предметов.
     *
     * @param itemList список предметов.
     * @return общая цена.
     */
    private fun calculateItemListPrice(itemList: List<ItemStack>): Int {
        return itemList.sumOf { this.calculateItemPrice(it) }
    }

    /**
     * Вычисляет цену отдельного предмета. Учитывает количество предметов в стаке!
     *
     * @param item предмет, для которого вычисляется цена.
     * @return цена предмета.
     */
    private fun calculateItemPrice(item: ItemStack): Int {
        return (this.getMaterialPrice(item.type) * item.amount)
    }

    private fun getMaterialPrice(material: Material, defaultPrice: Int = 50): Int {

        val pricingConfig = plugin.configurationClip.pricesConfig

        return if (pricingConfig.contains(material.name))
            pricingConfig.getInt(material.name)
        else defaultPrice.also {
            plugin.logger.info("Price for material $material not found. Updating configuration... Default price is $defaultPrice.")
            plugin.logger.info("Configuration reloaded automatically.")
            pricingConfig.set(material.name, it)
            pricingConfig.save(File(plugin.dataFolder, "prices.yml"))
            plugin.reloadConfigurations()
        }
    }

    companion object {
        private val discs = Material.entries.filter { material: Material -> material.isRecord }
    }

}
```