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

import org.slf4j.Logger
import org.slf4j.LoggerFactory
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.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import ru.yandex.direct.core.entity.uac.service.appinfo.ParseAppStoreUrlService
import ru.yandex.direct.core.entity.uac.service.appinfo.ParseAppStoreContentService.ParseAppStoreContentException
import ru.yandex.direct.core.entity.uac.validation.invalidAppUrl
import ru.yandex.direct.core.security.authorization.PreAuthorizeRead
import ru.yandex.direct.validation.result.ValidationResult
import ru.yandex.direct.web.core.security.DirectWebAuthenticationSource
import ru.yandex.direct.web.entity.uac.model.AppInfoWithContent
import ru.yandex.direct.core.service.appinfo.UacAppInfoParsingService
import ru.yandex.direct.web.entity.uac.model.ParseAppInfoRequest
import ru.yandex.direct.web.validation.kernel.ValidationResultConversionService

@RestController
@Api(tags = ["uac"])
@RequestMapping("/uac", produces = [MediaType.APPLICATION_JSON_VALUE])
open class UacAppInfoParsingController(
    private val parseAppStoreUrlService: ParseAppStoreUrlService,
    private val validationResultConversionService: ValidationResultConversionService,
    private val appInfoParsingService: UacAppInfoParsingService,
    private val authenticationSource: DirectWebAuthenticationSource,
) {
    companion object {
        private val logger: Logger = LoggerFactory.getLogger(UacAppInfoParsingController::class.java)
    }

    @ApiOperation(
        value = "appInfoParsing",
        httpMethod = "POST",
        nickname = "appInfoParsing",
    )
    @PreAuthorizeRead
    @PostMapping(
        value = ["app_info/parsing"],
        consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE],
        produces = [MediaType.APPLICATION_JSON_UTF8_VALUE],
    )
    open fun parseFromStoreOrTrackingUrl(
        @RequestBody request: ParseAppInfoRequest
    ): ResponseEntity<Any> {
        val appStoreUrlValidation = parseAppStoreUrlService.getAppStoreUrl(request.url)
        if (appStoreUrlValidation.hasErrors()) {
            return ResponseEntity(
                validationResultConversionService.buildValidationResponse(
                    appStoreUrlValidation
                ),
                HttpStatus.BAD_REQUEST
            )
        }
        val url = appStoreUrlValidation.value

        try {
            val (appInfo, contents) = appInfoParsingService.getFromCacheOrParse(
                url,
                request.cacheTtl ?: -1
            )
            val regionWithName = appInfoParsingService.getDefaultTargetRegionWithName(
                region = url.parsedUrl.storeCountry,
                lang = authenticationSource.authentication.subjectUser.lang.toString()
            )

            return ResponseEntity.ok(
                AppInfoWithContent(
                    appInfo = appInfo,
                    contents = contents,
                    isTrackingUrl = url.fromTrackingUrl,
                    defaultTargetRegion = regionWithName?.first,
                    defaultTargetRegionName = regionWithName?.second,
                )
            )
        } catch (e: ParseAppStoreContentException) {
            logger.error("Failed to parse store", e)
            return ResponseEntity(validationResultConversionService.buildValidationResponse(
                    ValidationResult.failed(null, invalidAppUrl())
                ),
                HttpStatus.BAD_REQUEST)
        }
    }
}
