package com.yeejoin.amos.boot.module.common.api.entity;

import com.yeejoin.amos.boot.biz.common.annotation.TechnicalParameter;
import com.yeejoin.amos.boot.module.common.api.dto.TechParamItem;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 设备
 */
@Data
@Accessors(chain = true)
@Slf4j
@Document(indexName = "idx_biz_equipment_info", shards = 3, replicas = 2, createIndex = false)
public class ESEquipmentInfo {

    @Id
    private String SEQUENCE_NBR;

    /**
     * 管辖机构名称
     */
    @Field(type = FieldType.Keyword)
    private String ORG_BRANCH_NAME;

    /**
     * 管辖机构org_code
     */
    @Field(type = FieldType.Keyword)
    private String ORG_BRANCH_CODE;

    /**
     * 使用单位名称
     */
    @Field(type = FieldType.Keyword)
    private String USE_UNIT_NAME;

    /**
     * 使用单位统一信用代码
     */
    @Field(type = FieldType.Keyword)
    private String USE_UNIT_CREDIT_CODE;

    /**
     * 设备种类编码
     */
    @Field(type = FieldType.Keyword)
    private String EQU_LIST_CODE;

    /**
     * 设备种类名称
     */
    @Field(type = FieldType.Text)
    private String EQU_LIST;

    /**
     * 设备类别编码
     */
    @Field(type = FieldType.Keyword)
    private String EQU_CATEGORY_CODE;

    /**
     * 设备类别名称
     */
    @Field(type = FieldType.Text)
    private String EQU_CATEGORY;

    /**
     * 设备品种编码
     */
    @Field(type = FieldType.Keyword)
    private String EQU_DEFINE_CODE;

    /**
     * 设备品种名称
     */
    @Field(type = FieldType.Text)
    private String EQU_DEFINE;

    /**
     * 使用登记证编号
     */
    @Field(type = FieldType.Keyword)
    private String USE_ORG_CODE;

    /**
     * 使用登记证-发证日期
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate issueDate;

    /**
     * 96333电梯码
     */
    @Field(type = FieldType.Keyword)
    private String CODE96333;

    /**
     * 设备代码
     */
    @Field(type = FieldType.Keyword)
    private String EQU_CODE;

    /**
     * 监管码
     */
    @Field(type = FieldType.Keyword)
    private String SUPERVISORY_CODE;

    /**
     * 使用场所
     */
    @Field(type = FieldType.Keyword)
    private String USE_PLACE;

    /**
     * 详细地址
     */
    @Field(type = FieldType.Text)
    private String ADDRESS;

    /**
     * 设备状态:在用、停用、报废
     */
    @Field(type = FieldType.Integer)
    private Integer EQU_STATE;

    /**
     * 认领状态
     */
    @Field(type = FieldType.Keyword)
    private String STATUS;

    /**
     * 更新日期
     */
    @Field(type = FieldType.Long)
    private Long REC_DATE;

    /**
     * 安全管理员
     */
    @Field(type = FieldType.Text)
    private String SAFETY_MANAGER;

    /**
     * 安全管理员电话
     */
    @Field(type = FieldType.Keyword)
    private String PHONE;


    /**
     * 维保单位统一信用代码
     */
    @Field(type = FieldType.Keyword)
    private String MAINTAIN_UNIT;

    /**
     * 维保单位名称
     */
    @Field(type = FieldType.Keyword)
    private String MAINTAIN_UNIT_NAME;

    /**
     * 单位内部编号
     */
    @Field(type = FieldType.Keyword)
    private String USE_INNER_CODE;

    /**
     * 出场编号
     */
    @Field(type = FieldType.Keyword)
    private String FACTORY_NUM;

    /**
     * 制造单位名称
     */
    @Field(type = FieldType.Keyword)
    private String PRODUCE_UNIT_NAME;

    /**
     * 安改维单位统一信用代码
     */
    @Field(type = FieldType.Keyword)
    private String USC_UNIT_CREDIT_CODE;

    /**
     * 安改维单位统名称
     */
    @Field(type = FieldType.Text)
    private String USC_UNIT_NAME;

    /**
     * 安装日期
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate USC_DATE;

    /**
     * 投用日期
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate USE_DATE;

    /**
     * 创建日期
     */
    @Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
    private LocalDateTime createDate;


    /**
     * 产品名称
     */
    @Field(type = FieldType.Keyword)
    private String PRODUCT_NAME;

    /**
     * 设备品牌
     */
    @Field(type = FieldType.Text)
    private String BRAND_NAME;

    /**
     * 设备型号
     */
    @Field(type = FieldType.Text)
    private String EQU_TYPE;

    /**
     * 制造日期
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate PRODUCE_DATE;

    /**
     * 设备来源
     */
    @Field(type = FieldType.Keyword)
    private String DATA_SOURCE;

    /**
     * 是否车用气瓶
     */
    @Field(type = FieldType.Keyword)
    private String WHETHER_VEHICLE_CYLINDER;

    /**
     * 是否撬装式压力容器
     */
    @Field(type = FieldType.Keyword)
    private String WHETHER_SKID_MOUNTED_PRESSURE_VESSEL;

    /**
     * 气瓶分类
     */
    @Field(type = FieldType.Keyword)
    private String CYLINDER_CATEGORY;


    /**
     * 是否纳管：true - 已纳管 false-未纳管
     */
    @Field(type = FieldType.Boolean)
    private Boolean IS_INTO_MANAGEMENT;
    /**
     * 设备使用地点区域码610000#610100#610101#61010101d 到街道
     */
    @Field(type = FieldType.Keyword)
    private String USE_PLACE_CODE;

    /**
     * 设备使用场所代码-来源数据字典ADDRESS
     */
    @Field(type = FieldType.Keyword)
    private String USE_SITE_CODE;

    /**
     * 工程装置（工业管道使用）
     */
    @Field(type = FieldType.Keyword)
    private String PROJECT_CONTRAPTION;

    /**
     * 信息化
     */
    @Field(type = FieldType.Text)
    private String INFORMATION_SITUATION;

    /**
     * 工程装置id（工业管道使用）
     */
    @Field(type = FieldType.Keyword, name = "PROJECT_CONTRAPTION_ID")
    private String projectContraptionId;


    /**
     * 是否可以做业务-西安电梯导入用（false-否，true-是）
     */
    @Field(type = FieldType.Boolean, name = "IS_DO_BUSINESS")
    private Boolean IS_DO_BUSINESS;

    /**
     * 数据质量等级
     */
    @Field(type = FieldType.Integer, name = "DATA_QUALITY_SCORE")
    private Integer dataQualityScore;

    /**
     * 设计单位统一信用代码
     */
    @Field(type = FieldType.Keyword)
    private String designUnitCreditCode;

    /**
     * 设计单位名称
     */
    @Field(type = FieldType.Text)
    private String designUnitName;

    /**
     * 制造单位统一社会信用代码
     */
    @Field(type = FieldType.Keyword)
    private String produceUnitCreditCode;

    /**
     * 设计日期
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate designDate;


    /**
     * 车牌号
     */
    @Field(type = FieldType.Keyword)
    private String carNumber;

    /**
     * 下次检验日期-冗余字段
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate NEXT_INSPECT_DATE;

    /**
     * 检验日期-冗余字段
     */
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDate INSPECT_DATE;

    /**
     * 设备总价值（万元）
     */
    @Field(type = FieldType.Keyword)
    private String equPrice;

    /**
     * 单位类型-多个逗号分隔开-实时的单位类型
     */
    @Field(type = FieldType.Keyword)
    private String unitType;

    /**
     * 是否球罐
     * 1：是
     * 0：不是
     */
    @Field(type = FieldType.Keyword)
    private String whetherSphericalTank;

    /**
     * 最新一条检验信息
     */
    @Field(type = FieldType.Nested)
    private List<Inspection> inspections;

    /**
     * 最新一条维保信息
     */
    @Field(type = FieldType.Nested)
    private List<Maintenance> maintenances;

    /**
     * 压力管道长度
     */
    @Field(type = FieldType.Double)
    private Double pipeLength;

    /**
     * 技术参数
     */
    @Field(type = FieldType.Nested)
    private List<TechParam> techParams;

    @Data
    public static class TechParam {

        @Field(type = FieldType.Keyword)
        private String paramKey;

        @Field(type = FieldType.Text)
        private String paramLabel;

        @Field(type = FieldType.Keyword)
        private String strValue;

        @Field(type = FieldType.Long)
        private Long longValue;

        @Field(type = FieldType.Double)
        private Double doubleValue;

        @Field(type = FieldType.Boolean)
        private Boolean boolValue;

        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDate dateValue;

        public TechParam() {
        }

        public TechParam(TechParamItem paramItem, Object rawValue) {
            this.paramKey = paramItem.getParamKey();
            this.paramLabel = paramItem.getParamLabel();
            setValueByType(paramItem.getParamType(), rawValue, paramItem.getMaxPrecision());
        }


        private void setValueByType(TechnicalParameter.ParamType type, Object value, Integer precision) {
            // 清空所有字段确保无污染
            resetFields();
            if (value == null) return;
            try {
                switch (type) {
                    case STRING:
                        this.strValue = value.toString();
                        break;
                    case INTEGER:
                        this.longValue = ((Number) value).longValue();
                        break;
                    case FLOAT:
                        this.doubleValue = roundDouble(((Number) value).doubleValue(),
                                precision != null ? precision : 6);
                        break;
                    case BIG_DECIMAL:
                        BigDecimal bd = (BigDecimal) value;
                        if (precision != null && bd.scale() > precision) {
                            this.strValue = bd.setScale(precision, RoundingMode.HALF_UP)
                                    .stripTrailingZeros().toPlainString();
                        } else {
                            this.doubleValue = bd.doubleValue();
                        }
                        break;
                    case BOOLEAN:
                        this.boolValue = Boolean.parseBoolean(value.toString());
                        break;
                }
            } catch (Exception e) {
                log.error("CONV_ERROR", e);
            }
        }

        private double roundDouble(double value, Integer precision) {
            // 参数校验
            if (Double.isNaN(value) || Double.isInfinite(value)) {
                return value; // 保留特殊值原样返回
            }
            // 默认精度处理
            int scale = (precision != null) ?
                    Math.min(precision, 16) : 6; // 最大支持16位小数

            // 银行家舍入法（HALF_EVEN）减少统计误差
            BigDecimal bd = BigDecimal.valueOf(value); // 注意：必须用valueOf避免精度丢失
            bd = bd.setScale(scale, RoundingMode.HALF_UP);

            // 处理科学计数法（避免1.23E-4这样的输出）
            return bd.stripTrailingZeros().doubleValue();
        }

        private void resetFields() {
            this.strValue = null;
            this.longValue = null;
            this.doubleValue = null;
            this.boolValue = null;
            this.dateValue = null;
        }
    }


    @Data
    public static class Inspection {
        @Field(type = FieldType.Keyword)
        private String sequenceNbr;

        /**
         * 检验类型
         */
        @Field(type = FieldType.Keyword)
        private String inspectType;

        /**
         * 检验机构名称
         */
        @Field(type = FieldType.Text)
        private String inspectOrgName;

        /**
         * 检验人员
         */
        @Field(type = FieldType.Text)
        private String inspectStaff;


        /**
         * 检验结论
         */
        @Field(type = FieldType.Keyword)
        private String inspectConclusion;

        /**
         * 检验日期
         */
        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDate inspectDate;

        /**
         * 下次检验日期
         */
        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDate nextInspectDate;

        /**
         * 检验机构编码
         */
        @Field(type = FieldType.Keyword)
        private String inspectOrgCode;

        /**
         * 报告编号
         */
        @Field(type = FieldType.Keyword)
        private String inspectReportNo;
    }

    @Data
    public static class Maintenance {

        @Field(type = FieldType.Keyword)
        private String sequenceNbr;

        /**
         * 维保单位统一社会信用代码
         */

        @Field(type = FieldType.Keyword)
        private String meUnitCreditCode;
        /**
         * 维保单位名称
         */

        @Field(type = FieldType.Text)
        private String meUnitName;
        /**
         * 维保备案合同
         */
        @Field(type = FieldType.Text)
        private String repairInform;
        /**
         * 维保合同开始日期
         */
        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDate informStart;
        /**
         * 维保合同结束日期
         */
        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDate informEnd;
        /**
         * 维保负责1人姓名
         */
        @Field(type = FieldType.Text)
        private String meMaster;
        /**
         * 维保负责人1身份证
         */

        @Field(type = FieldType.Keyword)
        private String meMasterId;

        /**
         * 维保负责人1电话
         */

        @Field(type = FieldType.Keyword)
        private String meMasterPhone;

        /**
         * 紧急救援电话
         */

        @Field(type = FieldType.Keyword)
        private String emergencyCall;

        /**
         * 维保周期
         */
        @Field(type = FieldType.Keyword)
        private String meCycle;
        /**
         * 大修周期
         */

        @Field(type = FieldType.Text)
        private String overhaulCycle;
        /**
         * 24小时维保电话
         */
        @Field(type = FieldType.Text)
        private String me24Telephone;

        /**
         * 维保负责人2姓名
         */
        @Field(type = FieldType.Text)
        private String meMaster1;
        /**
         * 维保负责人2身份证
         */

        @Field(type = FieldType.Keyword)
        private String meMaster1Id;

        /**
         * 维保负责人2电话
         */

        @Field(type = FieldType.Keyword)
        private String meMaster1Phone;
    }
}
