package me.qwq.doghouse.controller.api.v1;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.apache.commons.lang3.StringUtils;
import org.jdom2.DocType;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import me.qwq.dogface.Dogface;
import me.qwq.doghouse.component.Rk;
import me.qwq.doghouse.exception.PageNotFoundException;
import me.qwq.doghouse.pojo.dto.DailyPostCommentStats;
import me.qwq.doghouse.pojo.dto.R;
import me.qwq.doghouse.service.CommentService;
import me.qwq.doghouse.service.StatisticsService;
import me.qwq.doghouse.util.CompressUtils;
import me.qwq.doghouse.util.GravatarUtils;

@RestController
@RequestMapping("/api/v1")
@Slf4j
public class ApiControllerV1 {
    
    private static final Namespace SVG_NAMESPACE = Namespace.getNamespace("http://www.w3.org/2000/svg");

    private static final String[] POST_FILLS_VAR = {"var(--post-fill-0)", "var(--post-fill-1)", "var(--post-fill-2)", "var(--post-fill-3)", "var(--post-fill-4)"};
    private static final String[] POST_STROKES_VAR = {"var(--post-stroke-0)", "var(--post-stroke-1)", "var(--post-stroke-2)", "var(--post-stroke-3)", "var(--post-stroke-4)"};
    private static final String[] COMMENT_FILLS_VAR = {"var(--comment-fill-0)", "var(--comment-fill-1)", "var(--comment-fill-2)", "var(--comment-fill-3)", "var(--comment-fill-4)"};
    private static final String[] COMMENT_STROKES_VAR = {"var(--comment-stroke-0)", "var(--comment-stroke-1)", "var(--comment-stroke-2)", "var(--comment-stroke-3)", "var(--comment-stroke-4)"};
    
    @Autowired
    StatisticsService statisticsService;
    
    @Autowired
    GravatarUtils gravatarUtils;
    
    @Autowired
    CommentService commentService;
    
    @Autowired
    Dogface dogface;

    @Autowired
    HttpServletRequest request;
    
    @Autowired
    HttpServletResponse response;

    @GetMapping(value={
            "/gravatar/{hash}", 
            "/gravatar/{hash}/{size}"}, produces = MediaType.IMAGE_JPEG_VALUE)
    public byte[] getGravatar(@PathVariable(value="hash") String hash,
            @PathVariable(value="size", required=false) Integer size, 
            @RequestParam(required=false) String nocache) {

        if (size == null || size <= 0) size = 36;
        Future<byte[]> future = 
                gravatarUtils.getReversedProxyGravatarAsync(hash, size, StringUtils.isBlank(nocache));
        
        byte[] avatar;
        try {
            avatar = future.get();
        }
        catch (InterruptedException | ExecutionException e) {
            throw new PageNotFoundException();
        }
        if (avatar == null) {
            throw new PageNotFoundException();
        }
        try {
            response.setHeader("Content-Encoding", "gzip");
            return CompressUtils.compressGZ(avatar);
        }
        catch (IOException e) {
            log.error("GZIP 压缩 gravatar 头像错误", e);
            throw new PageNotFoundException();
        }
    }
    
    @GetMapping(value={
            "/dogavatar/{hash}", 
            "/dogavatar/{hash}/{size}"}, produces = MediaType.IMAGE_PNG_VALUE)
    public byte[] getDogavatar(@PathVariable(value="hash") String hash,
            @PathVariable(value="size", required=false) Integer size) throws IOException {
        
        if (size == null || size <= 0) size = 36;
        byte[] avatar = dogface.getDogavatar(hash, size);
        if (avatar == null) {
            throw new PageNotFoundException();
        }
        try {
            response.setHeader("Content-Encoding", "gzip");
            return CompressUtils.compressGZ(avatar);
        }
        catch (IOException e) {
            log.error("GZIP 压缩 gravatar 头像错误", e);
            throw new PageNotFoundException();
        }
    }
    @GetMapping(value={
            "/gravatars/clearCache"})
    public R<?> clearGravatarCache() {
        
        Rk.Gravatar.clearGravatarCache();
        return R.ok();
        
    }
    
    
    private static String colorClassifier(int count, String[] colorSet) {
        if (count < 0) count = 0;
        if (count < 4) return colorSet[count];
        return colorSet[4];
    }
    
    @GetMapping(path="/getPassDaysStatistics", produces="application/json")
    public DailyPostCommentStats getPassDaysStatistics(Integer passDays) {
        return statisticsService.getPostAndCommentCountsWithDates(passDays, null);
    }
    
    public String gitLikeStatisticsSvg(Integer cols, Integer rows) {

        if (cols == null || cols < 1) {
            cols = 1;
        }
        if (rows == null || rows < 1) {
            rows = 1;
        }
        
        int span = 2, size = 8, stroke = 1;
        
        Integer total = cols * rows;

        
        Element svgRoot = new Element("svg");
        // 设置命名空间
        svgRoot.setNamespace(SVG_NAMESPACE);
        
        int
        w = (span + size) * cols - span + stroke * 2,
        h = (span + size) * rows - span + stroke * 2;
        
        svgRoot.setAttribute("width", "100%");
        svgRoot.setAttribute("height", "100%");
        svgRoot.setAttribute("viewBox", String.format("0 0 %d %d", w, h));
        
        // 获取 n 日以来的文章和评论统计
        DailyPostCommentStats s = statisticsService.getPostAndCommentCountsWithDates(total, null);

        List<String> dates = s.dates();
        List<Integer> postCounts = s.postCounts();
        List<Integer> commentCounts = s.commentCounts();
        
        for (int col = 0; col < cols; col++) {
            for (int row = 0; row < rows; row++) {
                int offset = col * rows + row;
                String date = dates.get(offset);
                Integer posts = postCounts.get(offset);
                Integer comments = commentCounts.get(offset);
                Boolean hasPost = posts != 0;
                Boolean hasComment = comments != 0;
                
                int x = stroke + (span + size) * col;
                int y = stroke + (span + size) * row;
                
                Element postRect = new Element("rect");
                postRect.setAttribute("x", Integer.toString(x));
                postRect.setAttribute("y", Integer.toString(y));
                
                postRect.setAttribute("stroke-width", "1.2");
                postRect.setAttribute("stroke", 
                        !hasComment ? 
                            colorClassifier(posts, POST_STROKES_VAR) :
                            colorClassifier(comments, COMMENT_STROKES_VAR));
                
                postRect.setAttribute("width", Integer.toString(size));
                postRect.setAttribute("height", Integer.toString(size));
                postRect.setAttribute("rx", Integer.toString(stroke));
                postRect.setAttribute("ry", Integer.toString(stroke));
                postRect.setAttribute("fill", 
                        (hasComment && !hasPost) ?
                        colorClassifier(comments, COMMENT_FILLS_VAR):
                        colorClassifier(posts, POST_FILLS_VAR));
                
                postRect.setAttribute("data-posts", posts.toString());
                postRect.setAttribute("data-comments", comments.toString());
                postRect.setAttribute("data-date", date);
                postRect.setNamespace(SVG_NAMESPACE);

                // 将矩形元素添加到 <svg> 元素中
                svgRoot.addContent(postRect);
            }
        }

        // 创建文档对象
        Document svgDoc = new Document(svgRoot);
        DocType svgDocType = new DocType("svg");
        svgDoc.setDocType(svgDocType);

        // 输出SVG文档到控制台
        XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
        return xmlOutputter.outputString(svgDoc);
    }

}