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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.jg.api.dto.JgUseRegistrationManageDto;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CertificateStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CylinderTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgUseRegistrationEqMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgUseRegistrationManageMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgUseRegistrationMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgVehicleInformationMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgUseRegistrationManageService;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgUseInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2024-07-03
 */
@Service
public class JgUseRegistrationManageServiceImpl extends BaseService<JgUseRegistrationManageDto, JgUseRegistrationManage, JgUseRegistrationManageMapper> implements IJgUseRegistrationManageService {

    @Autowired
    RestHighLevelClient restHighLevelClient;

    @Autowired
    private JgUseRegistrationManageMapper jgUseRegistrationManageMapper;

    @Autowired
    private JgUseRegistrationMapper jgUseRegistrationMapper;

    @Autowired
    private JgUseRegistrationEqMapper jgUseRegistrationEqMapper;

    @Autowired
    private CommonServiceImpl commonServiceImpl;

    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;

    @Autowired
    private JgVehicleInformationMapper jgVehicleInformationMapper;


    @Autowired
    private JgCertificateChangeRecordServiceImpl jgCertificateChangeRecordService;

    @Autowired
    private JgUseRegistrationServiceImpl jgUseRegistrationService;

    @Autowired
    private JgVehicleInformationServiceImpl jgVehicleInformationService;

    /**
     * 将已经通过使用登记审批的证信息录入到 jg-use-registration-manage 表中
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean brushHistoryCertificate() {
        this.baseMapper.delete(new LambdaQueryWrapper<>());

        // 使用登记表中已经审批通过的单子
        List<JgUseRegistration> jgUseRegistrations = jgUseRegistrationMapper.selectList(new LambdaQueryWrapper<JgUseRegistration>()
                .eq(JgUseRegistration::getStatus, "已完成")
                .eq(JgUseRegistration::getIsDelete, false));
        for (JgUseRegistration useRegistration : jgUseRegistrations) {
            // 使用单位信息
            Map<String, Object> enterpriseInfo = commonServiceImpl.getEnterpriseInfo(useRegistration.getUseUnitCreditCode());
            // 设备使用地址
            String fullAddress = "";
            // 设备种类/类别/品种
            Map<String, String> equType = jgUseRegistrationMapper.getEquTypeByUseRegSeq(String.valueOf(useRegistration.getSequenceNbr()));
            if (!"unit".equals(useRegistration.getManageType())) {
                List<JgUseRegistrationEq> jgUseRegistrationEqs = jgUseRegistrationEqMapper.selectList(new LambdaQueryWrapper<JgUseRegistrationEq>()
                        .eq(JgUseRegistrationEq::getEquipTransferId, useRegistration.getSequenceNbr()));
                if (!ValidationUtil.isEmpty(jgUseRegistrationEqs)) {
                    String equId = jgUseRegistrationEqs.get(0).getEquId();
                    IdxBizJgUseInfo useInfo = idxBizJgUseInfoService.getOne(new QueryWrapper<IdxBizJgUseInfo>()
                            .eq("RECORD", equId));
                    if (!ObjectUtils.isEmpty(useInfo.getProvinceName())) {
                        fullAddress += useInfo.getProvinceName();
                    }
                    if (!ObjectUtils.isEmpty(useInfo.getCityName())) {
                        fullAddress += useInfo.getCityName();
                    }
                    if (!ObjectUtils.isEmpty(useInfo.getCountyName())) {
                        fullAddress += useInfo.getCountyName();
                    }
                    if (!ObjectUtils.isEmpty(useInfo.getStreetName())) {
                        fullAddress += useInfo.getStreetName();
                    }
                    if (!ObjectUtils.isEmpty(useInfo.getAddress())) {
                        fullAddress += useInfo.getAddress();
                    }
                }
            }
            // 组装数据
            JgUseRegistrationManage jgUseRegistrationManage = new JgUseRegistrationManage();
            jgUseRegistrationManage.setUseUnitName(useRegistration.getUseUnitName());
            jgUseRegistrationManage.setApplyNo(useRegistration.getApplyNo());
            jgUseRegistrationManage.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
            jgUseRegistrationManage.setReceiveOrgName(useRegistration.getReceiveOrgName());
            jgUseRegistrationManage.setAuditPassDate(useRegistration.getAuditPassDate());
            jgUseRegistrationManage.setRegType(BusinessTypeEnum.JG_USAGE_REGISTRATION.getName());
            jgUseRegistrationManage.setRegDate(useRegistration.getRegDate());
            jgUseRegistrationManage.setEquList(equType.get("equList"));
            jgUseRegistrationManage.setEquListCode(equType.get("equListCode"));
            jgUseRegistrationManage.setEquCategory(equType.get("equCategory"));
            jgUseRegistrationManage.setEquCategoryCode(equType.get("equCategoryCode"));
            jgUseRegistrationManage.setEquDefine(equType.get("equDefine"));
            jgUseRegistrationManage.setEquDefineCode(equType.get("equDefineCode"));
            jgUseRegistrationManage.setIsDelete(Boolean.FALSE);
            jgUseRegistrationManage.setRecUserId(useRegistration.getRecUserId());
            jgUseRegistrationManage.setRecUserName(useRegistration.getRecUserName());
            jgUseRegistrationManage.setRecDate(useRegistration.getRecDate());
            jgUseRegistrationManage.setCreateUserId(useRegistration.getCreateUserId());
            jgUseRegistrationManage.setCreateDate(useRegistration.getRecDate());
            jgUseRegistrationManage.setEquUseAddress(fullAddress);
            jgUseRegistrationManage.setManageType(useRegistration.getManageType());
            jgUseRegistrationManage.setUseUnitAddress(!ValidationUtil.isEmpty(enterpriseInfo) ? (String) enterpriseInfo.get("address") : "");
            jgUseRegistrationManage.setUseRegistrationCode(useRegistration.getUseRegistrationCode());
            jgUseRegistrationManage.setUseUnitCreditCode(useRegistration.getUseUnitCreditCode());
            jgUseRegistrationManage.setReceiveCompanyCode(useRegistration.getReceiveCompanyCode());
            jgUseRegistrationManage.setCertificateNo(commonServiceImpl.generateCertificateNo(equType, useRegistration.getAuditPassDate(), useRegistration.getReceiveCompanyCode()));
            this.baseMapper.insert(jgUseRegistrationManage);
        }


        // 车用气瓶使用登记表中已经审批通过的单子
        List<JgVehicleInformation> jgVehicleInformations = jgVehicleInformationMapper.selectList(new LambdaQueryWrapper<JgVehicleInformation>()
                .eq(JgVehicleInformation::getStatus, "已完成")
                .eq(JgVehicleInformation::getIsDelete, false));
        for (JgVehicleInformation vehicleInformation : jgVehicleInformations) {
            // 使用单位信息
            Map<String, Object> enterpriseInfo = commonServiceImpl.getEnterpriseInfo(vehicleInformation.getUseUnitCreditCode());
            // 设备种类/类别/品种
            Map<String, String> equType = jgUseRegistrationMapper.getEquTypeByVehSeq(String.valueOf(vehicleInformation.getSequenceNbr()));
            // 组装数据
            JgUseRegistrationManage jgUseRegistrationManage = new JgUseRegistrationManage();
            jgUseRegistrationManage.setUseUnitName(vehicleInformation.getUseUnitName());
            jgUseRegistrationManage.setApplyNo(vehicleInformation.getApplyNo());
            jgUseRegistrationManage.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
            jgUseRegistrationManage.setReceiveOrgName(vehicleInformation.getReceiveOrgName());
            jgUseRegistrationManage.setAuditPassDate(vehicleInformation.getAuditPassDate());
            jgUseRegistrationManage.setRegType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName());
            jgUseRegistrationManage.setRegDate(vehicleInformation.getRegDate());
            jgUseRegistrationManage.setEquList(equType.get("equList"));
            jgUseRegistrationManage.setEquListCode(equType.get("equListCode"));
            jgUseRegistrationManage.setEquCategory(equType.get("equCategory"));
            jgUseRegistrationManage.setEquCategoryCode(equType.get("equCategoryCode"));
            jgUseRegistrationManage.setEquDefine(equType.get("equDefine"));
            jgUseRegistrationManage.setEquDefineCode(equType.get("equDefineCode"));
            jgUseRegistrationManage.setIsDelete(Boolean.FALSE);
            jgUseRegistrationManage.setRecUserId(vehicleInformation.getRecUserId());
            jgUseRegistrationManage.setRecUserName(vehicleInformation.getRecUserName());
            jgUseRegistrationManage.setRecDate(vehicleInformation.getRecDate());
            jgUseRegistrationManage.setCreateUserId(vehicleInformation.getCreateUserId());
            jgUseRegistrationManage.setCreateDate(vehicleInformation.getRecDate());
            jgUseRegistrationManage.setEquUseAddress("");
            jgUseRegistrationManage.setManageType("unit");
            jgUseRegistrationManage.setCarNumber(vehicleInformation.getCarNumber());
            jgUseRegistrationManage.setUseUnitAddress(!ValidationUtil.isEmpty(enterpriseInfo) ? (String) enterpriseInfo.get("address") : "");
            jgUseRegistrationManage.setUseRegistrationCode(vehicleInformation.getUseRegistrationCode());
            jgUseRegistrationManage.setUseUnitCreditCode(vehicleInformation.getUseUnitCreditCode());
            jgUseRegistrationManage.setReceiveCompanyCode(vehicleInformation.getReceiveCompanyCode());
            jgUseRegistrationManage.setCertificateNo(commonServiceImpl.generateCertificateNo(equType, vehicleInformation.getAuditPassDate(), vehicleInformation.getReceiveCompanyCode()));
            this.baseMapper.insert(jgUseRegistrationManage);
        }
        return Boolean.TRUE;
    }


    /**
     * 分页查询
     */
    public Page<JgUseRegistrationManageDto> queryForJgUseRegistrationManagePage(Page<JgUseRegistrationManageDto> page,
                                                                                JgUseRegistrationManageDto dto,
                                                                                String sort) {
        SortVo sortMap = commonServiceImpl.sortFieldConversion(sort);
        if (ApplicationFormTypeEnum.BF.getBusinessCode().equals(dto.getApplyType()) && (!CylinderTypeEnum.CYLINDER.getCode().equals(dto.getEquCategoryCode()) || dto.getRegType().equals(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName()))){
            dto.setCertificateStatus(null);
            dto.setIsScrap("0");
        }
        return jgUseRegistrationManageMapper.queryForPage(page, dto, sortMap);

    }

    /**
     * 根据sequenceNbr查询---使用登记证详情用
     *
     * @param sequenceNbr 主键
     * @return
     */
    public JgUseRegistrationManage queryDetailBySeq(String sequenceNbr) {
        return this.baseMapper.selectById(sequenceNbr);
    }

    /**
     * 根据sequenceNbr查询使用登记证 操作流水---使用登记证详情用
     *
     * @param sequenceNbr 主键
     * @return
     */
    public List<Map<String, String>> operationRecord(String sequenceNbr) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        JgUseRegistrationManage jgUseRegistrationManage = this.baseMapper.selectById(sequenceNbr);
        List<JgCertificateChangeRecord> changeRecordList = jgCertificateChangeRecordService.list(new LambdaQueryWrapper<JgCertificateChangeRecord>()
                .eq(JgCertificateChangeRecord::getUseRegistrationCode, jgUseRegistrationManage.getUseRegistrationCode())
                .orderByDesc(JgCertificateChangeRecord::getCreateDate));
        return changeRecordList.stream()
                .map(x -> {
                    Map<String, String> map = new HashMap<>();
                    map.put("operatingTime", simpleDateFormat.format(x.getRecDate()));
                    map.put("content", x.getChangeContent());
                    map.put("routePath", x.getRoutePath());
                    return map;
                }).collect(Collectors.toList());
    }

    /**
     * 根据sequenceNbr查询使用登记证对应设备列表---使用登记证详情用
     * 分页接口
     *
     * @param sequenceNbr 主键
     * @return
     */
    public Page<JSONObject> certificateEquList(int current, int size, String sequenceNbr) {
        return queryEquForPageByCertificateSeqList("",Collections.singletonList(Long.parseLong(sequenceNbr)), current, size);
    }

    /**
     * 列表查询
     */
    public List<JgUseRegistrationManageDto> queryByUseUnitCreditCode(JgUseRegistrationManageDto dto) {
        return jgUseRegistrationManageMapper.queryByUseUnitCreditCode(dto);
    }

    /**
     * 根据证的sequenceNbr，查询证下面的所有设备
     */
    public List<JSONObject> queryEquByCertificateSeq(Long sequenceNbr) {
        return queryEquByCertificateSeqList(Collections.singletonList(sequenceNbr));
    }

    /**
     * 根据证的sequenceNbr集合，批量查询证下面的所有设备
     */
    public List<JSONObject> queryEquByCertificateSeqList(List<Long> sequenceNbrList) {
        List<JgUseRegistrationManage> jgUseRegistrationManageList = this.baseMapper.selectList(new LambdaQueryWrapper<JgUseRegistrationManage>()
                .in(JgUseRegistrationManage::getSequenceNbr, sequenceNbrList)
                .eq(JgUseRegistrationManage::getIsDelete, 0)
                .select(JgUseRegistrationManage::getUseRegistrationCode));
        if (ValidationUtil.isEmpty(jgUseRegistrationManageList)) {
            return new ArrayList<>();
        }
        List<JSONObject> result = new ArrayList<>();
        Set<String> useOrgCodes = jgUseRegistrationManageList.stream().map(JgUseRegistrationManage::getUseRegistrationCode).collect(Collectors.toSet());

        // es中通过查询【使用登记证编号】所有设备
        SearchRequest request = new SearchRequest("idx_biz_view_jg_all");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.trackTotalHits(true);

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("USE_ORG_CODE", useOrgCodes);
        boolQuery.must(termsQuery);
        builder.query(boolQuery);
        request.source(builder);

        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(hit);
                JSONObject dto2 = jsonObject.getJSONObject("sourceAsMap");
                result.add(dto2);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 根据证的sequenceNbr集合，批量查询证下面的所有设备
     *
     * @param enableType 启用停用业务使用 - 过滤设备状态 （1：在用 2：停用） 对应枚举：EquimentEnum
     * @param sequenceNbrList 证的sequenceNbr集合
     * @param current         分页-当前页
     * @param size            分页-分页数
     * @return 查询结果
     */
    public Page<JSONObject> queryEquForPageByCertificateSeqList(String enableType,List<Long> sequenceNbrList, int current, int size) {
        List<JgUseRegistrationManage> jgUseRegistrationManageList = this.baseMapper.selectList(new LambdaQueryWrapper<JgUseRegistrationManage>()
                .in(JgUseRegistrationManage::getSequenceNbr, sequenceNbrList)
                .eq(JgUseRegistrationManage::getIsDelete, 0));
        if (ValidationUtil.isEmpty(jgUseRegistrationManageList)) {
            return new Page<>();
        }

        List<JSONObject> list = new LinkedList<>();
        long totle = 0;

        Page<JSONObject> result = new Page<>(Optional.of(current).orElse(1), Optional.of(size).orElse(10));
        Set<String> useOrgCodes = jgUseRegistrationManageList.stream().map(JgUseRegistrationManage::getUseRegistrationCode).collect(Collectors.toSet());

        // es中通过查询【使用登记证编号】所有设备
        SearchRequest request = new SearchRequest("idx_biz_view_jg_all");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.trackTotalHits(true);

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("USE_ORG_CODE", useOrgCodes);
        boolQuery.must(termsQuery);

        // 设备状态 对应枚举EquimentEnum
        if (!ObjectUtils.isEmpty(enableType)) {
            BoolQueryBuilder elcBuilder = QueryBuilders.boolQuery();
            elcBuilder.must(QueryBuilders.matchPhraseQuery("EQU_STATE", QueryParser.escape(enableType)));
            boolQuery.must(elcBuilder);
        }

        builder.query(boolQuery);
        builder.from((current - 1) * size);
        builder.size(size);
        request.source(builder);

        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(hit);
                JSONObject dto = jsonObject.getJSONObject("sourceAsMap");
                dto.put("record", dto.get("SEQUENCE_NBR"));
                list.add(dto);
            }
            totle = Objects.requireNonNull(response.getInternalResponse().hits().getTotalHits()).value;
        } catch (Exception e) {
            e.printStackTrace();
        }
        result.setRecords(list);
        result.setTotal(totle);
        return result;
    }

    /**
     * 标志/使用登记证/汇总表 打印
     *
     * @param response       响应
     * @param printType      打印类型
     * @param certificateSeq 使用登记证的seq
     */
    public void printCertificate(HttpServletResponse response, String printType, String certificateSeq) {

        if (StringUtils.isEmpty(printType) || StringUtils.isEmpty(certificateSeq)) {
            throw new BadRequest("打印失败，请联系管理员！");
        }

        JgUseRegistrationManage manage = this.baseMapper.selectById(certificateSeq);
        String regType = manage.getRegType();
        String useRegistrationCode = manage.getUseRegistrationCode();
        String sequenceNbr = null;
        String equCategoryCode = manage.getEquCategoryCode();

        switch (printType) {
            case "certificateNormalPrint":// 使用登记证 普打
            case "certificateNestedPrint":// 使用登记证 套打
            case "useFlagNormalPrint":// 使用标志 普打
            case "useFlagNestedPrint":// 使用标志 套打
                if (BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName().equals(regType)) {
                    JgVehicleInformation vehicleInformation = jgVehicleInformationService.getOne(
                            new LambdaQueryWrapper<JgVehicleInformation>()
                                    .eq(JgVehicleInformation::getUseRegistrationCode, useRegistrationCode));
                    sequenceNbr = String.valueOf(vehicleInformation.getSequenceNbr());
                    jgVehicleInformationService.exportVehicleUseRegistrationCertificate(sequenceNbr, response, getPrintTypeCode(printType));
                } else if (BusinessTypeEnum.JG_USAGE_REGISTRATION.getName().equals(regType)) {
                    jgUseRegistrationService.list(
                                    new LambdaQueryWrapper<JgUseRegistration>()
                                            .eq(JgUseRegistration::getUseRegistrationCode, useRegistrationCode)
                            ).stream()
                            .max(Comparator.comparing(JgUseRegistration::getRecDate))
                            .ifPresent(useRegistration -> jgUseRegistrationService.exportUseRegistrationCertificate(String.valueOf(useRegistration.getSequenceNbr()), response, getPrintTypeCode(printType)));
                }
                break;
            case "exportSummaryTable":// 工业管道和气瓶 汇总表下载
                List<JgUseRegistration> jgUseRegistrations = jgUseRegistrationService.getBaseMapper().selectList(new LambdaQueryWrapper<JgUseRegistration>()
                        .eq(JgUseRegistration::getUseRegistrationCode, useRegistrationCode));
                List<Long> useRegistrationSeqs = jgUseRegistrations.stream().map(JgUseRegistration::getSequenceNbr).collect(Collectors.toList());
                jgUseRegistrationService.exportSummaryBasicInfo(useRegistrationSeqs, response, equCategoryCode);
                break;
            default:
                break;
        }
    }

    private String getPrintTypeCode(String printType) {
        switch (printType) {
            case "certificateNormalPrint":
                return "0";
            case "certificateNestedPrint":
                return "1";
            case "useFlagNormalPrint":
                return "2";
            case "useFlagNestedPrint":
                return "3";
            default:
                return "";
        }
    }

}