package org.nstart.dep265.requestservice.controller

import jakarta.validation.Valid
import org.nstart.dep265.requestservice.dto.CreateRequestDto
import org.nstart.dep265.requestservice.dto.CreateRequestResponseDto
import org.nstart.dep265.requestservice.dto.DeleteRequestResponseDto
import org.nstart.dep265.requestservice.dto.RequestListFilter
import org.nstart.dep265.requestservice.dto.RequestListResponseDto
import org.nstart.dep265.requestservice.dto.RequestMapPageDto
import org.nstart.dep265.requestservice.dto.RequestResponseDto
import org.nstart.dep265.requestservice.dto.RequestStatusDto
import org.nstart.dep265.requestservice.dto.RequestWithCellsResponseDto
import org.nstart.dep265.requestservice.dto.SurveyTypeDto
import org.nstart.dep265.requestservice.service.RequestService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
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.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime
import java.util.UUID

@RestController
@RequestMapping("/v1/requests")
class RequestController(
    private val requestService: RequestService,
) {
    @PostMapping
    fun createRequest(@Valid @RequestBody request: CreateRequestDto): ResponseEntity<CreateRequestResponseDto> {
        return ResponseEntity.status(201).body(requestService.createRequest(request))
    }

    @GetMapping
    fun listRequests(
        @RequestParam(required = false) status: RequestStatusDto?,
        @RequestParam(required = false) surveyType: SurveyTypeDto?,
        @RequestParam(required = false) kpp: Int?,
        @RequestParam(required = false) highPriorityTransmit: Boolean?,
        @RequestParam(required = false) beginFrom: LocalDateTime?,
        @RequestParam(required = false) beginTo: LocalDateTime?,
        @RequestParam(required = false) endFrom: LocalDateTime?,
        @RequestParam(required = false) endTo: LocalDateTime?,
        @RequestParam(defaultValue = "false") includeDeleted: Boolean,
        @RequestParam(defaultValue = "0") page: Int,
        @RequestParam(defaultValue = "50") size: Int,
        @RequestParam(defaultValue = "createdAt,desc") sort: String,
    ): RequestListResponseDto {
        val query = RequestListFilter(
            status = status,
            surveyType = surveyType,
            kpp = kpp,
            highPriorityTransmit = highPriorityTransmit,
            beginFrom = beginFrom,
            beginTo = beginTo,
            endFrom = endFrom,
            endTo = endTo,
            includeDeleted = includeDeleted,
            page = page,
            size = size,
            sort = sort,
        )
        return requestService.listRequests(query)
    }

    @GetMapping("/map")
    fun listRequestsForMap(
        @RequestParam(required = false) status: RequestStatusDto?,
        @RequestParam(required = false) surveyType: SurveyTypeDto?,
        @RequestParam(required = false) kpp: Int?,
        @RequestParam(required = false) highPriorityTransmit: Boolean?,
        @RequestParam(required = false) beginFrom: LocalDateTime?,
        @RequestParam(required = false) beginTo: LocalDateTime?,
        @RequestParam(required = false) endFrom: LocalDateTime?,
        @RequestParam(required = false) endTo: LocalDateTime?,
        @RequestParam(defaultValue = "false") includeDeleted: Boolean,
        @RequestParam(defaultValue = "0") page: Int,
        @RequestParam(defaultValue = "50") size: Int,
        @RequestParam(defaultValue = "createdAt,desc") sort: String,
    ): RequestMapPageDto {
        val query = RequestListFilter(
            status = status,
            surveyType = surveyType,
            kpp = kpp,
            highPriorityTransmit = highPriorityTransmit,
            beginFrom = beginFrom,
            beginTo = beginTo,
            endFrom = endFrom,
            endTo = endTo,
            includeDeleted = includeDeleted,
            page = page,
            size = size,
            sort = sort,
        )
        return requestService.listRequestsForMap(query)
    }

    @GetMapping("/{id}")
    fun getRequestById(@PathVariable id: UUID): ResponseEntity<RequestResponseDto> {
        return requestService.getRequestById(id)
            ?.let { request -> ResponseEntity.ok(request) }
            ?: ResponseEntity.notFound().build()
    }

    @GetMapping("/{id}/cells")
    fun getRequestWithCells(@PathVariable id: UUID): ResponseEntity<RequestWithCellsResponseDto> {
        return requestService.getRequestWithCells(id)
            ?.let { response -> ResponseEntity.ok(response) }
            ?: ResponseEntity.notFound().build()
    }

    @DeleteMapping("/{id}")
    fun deleteRequest(@PathVariable id: UUID): ResponseEntity<DeleteRequestResponseDto> {
        return requestService.deleteRequest(id)
            ?.let { response -> ResponseEntity.ok(response) }
            ?: ResponseEntity.notFound().build()
    }
}
