package com.lanyuanxiaoyao.bookstore.controller

import cn.hutool.core.util.IdUtil
import com.lanyuanxiaoyao.bookstore.Chapter
import com.lanyuanxiaoyao.bookstore.ChapterRepository
import com.lanyuanxiaoyao.bookstore.Line
import com.lanyuanxiaoyao.bookstore.LineRepository
import com.lanyuanxiaoyao.bookstore.PageResponse
import jakarta.annotation.Resource
import jakarta.transaction.Transactional
import org.slf4j.LoggerFactory
import org.springframework.data.domain.PageRequest
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

@RestController
@RequestMapping("line")
class LineController {
    private val log = LoggerFactory.getLogger(javaClass)

    @Resource
    private lateinit var chapterRepository: ChapterRepository

    @Resource
    private lateinit var lineRepository: LineRepository

    @GetMapping("list/{chapterId}")
    fun list(
        @PathVariable("chapterId") chapterId: String,
        @RequestParam("page", defaultValue = "1") page: Int,
        @RequestParam("size", defaultValue = "10") size: Int
    ): PageResponse<ViewItem> {
        val pageable = lineRepository.findAll({ root, _, builder ->
            builder.equal(root.get<Chapter>("chapter").get<String>("chapterId"), chapterId)
        }, PageRequest.of(0.coerceAtLeast(page - 1), size))
        return PageResponse(
            pageable.content.map { ViewItem(it) },
            pageable.totalElements,
        )
    }

    @Transactional
    @PostMapping("save/{lineId}")
    fun save(@PathVariable("lineId") lineId: String, @RequestBody item: ViewItem) {
        val chapter = chapterRepository.findById(lineId).orElseThrow()
        lineRepository.save(
            Line(
                lineId = item.lineId ?: IdUtil.fastSimpleUUID(),
                sequence = item.sequence,
                text = item.text,
                chapter = chapter,
            )
        )
    }

    @Transactional
    @PostMapping("update/{lineId}")
    fun update(@PathVariable("lineId") lineId: String, @RequestBody item: ViewItem) {
        val line = lineRepository.findById(lineId).orElseThrow()
        line.text = item.text
        lineRepository.save(line)
    }

    @GetMapping("detail/{lineId}")
    fun detail(@PathVariable("lineId") lineId: String): ViewItem {
        return lineRepository.findById(lineId).orElseThrow().let { ViewItem(it) }
    }

    @Transactional
    @GetMapping("remove/{lineId}")
    fun remove(@PathVariable("lineId") lineId: String) {
        lineRepository.deleteById(lineId)
    }

    data class ViewItem(
        val lineId: String?,
        val sequence: Long,
        val text: String,
    ) {
        constructor(line: Line) : this(
            line.lineId,
            line.sequence,
            line.text,
        )
    }
}