package link.at17.mid.tushare.data.crawler.tushare;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * Tushare 请求主体封装
 * @author Barry
 *
 */
@Data
@EqualsAndHashCode(callSuper=false)
public class TushareRequestBody extends JSONObject implements Cloneable {

    private static final long serialVersionUID = 1L;
    private List<String> fields = new ArrayList<>();
    private static final String PARAMS = "params";
    private static final String API_NAME = "api_name";
    private static final String FIELDS = "fields";
    private static final String TOKEN = "token";
    private static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd"); 
    private static final DateTimeFormatter DEFAULT_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 
    
    private String fingerprint = null;
    
    /**
     * 使用 apiName 实例化
     * @param apiName
     */
    public TushareRequestBody(String apiName) {
        put(API_NAME, apiName);
        put(PARAMS, new JSONObject());
        put(FIELDS, null);
        put(TOKEN, null);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TushareRequestBody clone() {
        TushareRequestBody copy = new TushareRequestBody(getString(API_NAME));
        copy.putAll(JSONObject.parseObject(this.toJSONString()));
        copy.fields = (List<String>)JSONObject.parseObject(JSONObject.toJSONString(fields), ArrayList.class);
        
        if (hasFingerprint()) {
            copy.fingerprint = fingerprint;
        }
        
        return copy;
    }
    
    /**
     * 添加多个查询字段，字段间以逗号分隔
     * @param fields
     * @return
     */
    public TushareRequestBody addFields(String fields) {
        Collections.addAll(this.fields, fields.split(","));
        this.fields = this.fields.stream().distinct().collect(Collectors.toList());
        put(FIELDS, this.fields);
        return this;
    }

    /**
     * 添加多个查询字段
     * @param fields
     * @return
     */
    public TushareRequestBody addFields(String... fields) {
        Collections.addAll(this.fields, fields);
        this.fields = this.fields.stream().distinct().collect(Collectors.toList());
        put(FIELDS, this.fields);
        return this;
    }

    /**
     * 添加单个查询字段
     * @param field
     * @return
     */
    public TushareRequestBody addField(String field) {
        fields.add(field);
        fields = fields.stream().distinct().collect(Collectors.toList());
        put(FIELDS, fields);
        return this;
    }

    /**
     * 添加查询参数
     * @param name
     * @param value
     * @return
     */
    public TushareRequestBody addParam(String name, String value) {
        ((JSONObject)get(PARAMS)).put(name, value);
        return this;
    }
    
    /**
     * 添加日期型查询参数，会截断到日期，格式：yyyyMMdd
     * @param name 参数名称
     * @param date 日期
     * @return
     */
    public TushareRequestBody addDateParam(String name, TemporalAccessor date) {
        addParam(name, DEFAULT_DATE_FORMATTER.format(date));
        return this;
    }
    
    /**
     * 添加日期时间查询参数，格式：yyyy-MM-dd HH:mm:ss
     * @param name 参数名称
     * @param dateTime 时间
     * @return
     */
    public TushareRequestBody addDateTimeParam(String name, TemporalAccessor dateTime) {
        addParam(name, DEFAULT_TIME_FORMATTER.format(dateTime));
        return this;
    }

    /**
     * 添加查询参数
     * @param params
     * @return
     */
    public TushareRequestBody addParams(Map<String, String> params) {
        ((JSONObject)get(PARAMS)).putAll(params);
        return this;
    }
    
    public TushareRequestBody setToken(String token) {
        put(TOKEN, token);
        return this;
    }
    
    /**
     * 生成当前请求参数的 fingerprint
     * @return
     */
    public TushareRequestBody generateFingerPrint() {
        if (!hasFingerprint()) {
            StringBuilder sb = new StringBuilder()
                    .append(API_NAME)
                    .append(':')
                    .append(get(API_NAME))
                    .append('|')
                    .append(PARAMS)
                    .append(':')
                    .append(JSON.toJSONString(get(PARAMS)));
            fingerprint = sb.toString();
        }
        return this;
    }
    
    /**
     * 是否有 fingerprint，用于判断请求是否为同一类型
     * @return
     */
    public Boolean hasFingerprint () {
        return StringUtils.isNotEmpty(fingerprint);
    }
    
}
                                                                