package com.ruoyi.web.core.config;

import com.fasterxml.jackson.databind.JavaType;
import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import lombok.Getter;
import lombok.Setter;
import org.springdoc.core.providers.ObjectMapperProvider;

import javax.validation.constraints.Min;
import java.util.Iterator;
import java.util.List;

public class PageModelsConverter implements ModelConverter {

    private static final String PAGE_TO_REPLACE = "org.springframework.data.domain.Page";

    private static final String PAGE_IMPL_TO_REPLACE = "org.springframework.data.domain.PageImpl";

    private final ObjectMapperProvider springDocObjectMapper;

    public PageModelsConverter(ObjectMapperProvider springDocObjectMapper) {
        this.springDocObjectMapper = springDocObjectMapper;
    }

    @Override
    public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
        JavaType javaType = springDocObjectMapper.jsonMapper().constructType(type.getType());
        if (javaType != null) {
            Class<?> cls = javaType.getRawClass();
            if (PAGE_TO_REPLACE.equals(cls.getCanonicalName()) || PAGE_IMPL_TO_REPLACE.equals(cls.getCanonicalName())) {
                JavaType replaceJavaType = springDocObjectMapper.jsonMapper().getTypeFactory()
                        .constructType(Page.class, javaType.getBindings());
                type = new AnnotatedType(replaceJavaType).resolveAsRef(true);
            }
        }
        return (chain.hasNext()) ? chain.next().resolve(type, context, chain) : null;
    }

    @Getter
    @Setter
    public static class Page<T> {

        @Min(0)
        @io.swagger.v3.oas.annotations.media.Schema(description = "每页记录数")
        private int size;

        @Min(0)
        @io.swagger.v3.oas.annotations.media.Schema(description = "当前页号，从0开始")
        private int page;

        @Min(0)
        @io.swagger.v3.oas.annotations.media.Schema(description = "总记录数")
        private int totalElements;

        @Min(0)
        @io.swagger.v3.oas.annotations.media.Schema(description = "总页数")
        private int totalPages;

        @ArraySchema(arraySchema = @io.swagger.v3.oas.annotations.media.Schema(description = "当前页的记录列表"))
        private List<T> content;
    }
}
