package com.lanyuanxiaoyao.digtal.market.runner

import cn.hutool.core.util.NumberUtil
import com.lanyuanxiaoyao.digtal.market.ArticleRepository
import com.lanyuanxiaoyao.digtal.market.keywords
import com.lanyuanxiaoyao.digtal.market.parseArticle
import com.lanyuanxiaoyao.digtal.market.parseArticleLink
import com.lanyuanxiaoyao.digtal.market.service.DescriptionService
import com.lanyuanxiaoyao.digtal.market.sites
import com.lanyuanxiaoyao.squirrel.core.common.Management
import com.lanyuanxiaoyao.squirrel.core.common.PageParseException
import dev.failsafe.RetryPolicy
import jakarta.annotation.Resource
import java.util.concurrent.atomic.AtomicLong
import kotlin.time.Duration.Companion.seconds
import kotlin.time.toJavaDuration
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service

@Service
class NewsRunner : Runner {
    private val logger = LoggerFactory.getLogger(javaClass)
    private val retryPolicy = RetryPolicy
        .builder<Any>()
        .withDelay(10.seconds.toJavaDuration())
        .withMaxRetries(2)
        .handleIf { e -> (e is PageParseException).not() }
        .build()

    @Resource
    private lateinit var articleRepository: ArticleRepository

    @Resource
    private lateinit var descriptionService: DescriptionService

    @Resource
    private lateinit var management: Management

    @Scheduled(cron = "0 0 8-21 * * ?")
    override fun run() {
        sites.forEach { run(it.code) }
    }

    fun run(code: String) {
        sites
            .filter { it.code == code }
            .forEach { site ->
                logger.info("站点: {}", site.name)
                keywords.forEach { keyword ->
                    val url = site.search?.replace("{query}", keyword)
                    logger.info("正在搜索: {}, 地址: {}", keyword, url)
                    val links =
                        try {
                            parseArticleLink(management, site.code, url, false)
                        } catch (e: Exception) {
                            logger.error("解析失败 $url", e)
                            emptyList()
                        }
                    val total = links.size
                    val current = AtomicLong(0)
                    val hashList = articleRepository.findAllId()
                    links
                        .filter {
                            if (hashList.contains(it.hash)) {
                                current.addAndGet(1)
                                false
                            } else true
                        }
                        .forEach { link ->
                            Thread.sleep(1000)
                            logger.info("进度：{} 采集文章：{} {}", NumberUtil.formatPercent(current.addAndGet(1) * 1.0 / total, 2), link.title, link.url)
                            try {
                                parseArticle(management, link)
                                    ?.let { article ->
                                        if (!article.text.isNullOrBlank() || !article.html.isNullOrBlank()) {
                                            val content = if (article.text.isNullOrBlank()) article.html else article.text
                                            val triple = descriptionService.parseDescription(content)
                                            logger.info("标题：{}", triple?.title)
                                            logger.info("作者：{}", triple?.author)
                                            logger.info("副标题：{}", triple?.subtitle)
                                            logger.info("描述：{}", triple?.description)
                                            logger.info("标签：{}", triple?.tags)

                                            article.title = if (link.title.isNullOrBlank()) triple?.title else link.title
                                            article.author = if (article.author.isNullOrBlank()) triple?.author else article.author
                                            article.subtitle = triple?.subtitle
                                            article.description = triple?.description
                                            article.tags = triple?.tags

                                            if (triple == null) {
                                                val error = articleRepository.findErrorById(link.hash)
                                                article.error = error?.plus(1) ?: 1
                                            }
                                        }

                                        article.category = keyword
                                        articleRepository.save(article)
                                    }
                            } catch (e: Exception) {
                                logger.error("解析失败 $link", e)
                            }
                        }
                }
            }
        logger.info("本轮采集完成")
    }
}
