package com.yeejoin.amos.boot.module.common.biz.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.elasticsearch.index.query.QueryBuilders.existsQuery;

@Slf4j
@Service
public class TZSCommonServiceImpl {

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public static final String overdue = "overdue";
    public static final String near = "near";
    public static final String normal = "normal";
    public static final String none = "none";
    public static final String noLicense = "noLicense";
    public static final String noLicenseReq = "noLicenseReq";

    public static final Map<String, String> licensesStatusMap = new HashMap<>(6);
    public static final Map<String, String> permitStatusMap = new HashMap<>(4);
    public static final Map<String, String> inspectionStatusMap = new HashMap<>(4);

    @PostConstruct
    public void init() {
        permitStatusMap.put(overdue, "许可超期");
        permitStatusMap.put(near, "许可临期");
        permitStatusMap.put(normal, "许可正常");
        permitStatusMap.put(none, "无有效期");

        inspectionStatusMap.put(overdue, "检验超期");
        inspectionStatusMap.put(near, "检验临期");
        inspectionStatusMap.put(normal, "检验正常");
        inspectionStatusMap.put(none, "无下次检验日期");

        licensesStatusMap.put(overdue, "资质超期");
        licensesStatusMap.put(near, "资质临期");
        licensesStatusMap.put(normal, "资质正常");
        licensesStatusMap.put(none, "无有效期");
        licensesStatusMap.put(noLicense, "无资质");
        licensesStatusMap.put(noLicenseReq, "无资质要求");
    }

    /**
     * 获取用户的资质状态-从统计服务-综合统计迁移而来
     *
     * @param esUserInfoJson es中的用户数据
     * @return 用户的资质状态
     */
    public String getLicensesStatusWithEsUserInfo(JSONObject esUserInfoJson, String licensesStatusStr) {
        String licensesStatus = null;
        if (esUserInfoJson.containsKey("licenses")) {
            // 以下人员类型有资质要求
            // 人员类型(newPost)：检验人员：66151、检测人员：66152 ,检验检测区域负责人 :6667
            // 人员子类型(subPost)： 持证人员:6713、持证人员(P):6764、持证人员(R2):6765
            String newPost = ObjectUtils.isEmpty(esUserInfoJson.getString("newPost")) ? "" : esUserInfoJson.getString("newPost");
            String subPost = ObjectUtils.isEmpty(esUserInfoJson.getString("subPost")) ? "" : esUserInfoJson.getString("subPost");
            if (newPost.contains("66151") || newPost.contains("66152") || newPost.contains("6667") || subPost.contains("6713") || subPost.contains("6764") || subPost.contains("6765")) {
                JSONArray licenses = esUserInfoJson.getJSONArray("licenses");
                String overdueStr = licensesStatusMap.get(overdue);
                String nearStr = licensesStatusMap.get(near);
                String normalStr = licensesStatusMap.get(normal);
                String noneStr = licensesStatusMap.get(none);
                String noLicenseStr = licensesStatusMap.get(noLicense);
                if (!ObjectUtils.isEmpty(licenses)) {
                    if (!"".equals(licensesStatusStr)) {
                        licensesStatus = licensesStatusMap.get(licensesStatusStr);
                    } else {
                        List<String> permissionStatusList = new ArrayList<>();
                        for (Object object : licenses) {
                            JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(object));
                            if(!json.containsKey("certNo")){
                                permissionStatusList.add(noLicenseStr);
                                continue;
                            }
                            if (!json.containsKey("expiryDate")) {
                                permissionStatusList.add(noneStr);
                                continue;
                            }
                            String expiryDate = json.getString("expiryDate");
                            if (!ObjectUtils.isEmpty(expiryDate)) {
                                long daysBetween = ChronoUnit.DAYS.between(LocalDate.now(), LocalDate.parse(expiryDate, formatter));
                                if (daysBetween < 0) {
                                    permissionStatusList.add(overdueStr);
                                } else if (daysBetween <= 30) {
                                    permissionStatusList.add(nearStr);
                                } else {
                                    permissionStatusList.add(normalStr);
                                }
                            }
                        }
                        long overdue = permissionStatusList.stream().filter(e -> e.equals(overdueStr)).count();
                        long near = permissionStatusList.stream().filter(e -> e.equals(nearStr)).count();
                        long no = permissionStatusList.stream().filter(e -> e.equals(noLicenseStr)).count();
                        long none = permissionStatusList.stream().filter(e -> e.equals(noneStr)).count();
                        long normal = permissionStatusList.stream().filter(e -> e.equals(normalStr)).count();
                        // 需按照资质严重顺序进行判断，先判断超期，再判断临期，在判断无资质，再判断无有效期，最后判断正常
                        if (overdue > 0) {
                            licensesStatus = overdueStr;
                        } else if (near > 0) {
                            licensesStatus = nearStr;
                        } else if (no > 0) {
                            licensesStatus = noLicenseStr;
                        } else if (none > 0) {
                            licensesStatus = noneStr;
                        } else if (normal > 0) {
                            licensesStatus = normalStr;
                        }
                    }
                } else {
                    licensesStatus = noLicenseStr;
                }
            } else {
                licensesStatus = !"".equals(licensesStatusStr) ? licensesStatusMap.get(licensesStatusStr) : licensesStatusMap.get(noLicenseReq);
            }
        }
        return licensesStatus;
    }

    /**
     * 需要资质的人员查询构造条件
     * 无资质:需要资质但是没有填写
     *
     * @return
     */
    public BoolQueryBuilder getNotLicencesBuilderWithPerson() {
        return QueryBuilders.boolQuery()
                .should(QueryBuilders.wildcardQuery("newPost", "*66151*"))
                .should(QueryBuilders.wildcardQuery("newPost", "*66152*"))
                .should(QueryBuilders.wildcardQuery("newPost", "*6667*"))
                .should(QueryBuilders.boolQuery().must(QueryBuilders.wildcardQuery("newPost", "*6552*"))
                        .must(QueryBuilders.wildcardQuery("subPost", "*6713*")))
                .should(QueryBuilders.boolQuery().must(QueryBuilders.wildcardQuery("newPost", "*6763*"))
                        .should(QueryBuilders.wildcardQuery("subPost", "*6764*"))
                        .should(QueryBuilders.wildcardQuery("subPost", "*6765*"))
                        .minimumShouldMatch(1)
                )
                .minimumShouldMatch(1);
    }

    /**
     * 无资质要求的人员查询构造条件
     * 无资质要求：不需要资质
     *
     * @return
     */
    public BoolQueryBuilder getNotNeedLicencesBuilderWithPerson() {
        return QueryBuilders.boolQuery()
                .mustNot(QueryBuilders.wildcardQuery("newPost", "*66151*"))
                .mustNot(QueryBuilders.wildcardQuery("newPost", "*66152*"))
                .mustNot(QueryBuilders.wildcardQuery("newPost", "*6667*"))
                .mustNot(QueryBuilders.boolQuery().must(QueryBuilders.wildcardQuery("newPost", "*6552*"))
                        .must(QueryBuilders.wildcardQuery("subPost", "*6713*")))
                .mustNot(QueryBuilders.boolQuery().must(QueryBuilders.wildcardQuery("newPost", "*6763*"))
                        .should(QueryBuilders.wildcardQuery("subPost", "*6764*"))
                        .should(QueryBuilders.wildcardQuery("subPost", "*6765*"))
                        .minimumShouldMatch(1)
                );
    }

    /**
     * 人员资质状态查询构造条件
     *
     * @param boolMust
     * @param licensesStatus
     * @param path
     * @param nestedField
     */
    public void buildExpiryDateQueryBuilder(BoolQueryBuilder boolMust, String licensesStatus, String path, String nestedField) {
        NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery(
                path,
                existsQuery(path + "." + "certNo"),
                ScoreMode.None
        );
        if (licensesStatus.equals(overdue)) {
            // 不需要资质的人员查询构造条件
            BoolQueryBuilder notNeedLicensesQueryBuilder = this.getNotLicencesBuilderWithPerson();
            boolMust.must(notNeedLicensesQueryBuilder);
            // 超期：小于当前日期
            NestedQueryBuilder overdueQuery = QueryBuilders.nestedQuery(
                    path,
                    QueryBuilders.rangeQuery(nestedField).lt(LocalDate.now().format(formatter)),
                    ScoreMode.None
            );
            boolMust.must(overdueQuery);
            boolMust.must(nestedQuery);
        } else if (licensesStatus.equals(near)) {
            // 不需要资质的人员查询构造条件
            BoolQueryBuilder notNeedLicensesQueryBuilder = this.getNotLicencesBuilderWithPerson();
            boolMust.must(notNeedLicensesQueryBuilder);
            // 临期：小于等于当前日期加上30天
            NestedQueryBuilder nearQuery = QueryBuilders.nestedQuery(
                    path,
                    QueryBuilders.rangeQuery(nestedField).lte(LocalDate.now().plusDays(30).format(formatter)).gte(LocalDate.now().format(formatter)),
                    ScoreMode.None
            );
            boolMust.must(nearQuery);
            boolMust.must(nestedQuery);
        } else if (licensesStatus.equals(normal)) {
            // 不需要资质的人员查询构造条件
            BoolQueryBuilder notNeedLicensesQueryBuilder = this.getNotLicencesBuilderWithPerson();
            boolMust.must(notNeedLicensesQueryBuilder);
            // 正常：大于当前日期加上30天
            NestedQueryBuilder normalQuery = QueryBuilders.nestedQuery(
                    path,
                    QueryBuilders.rangeQuery(nestedField).gt(LocalDate.now().plusDays(30).format(formatter)),
                    ScoreMode.None
            );
            boolMust.must(normalQuery);
            boolMust.must(nestedQuery);
        } else if (licensesStatus.equals(none)) {
            // 不需要资质的人员查询构造条件
            BoolQueryBuilder notNeedLicensesQueryBuilder = this.getNotLicencesBuilderWithPerson();
            boolMust.must(notNeedLicensesQueryBuilder);
            // 无有效期
            NestedQueryBuilder noneQuery = QueryBuilders.nestedQuery(
                    path,
                    QueryBuilders.boolQuery().mustNot(existsQuery(nestedField)),
                    ScoreMode.None
            );
            boolMust.must(noneQuery);
            boolMust.must(nestedQuery);
        }
        // 只在人员列表处用到
        // 综合统计处未用到下面的条件，理论上走不到下面俩条件
        else if (licensesStatus.equals(noLicense)) {
            // 无资质
            BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
            meBuilder.must(this.getNotLicencesBuilderWithPerson());
            meBuilder.must(QueryBuilders.boolQuery().mustNot(nestedQuery));
            boolMust.must(nestedQuery);
        } else if (licensesStatus.equals(noLicenseReq)) {
            // 无资质要求
            boolMust.must(this.getNotNeedLicencesBuilderWithPerson());
        }
    }
}