package com.lanyuanxiaoyao.bookstore.controller

import cn.hutool.core.util.IdUtil
import com.lanyuanxiaoyao.bookstore.Book
import com.lanyuanxiaoyao.bookstore.BookRepository
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("book")
class BookController {
    private val log = LoggerFactory.getLogger(javaClass)

    @Resource
    private lateinit var bookRepository: BookRepository

    @GetMapping("list")
    fun list(
        @RequestParam("page", defaultValue = "1") page: Int,
        @RequestParam("size", defaultValue = "10") size: Int
    ): PageResponse<ViewItem> {
        val pageable = bookRepository.findAll(PageRequest.of(0.coerceAtLeast(page - 1), size))
        return PageResponse(
            pageable.content.map { ViewItem(it) },
            pageable.totalElements,
        )
    }

    @Transactional
    @PostMapping("save")
    fun save(@RequestBody item: ViewItem) {
        bookRepository.save(
            Book(
                bookId = item.bookId ?: IdUtil.fastSimpleUUID(),
                name = item.name,
                author = item.author,
                description = item.description,
                source = item.source,
                tags = item.tags?.toMutableSet() ?: mutableSetOf()
            )
        )
    }

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

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

    @GetMapping("tags")
    fun tags(): List<String> {
        return bookRepository.findAllTag()
    }

    data class ViewItem(
        val bookId: String?,
        val name: String,
        val author: String?,
        val description: String,
        val source: String?,
        val tags: Set<String>?,
    ) {
        constructor(book: Book) : this(
            book.bookId,
            book.name,
            book.author,
            book.description,
            book.source,
            book.tags,
        )
    }
}