package ru.yandex.direct.web.entity.uac.controller

import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import ru.yandex.direct.core.entity.uac.grut.GrutTransactionProvider
import ru.yandex.direct.core.entity.uac.model.BaseUacTrackingInfo
import ru.yandex.direct.core.entity.uac.service.UacCampaignServiceHolder
import ru.yandex.direct.core.security.authorization.PreAuthorizeRead
import ru.yandex.direct.web.core.security.DirectWebAuthenticationSource
import ru.yandex.direct.web.core.security.authentication.DirectCookieAuthProvider.PARAMETER_ULOGIN
import ru.yandex.direct.web.entity.uac.converter.UacTrackingInfoConverter
import ru.yandex.direct.web.entity.uac.toResponse

@RestController
@Api(tags = ["uac"])
@RequestMapping("/uac", produces = [MediaType.APPLICATION_JSON_VALUE])
class UacTrackingInfoController(
    private val authenticationSource: DirectWebAuthenticationSource,
    private val serviceHolder: UacCampaignServiceHolder,
    private val uacTrackingInfoConverter: UacTrackingInfoConverter,
    private val grutTransactionProvider: GrutTransactionProvider,
) {
    @ApiOperation(
        value = "getTrackingInfoList",
        httpMethod = "GET",
        nickname = "getTrackingInfoList",
    )
    @PreAuthorizeRead
    @GetMapping(value = ["tracking_info"])
    fun getTrackingInfoList(
        @RequestParam(value = "app_info.id", required = true) appInfoId: String,
        @RequestParam(value = PARAMETER_ULOGIN) ulogin: String?,
    ): ResponseEntity<Any> {
        /**
         * todo: https://st.yandex-team.ru/DIRECT-159951
         */
        val trackingInfo = getTrackingInfo(false, appInfoId).toMutableList()

        trackingInfo.addAll(
            grutTransactionProvider.runInTransaction { getTrackingInfo(true, appInfoId) })

        return ResponseEntity(
            uacTrackingInfoConverter.toUacTrackingInfo(filterTrackingInfos(trackingInfo)).toResponse(), HttpStatus.OK)
    }

    private fun getTrackingInfo(useGrut: Boolean, appInfoId: String): List<BaseUacTrackingInfo> {
        val operator = authenticationSource.authentication.operator
        val subjectUser = authenticationSource.authentication.subjectUser
        val accountId = serviceHolder.getUacCampaignService(useGrut).getOrCreateClient(operator, subjectUser)
        val uacCampaignService = serviceHolder.getUacCampaignService(useGrut)
        return uacCampaignService.getTrackingInfosByAccountIdAndAppId(accountId, appInfoId)
    }

    private fun filterTrackingInfos(trackingInfos: List<BaseUacTrackingInfo>): List<BaseUacTrackingInfo> {
        return trackingInfos
            .sortedBy { it.createdTime }
            .groupBy { listOf(it.trackingUrl, it.impressionUrl) }
            .map { it.value[0] }
            .sortedBy { it.createdTime }
    }
}
