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

import com.yandex.direct.api.v5.campaigns.CpmBannerCampaignNetworkStrategy
import com.yandex.direct.api.v5.campaigns.CpmBannerCampaignNetworkStrategyTypeEnum
import com.yandex.direct.api.v5.campaigns.CpmBannerCampaignSearchStrategy
import com.yandex.direct.api.v5.campaigns.CpmBannerCampaignSearchStrategyTypeEnum
import com.yandex.direct.api.v5.campaigns.CpmBannerCampaignStrategy
import org.slf4j.LoggerFactory
import ru.yandex.direct.core.entity.campaign.model.CpmBannerCampaign
import ru.yandex.direct.core.entity.campaign.model.DbStrategy
import ru.yandex.direct.core.entity.campaign.model.StrategyName
import java.lang.invoke.MethodHandles

private val logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())

fun createCpmBannerCampaignGetStrategy(campaign: CpmBannerCampaign): CpmBannerCampaignStrategy {
    val biddingStrategy = toCpmBannerCampaignExternalStrategy(campaign.strategy)
    return biddingStrategy.apply {
        if (search.biddingStrategyType == null) {
            search.biddingStrategyType = CpmBannerCampaignSearchStrategyTypeEnum.UNKNOWN
            logger.warn("Campaign ${campaign.id} has unknown strategy ${campaign.strategy}")
        }

        if (network.biddingStrategyType == null) {
            network.biddingStrategyType = CpmBannerCampaignNetworkStrategyTypeEnum.UNKNOWN
            logger.warn("Campaign ${campaign.id} has unknown strategy ${campaign.strategy}")
        }
    }
}

fun toCpmBannerCampaignExternalStrategy(internalStrategy: DbStrategy) =
    CpmBannerCampaignStrategy().apply {
        search = getSearchStrategy(internalStrategy)
        network = getNetworkStrategy(internalStrategy)
    }

private fun getSearchStrategy(internalStrategy: DbStrategy): CpmBannerCampaignSearchStrategy {
    // CpmBannerCampaign бывает только в сетях
    check(!internalStrategy.platform.isSearch())
    return CpmBannerCampaignSearchStrategy().apply {
        biddingStrategyType = CpmBannerCampaignSearchStrategyTypeEnum.SERVING_OFF
    }
}

private fun getNetworkStrategy(internalStrategy: DbStrategy): CpmBannerCampaignNetworkStrategy {
    // CpmBannerCampaign бывает только в сетях
    check(internalStrategy.platform.isNetwork())
    val network = CpmBannerCampaignNetworkStrategy()
    val strategyData = internalStrategy.strategyData
    when (strategyData.name) {
        StrategyName.CPM_DEFAULT.name.lowercase() -> {
            network.biddingStrategyType = CpmBannerCampaignNetworkStrategyTypeEnum.MANUAL_CPM
        }
        StrategyName.AUTOBUDGET_MAX_REACH.name.lowercase() -> {
            network.biddingStrategyType =
                CpmBannerCampaignNetworkStrategyTypeEnum.WB_DECREASED_PRICE_FOR_REPEATED_IMPRESSIONS
            network.wbDecreasedPriceForRepeatedImpressions =
                toStrategyWbDecreasedPriceForRepeatedImpressions(strategyData)
        }
        StrategyName.AUTOBUDGET_MAX_REACH_CUSTOM_PERIOD.name.lowercase() -> {
            network.biddingStrategyType =
                CpmBannerCampaignNetworkStrategyTypeEnum.CP_DECREASED_PRICE_FOR_REPEATED_IMPRESSIONS
            network.cpDecreasedPriceForRepeatedImpressions =
                toStrategyCpDecreasedPriceForRepeatedImpressions(strategyData)
        }
        StrategyName.AUTOBUDGET_MAX_IMPRESSIONS.name.lowercase() -> {
            network.biddingStrategyType = CpmBannerCampaignNetworkStrategyTypeEnum.WB_MAXIMUM_IMPRESSIONS
            network.wbMaximumImpressions = toStrategyWbMaximumImpressions(strategyData)
        }
        StrategyName.AUTOBUDGET_MAX_IMPRESSIONS_CUSTOM_PERIOD.name.lowercase() -> {
            network.biddingStrategyType = CpmBannerCampaignNetworkStrategyTypeEnum.CP_MAXIMUM_IMPRESSIONS
            network.cpMaximumImpressions = toStrategyCpMaximumImpressions(strategyData)
        }
        StrategyName.AUTOBUDGET_AVG_CPV.name.lowercase() -> {
            network.biddingStrategyType = CpmBannerCampaignNetworkStrategyTypeEnum.WB_AVERAGE_CPV
            network.wbAverageCpv = toStrategyWbAverageCpv(strategyData)
        }
        StrategyName.AUTOBUDGET_AVG_CPV_CUSTOM_PERIOD.name.lowercase() -> {
            network.biddingStrategyType = CpmBannerCampaignNetworkStrategyTypeEnum.CP_AVERAGE_CPV
            network.cpAverageCpv = toStrategyCpAverageCpv(strategyData)
        }
    }
    return network
}
