package com.lanyuanxiaoyao.digtal.market.controller

import cn.hutool.core.date.LocalDateTimeUtil
import com.lanyuanxiaoyao.digtal.market.ArticleRepository
import com.lanyuanxiaoyao.digtal.market.sites
import com.lanyuanxiaoyao.squirrel.core.common.Site
import jakarta.annotation.Resource
import jakarta.persistence.criteria.Predicate
import java.sql.Date
import java.time.Instant
import org.slf4j.LoggerFactory
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
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

@RestController
@RequestMapping("overview")
class OverviewController {
    private val logger = LoggerFactory.getLogger(javaClass)

    @Resource
    private lateinit var articleRepository: ArticleRepository

    @GetMapping("news")
    fun news(
        @RequestParam("code", required = false) code: String?,
        @RequestParam("filter_keyword", required = false) filterKeyword: String?,
        @RequestParam("filter_date", required = false) filterDate: Long?,
        @RequestParam("filter_date_start", required = false) filterDateStart: Long?,
        @RequestParam("filter_date_end", required = false) filterDateEnd: Long?,
        @RequestParam("filter_source", required = false) filterSource: String?,
        @RequestParam("filter_author", required = false) filterAuthor: String?,
        @RequestParam("filter_category", required = false) filterCategory: String?,
        @RequestParam("page", defaultValue = "1") page: Int,
        @RequestParam("count", defaultValue = "10") count: Int,
    ): Map<String, Any> {
        val pageRequest = PageRequest.of(page - 1, count, Sort.by(Sort.Direction.DESC, "createTime"))
        val result = articleRepository.findAll({ root, _, builder ->
            val predictions = mutableListOf<Predicate>()
            filterKeyword?.let {
                predictions.add(
                    builder.or(
                        builder.like(root.get("title"), "%${it}%"),
                        builder.like(root.get("subtitle"), "%${it}%"),
                        builder.like(root.get("text"), "%${it}%"),
                        builder.like(root.get("description"), "%${it}%"),
                    )
                )
            }
            if (filterDate != null) {
                val datetime = LocalDateTimeUtil.of(filterDate * 1000)
                predictions.add(
                    builder.between(
                        root.get<Date>("createTime"),
                        Date.from(Instant.ofEpochMilli(LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.beginOfDay(datetime)))),
                        Date.from(Instant.ofEpochMilli(LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.endOfDay(datetime))))
                    )
                )
            } else if (filterDateStart != null && filterDateEnd != null) {
                predictions.add(
                    builder.between(root.get<Date>("createTime"), Date.from(Instant.ofEpochSecond(filterDateStart)), Date.from(Instant.ofEpochSecond(filterDateEnd)))
                )
            }
            filterSource?.let {
                val site = sites.firstOrNull { site -> site.name == it }
                if (site != null) {
                    predictions.add(
                        builder.equal(root.get<String>("code"), site.code)
                    )
                }
            }
            filterAuthor?.let {
                predictions.add(
                    builder.equal(root.get<String>("author"), it)
                )
            }
            filterCategory?.let {
                predictions.add(
                    builder.equal(root.get<String>("category"), it)
                )
            }
            builder.and(*predictions.toTypedArray())
        }, pageRequest)
        articleRepository.findAll({ builder ->
            builder.build()
        }, pageRequest)
        return mapOf(
            "items" to result.content.map {
                val site = sites.find { site -> site.code == it.code }!!
                val iframe = (site.options?.contains(Site.Option.OPEN_WITH_IFRAME) ?: false)
                mapOf(
                    "name" to site.name,
                    "code" to it.code,
                    "title" to it.title,
                    "subtitle" to it.subtitle,
                    "author" to it.author,
                    "description" to it.description,
                    "url" to it.url,
                    "createTime" to it.createTime,
                    "iframe" to iframe,
                    "category" to it.category,
                    "tags" to it.tags,
                )
            },
            "total" to result.totalElements,
        )
    }

    @GetMapping("all_source")
    fun allSource() = sites.map { it.name }

    @GetMapping("all_category")
    fun allCategory() = articleRepository.findAllCategory()

    @GetMapping("all_author")
    fun allAuthor() = articleRepository.findAllAuthor()
}