package com.arms.api.blog.service;

import com.arms.api.blog.model.vo.BlogVO;
import com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery;
import com.arms.egovframework.javaservice.esframework.model.dto.esquery.SearchDocDTO;
import com.arms.egovframework.javaservice.esframework.model.dto.esquery.SortDTO;
import com.arms.egovframework.javaservice.esframework.model.vo.DocumentResultWrapper;
import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import com.arms.api.blog.model.entity.BlogDTO;
import com.arms.api.blog.model.entity.BlogEntity;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Component
@AllArgsConstructor
@Slf4j
public class BlogServiceImpl implements BlogService {

    private final EsCommonRepositoryWrapper<BlogEntity> esCommonRepositoryWrapper;

    @Override
    @Transactional
    public Long addBlog(BlogDTO blogDTO) {
        BlogEntity blogEntity = blogDTO.createBlogEntity();
        BlogEntity savedEntity = esCommonRepositoryWrapper.save(blogEntity);
        return savedEntity.getC_id();
    }

    @Override
    @Transactional
    public Long updateBlog(BlogDTO blogDTO) {
        if (esCommonRepositoryWrapper.findDocById(blogDTO.getC_id()) == null) {
            throw new IllegalArgumentException("블로그 글을 찾을 수 없습니다.");
        }

        BlogEntity willUpdateEntity = blogDTO.createBlogEntity();
        esCommonRepositoryWrapper.save(willUpdateEntity);
        return willUpdateEntity.getC_id();
    }

    @Override
    @Transactional(readOnly = true)
    public BlogEntity getBlog(BlogDTO blogDTO) {
        Long c_id = blogDTO.getC_id();
        String c_blog_contents = blogDTO.getC_blog_contents();
        BlogEntity existingEntity = esCommonRepositoryWrapper.findDocById(c_id);

        if (existingEntity == null) {
            if (c_blog_contents != null && !c_blog_contents.isEmpty()) {
                BlogEntity willCreateEntity = blogDTO.createBlogEntity();
                asyncViewCountUp(c_id);
                esCommonRepositoryWrapper.save(willCreateEntity);
                return willCreateEntity;
            }
            throw new IllegalArgumentException("블로그 글을 찾을 수 없습니다.");
        }

        asyncViewCountUp(c_id);
        return existingEntity;
    }

    @Override
    @Transactional
    public Long removeBlog(Long blogId) {
        esCommonRepositoryWrapper.deleteById(blogId);
        return blogId;
    }

    @Override
    @Async
    public void asyncViewCountUp(Long blogId) {
        BlogEntity existingEntity = esCommonRepositoryWrapper.findDocById(blogId);

        if (existingEntity != null) {
            existingEntity.viewCountUp();
            esCommonRepositoryWrapper.save(existingEntity);
        } else {
            log.warn("블로그 글을 찾을 수 없습니다: {}", blogId);
        }
    }

    @Override
    public List<BlogEntity> getBlogListByViewCountDesc(BlogDTO blogDTO) {
        blogDTO.setSize(20);
        return getList(
                SimpleQuery
                        .search(blogDTO)
                        .orderBy(SortDTO.builder().field("c_blog_view_count").sortType("desc").build(),
                                SortDTO.builder().field("c_blog_created").sortType("desc").build()))
                .getBlogEntities();
    }

    @Override
    public BlogVO searchBlog(BlogDTO blogDTO) {
        return getList(
                SimpleQuery
                        .search(blogDTO)
                        .andMatchQueryFilter("c_blog_title", blogDTO.getC_blog_title())
                        .andMatchQueryFilter("c_blog_contents", blogDTO.getC_blog_contents())
                        .orderBy(SortDTO.builder().field("c_blog_view_count").sortType("desc").build(),
                                SortDTO.builder().field("c_blog_created").sortType("desc").build()));
    }


    private BlogVO getList(SimpleQuery<SearchDocDTO> simpleQuery) {
        DocumentResultWrapper<BlogEntity> docsBySearchAfter = esCommonRepositoryWrapper.findHits(simpleQuery);

        List<BlogEntity> docs = docsBySearchAfter.toDocs();

        return BlogVO.builder().blogEntities(docs)
                .totalHits(docsBySearchAfter.getTotalHits())
                .searchAfter(docsBySearchAfter.getLastSortValue()).build();

    }

}

