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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.biz.common.dto.JgUseRegistrationManageDto;
import com.yeejoin.amos.boot.biz.common.utils.QRCodeUtil;
import com.yeejoin.amos.boot.module.app.api.annotation.Converter;
import com.yeejoin.amos.boot.module.app.api.annotation.FieldDisplayDefine;
import com.yeejoin.amos.boot.module.app.api.dto.CylinderInfoForWX;
import com.yeejoin.amos.boot.module.app.api.dto.VehicleInfoForWX;
import com.yeejoin.amos.boot.module.app.api.mapper.AppCommonMapper;
import com.yeejoin.amos.boot.module.app.biz.strategy.ISearchDetailHandler;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;

@Component
public class VehicleSearchDetailDetailHandlerImpl implements ISearchDetailHandler {


    private final AppCommonMapper appCommonMapper;

    public VehicleSearchDetailDetailHandlerImpl(AppCommonMapper appCommonMapper) {
        this.appCommonMapper = appCommonMapper;
    }

    @Override
    public String manageType() {
        return "vehicle";
    }

    @Override
    public Map<String, Object> handler(JgUseRegistrationManageDto manageDto, String certType) {
        return this.getQueryCarCylinderInfo(manageDto, certType);
    }

    private Map<String, Object> getQueryCarCylinderInfo(JgUseRegistrationManageDto manageDto, String certType) {
        VehicleInfoForWX baseInfo = appCommonMapper.queryVehicleBaseInfo(manageDto.getSequenceNbr());
        // 最好改成查询es record再传入进去
        List<CylinderInfoForWX> cylinderInfos = appCommonMapper.queryCylinderIfoOfVehicle(manageDto.getApplyNo());
        fillEquDefine(baseInfo, cylinderInfos);
        Map<String, Object> result = new LinkedHashMap<>();
        JSONArray tabs = new JSONArray();
        buildFixFields(baseInfo, result);
        buildOneItemTypeMap( baseInfo, tabs);
        buildManyItemTypeTab(cylinderInfos, tabs);
        result.put("tab", tabs);
        result.put("certNo", manageDto.getCertificateNo());
        result.put("certType", certType);
        result.put("version", manageDto.getVersion());
        return result;
    }

    private void fillEquDefine(VehicleInfoForWX baseInfo, List<CylinderInfoForWX> cylinderInfos) {
        cylinderInfos.forEach(c-> c.setEquDefine(baseInfo.getEquDefine()));
    }

    private void buildFixFields(VehicleInfoForWX baseInfo, Map<String, Object> result) {
        result.put("useUnitName", baseInfo.getUseUnitName());
        result.put("equList", baseInfo.getEquList());
        result.put("useRegistrationCode", baseInfo.getUseRegistrationCode());
        result.put("status", baseInfo.getCertificateStatus());
        // 控制颜色 扩展证状态使用
        result.put("color", "#00FF00");
    }

    private void buildManyItemTypeTab(List<CylinderInfoForWX> cylinderInfos, JSONArray tabs) {
        JSONObject tab = new JSONObject();
        tab.put("title", "气瓶信息");
        tab.put("tabKey", "cylinderInfo");
        tab.put("tabValue", this.buildFieldsWithGroup(cylinderInfos));
        tabs.add(tab);
    }

    private void buildOneItemTypeMap(VehicleInfoForWX baseInfo, JSONArray tabs) {
        JSONObject tab = new JSONObject();
        tab.put("title", "基本信息");
        tab.put("tabKey", "baseInfo");
        tab.put("tabValue", this.buildFieldsOneGroup(baseInfo));
        tabs.add(tab);
    }

    private JSONArray buildFieldsOneGroup(VehicleInfoForWX baseInfo) {
        JSONArray groupArray = new JSONArray();
        JSONObject group = new JSONObject();
        JSONArray fieldArray = new JSONArray();
        Field[] fields = baseInfo.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            FieldDisplayDefine displayDefine = field.getAnnotation(FieldDisplayDefine.class);
            try {
                if (displayDefine != null && displayDefine.isExist()) {
                    String fieldName = displayDefine.value();
                    JSONObject json = new JSONObject();
                    json.put("fieldName", fieldName);
                    json.put("fieldKey", StringUtils.isNotBlank(displayDefine.alias()) ? displayDefine.alias() : field.getName());
                    json.put("fieldValue", field.get(baseInfo));
                    fieldArray.add(json);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        group.put("groupKey", "baseInfo");
        group.put("groupName", "");
        group.put("groupValue", fieldArray);
        groupArray.add(group);
        return groupArray;
    }

    private Object buildFieldsWithGroup(List<CylinderInfoForWX> cylinderInfos) {
        JSONArray groupArray = new JSONArray();
        for(CylinderInfoForWX cylinderInfo: cylinderInfos){
            JSONObject group = new JSONObject();
            JSONArray fieldArray = new JSONArray();
            Field[] fields = cylinderInfo.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                FieldDisplayDefine displayDefine = field.getAnnotation(FieldDisplayDefine.class);
                try {
                    if (displayDefine != null && displayDefine.isExist()) {
                        String fieldName = displayDefine.value();
                        JSONObject json = new JSONObject();
                        json.put("fieldName", fieldName);
                        json.put("fieldKey", StringUtils.isNotBlank(displayDefine.alias()) ? displayDefine.alias() : field.getName());
                        Converter<String> converter = displayDefine.converter().newInstance();
                        if(field.get(cylinderInfo) != null){
                            json.put("fieldValue", converter.convertToLabelData((String)field.get(cylinderInfo)));
                        } else {
                            json.put("fieldValue", "");
                        }
                        fieldArray.add(json);
                    }
                } catch (IllegalAccessException | InstantiationException e) {
                    throw new RuntimeException(e);
                }
            }
            group.put("groupKey", cylinderInfo.getEquCode());
            group.put("groupName", String.format("气瓶(%s)", cylinderInfo.getFactoryNum()));
            group.put("groupValue", fieldArray);
            groupArray.add(group);
        }
        return groupArray;
    }

    private JSONObject getQRCode(String code) {
        JSONObject jsonObject = new JSONObject();
        byte[] bytes = QRCodeUtil.generateQRCodeImageByteData(code, 50);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        try {
            MultipartFile file = new MockMultipartFile(code + ".jpg", code + ".jpg", ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
            FeignClientResult<Map<String, String>> date = Systemctl.fileStorageClient.updateCommonFileFree(file, "ugp/qrcode");
            if (date != null) {
                Map<String, String> map = date.getResult();
                Iterator<String> it = map.keySet().iterator();
                String urlString = it.next();
                jsonObject.put("fileUrl", urlString);
                jsonObject.put("fileName", code);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

}
