package ru.yandex.direct.api.v5.entity.campaigns.validation

import com.yandex.direct.api.v5.campaigns.TextCampaignNetworkStrategyTypeEnum
import com.yandex.direct.api.v5.campaigns.TextCampaignNetworkStrategyTypeEnum.NETWORK_DEFAULT
import com.yandex.direct.api.v5.campaigns.TextCampaignSearchStrategyTypeEnum
import com.yandex.direct.api.v5.campaigns.TextCampaignSetting
import com.yandex.direct.api.v5.campaigns.TextCampaignSettingsEnum
import com.yandex.direct.api.v5.campaigns.TextCampaignStrategy
import com.yandex.direct.api.v5.campaigns.TextCampaignStrategyAdd
import ru.yandex.direct.api.v5.entity.campaigns.CampaignDefectTypes
import ru.yandex.direct.api.v5.entity.campaigns.converter.StrategyAddConverter.toCampaignsAutobudget
import ru.yandex.direct.api.v5.entity.campaigns.converter.TextCampaignStrategyConverter.toCampaignStrategy
import ru.yandex.direct.api.v5.entity.campaigns.converter.TextCampaignUpdateItemConverter.Companion.mergeOldAndNewStrategies
import ru.yandex.direct.api.v5.entity.campaigns.converter.toContextLimit
import ru.yandex.direct.api.v5.validation.DefectType
import ru.yandex.direct.core.entity.campaign.model.CampaignsAutobudget
import ru.yandex.direct.core.entity.campaign.model.TextCampaign

fun limitPercentIsConsistentWithStrategy(strategy: TextCampaignStrategyAdd): DefectType? {
    val notOk = strategy.network?.toContextLimit() != null
        && isAutobudget(strategy)
    return if (notOk) CampaignDefectTypes.parameterInconsistentWithStrategy("LimitPercent") else null
}

fun limitPercentIsConsistentWithStrategy(
    newStrategy: TextCampaignStrategy,
    oldCampaign: TextCampaign
): DefectType? {
    val fullNewStrategy = mergeOldAndNewStrategies(newStrategy, oldCampaign)
    val notOk = fullNewStrategy.network?.toContextLimit() != null
        && isAutobudget(fullNewStrategy)
    return if (notOk) CampaignDefectTypes.parameterInconsistentWithStrategy("LimitPercent") else null
}

fun settingIsConsistentWithStrategy(
    setting: TextCampaignSetting,
    strategy: TextCampaignStrategyAdd
): DefectType? {
    return when (setting.option) {
        TextCampaignSettingsEnum.MAINTAIN_NETWORK_CPC -> {
            val notOk = strategy.network?.toContextLimit() != null
                && isAutobudget(strategy)
            if (notOk) CampaignDefectTypes.settingInconsistentWithStrategy("MAINTAIN_NETWORK_CPC") else null
        }
        else -> {
            null
        }
    }
}

fun settingIsConsistentWithStrategy(
    newSetting: TextCampaignSetting,
    newStrategy: TextCampaignStrategy?,
    oldCampaign: TextCampaign?
): DefectType? {
    return when (newSetting.option) {
        TextCampaignSettingsEnum.MAINTAIN_NETWORK_CPC -> {
            val fullNewStrategy = mergeOldAndNewStrategies(newStrategy, oldCampaign!!)
            val notOk = fullNewStrategy.network?.toContextLimit() != null
                && isAutobudget(fullNewStrategy)
            if (notOk) CampaignDefectTypes.settingInconsistentWithStrategy("MAINTAIN_NETWORK_CPC") else null
        }
        else -> {
            null
        }
    }
}

private fun isAutobudget(strategy: TextCampaignStrategyAdd) =
    toCampaignsAutobudget(toCampaignStrategy(strategy).strategyName) == CampaignsAutobudget.YES

private fun isAutobudget(strategy: TextCampaignStrategy) =
    toCampaignsAutobudget(toCampaignStrategy(strategy).strategyName) == CampaignsAutobudget.YES

/**
 * Смотри https://yandex.ru/dev/direct/doc/dg/objects/campaign-strategies.html
 */
fun getNetworkStrategyTypesCompatibleWith(
    searchStrategyType: TextCampaignSearchStrategyTypeEnum
): Set<TextCampaignNetworkStrategyTypeEnum> {
    return when (searchStrategyType) {
        TextCampaignSearchStrategyTypeEnum.HIGHEST_POSITION ->
            setOf(
                TextCampaignNetworkStrategyTypeEnum.MAXIMUM_COVERAGE,
                NETWORK_DEFAULT,
                TextCampaignNetworkStrategyTypeEnum.SERVING_OFF
            )
        TextCampaignSearchStrategyTypeEnum.AVERAGE_CPA,
        TextCampaignSearchStrategyTypeEnum.AVERAGE_CPC,
        TextCampaignSearchStrategyTypeEnum.AVERAGE_ROI,
        TextCampaignSearchStrategyTypeEnum.AVERAGE_CRR,
        TextCampaignSearchStrategyTypeEnum.PAY_FOR_CONVERSION,
        TextCampaignSearchStrategyTypeEnum.PAY_FOR_CONVERSION_CRR,
        TextCampaignSearchStrategyTypeEnum.WB_MAXIMUM_CLICKS,
        TextCampaignSearchStrategyTypeEnum.WB_MAXIMUM_CONVERSION_RATE,
        TextCampaignSearchStrategyTypeEnum.WEEKLY_CLICK_PACKAGE ->
            setOf(
                NETWORK_DEFAULT,
                TextCampaignNetworkStrategyTypeEnum.SERVING_OFF
            )
        TextCampaignSearchStrategyTypeEnum.SERVING_OFF ->
            setOf(
                TextCampaignNetworkStrategyTypeEnum.MAXIMUM_COVERAGE,
                TextCampaignNetworkStrategyTypeEnum.AVERAGE_CPA,
                TextCampaignNetworkStrategyTypeEnum.AVERAGE_CPC,
                TextCampaignNetworkStrategyTypeEnum.AVERAGE_ROI,
                TextCampaignNetworkStrategyTypeEnum.AVERAGE_CRR,
                TextCampaignNetworkStrategyTypeEnum.PAY_FOR_CONVERSION,
                TextCampaignNetworkStrategyTypeEnum.PAY_FOR_CONVERSION_CRR,
                TextCampaignNetworkStrategyTypeEnum.WB_MAXIMUM_CLICKS,
                TextCampaignNetworkStrategyTypeEnum.WB_MAXIMUM_CONVERSION_RATE,
                TextCampaignNetworkStrategyTypeEnum.WEEKLY_CLICK_PACKAGE
            )
        else ->
            setOf()
    }
}
