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.model.Platform
import ru.yandex.direct.core.security.authorization.PreAuthorizeRead
import ru.yandex.direct.utils.UrlUtils
import ru.yandex.direct.validation.defect.CommonDefects.invalidValue
import ru.yandex.direct.validation.result.Defect
import ru.yandex.direct.validation.result.ValidationResult
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.service.UacLinkService
import ru.yandex.direct.web.validation.kernel.ValidationResultConversionService
import java.net.URLDecoder
import java.nio.charset.StandardCharsets

@Suppress("unused")
@RestController
@Api(tags = ["uac"])
@RequestMapping("/uac", produces = [MediaType.APPLICATION_JSON_VALUE])
open class UacLinkController(
        private val authenticationSource: DirectWebAuthenticationSource,
        private val uacLinkService: UacLinkService,
        private val validationResultConversionService: ValidationResultConversionService
) {

    companion object {
        private const val PARAMETER_URL = "url"
        private const val PARAMETER_PLATFORM = "platform"
    }

    @ApiOperation(
            value = "linkInfoGet",
            httpMethod = "GET",
            nickname = "linkInfoGet",
    )
    @PreAuthorizeRead
    @GetMapping(value = ["linkinfo"])
    open fun getLinkInfo(
            @RequestParam(value = PARAMETER_ULOGIN) ulogin: String,
            @RequestParam(value = PARAMETER_URL) url: String,
            @RequestParam(value = PARAMETER_PLATFORM, required = false) platform: Platform?
    ): ResponseEntity<Any> {
        val subjectUser = authenticationSource.authentication.subjectUser
        val clientId = subjectUser.clientId
        val uid = subjectUser.uid
        // Мы хотим считать URL'ы с юникодом в query-части валидными, но validHref() рассчитан только на юникод в пути,
        // поэтому мы ему немного поможем и закодируем параметры сами
        val decodedUrl = try {
            URLDecoder.decode(url, StandardCharsets.UTF_8)
        } catch (e: IllegalArgumentException) {
            null
        } ?: return buildBadRequestResponse(ValidationResult.failed(url, invalidValue()))
        val urlToCheck = UrlUtils.encodeUrlQueryIfCan(decodedUrl)
        val result = uacLinkService.getLinkInfo(urlToCheck, clientId, uid, platform ?: Platform.ANDROID)
        if (!result.isSuccessful) {
            return buildBadRequestResponse(result.validationResult)
        }
        return ResponseEntity(result.result, HttpStatus.OK)
    }

    private fun buildBadRequestResponse(result: ValidationResult<*, Defect<*>>): ResponseEntity<Any> = ResponseEntity(
        validationResultConversionService.buildValidationResponse(result),
        HttpStatus.BAD_REQUEST)
}
