package com.zt.plat.module.erp.controller.admin.erp.vo;

import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialRespDTO;
import com.zt.plat.module.base.api.materialinfomation.dto.MaterialInfomationRespDTO;
import lombok.Getter;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 物料扩展属性安全取值工具类（适配所有属性编码）
 */
public class MaterialAttributeUtils {

    /**
     * 物料属性编码枚举（统一管理所有属性code）
     * 关联属性编码、名称、数据类型
     */
    @Getter
    public enum MaterialAttrCode {
        MTRL_BASE_UNIT_CODE("mtrlBaseUnitCode", "基本计量单位编码", DataType.STRING),
        MTRL_BASE_UNIT_NAME("mtrlBaseUnitName", "基本计量单位描述", DataType.STRING),
        MTRL_SHORT_DESC("mtrlShortDesc", "短描述", DataType.STRING),
        MTRL_LONG_DESC("mtrlLongDesc", "长描述", DataType.STRING),
        MTRL_CHALCO_CODE("mtrlChalcoCode", "中铝编码", DataType.STRING),
        MTRL_ZHONGTONG_CODE("mtrlZhongtongCode", "中铜编码", DataType.STRING),
        MTRL_SPECIFICATION("mtrlSpecification", "规格", DataType.STRING),
        MTRL_TEXTURE("mtrlTexture", "材质", DataType.STRING),
        MTRL_RECORD_TIME("mtrlRecordTime", "记录时间", DataType.DATETIME),
        MTRL_DRAWING_NUMBER("mtrlDrawingNumber", "图号", DataType.STRING),
        MTRL_ORDER_NUMBER("mtrlOrderNumber", "订货号", DataType.STRING),
        MTRL_OTHER_PARAMETERS("mtrlOtherParameters", "其它参数", DataType.STRING),
        MTRL_EQUIPMENT_CATEGORY("mtrlEquipmentCategory", "设备类别", DataType.STRING),
        MTRL_MANUFACTURER("mtrlManufacturer", "主机生产商", DataType.STRING),
        MTRL_SOURCE("mtrlSource", "来源", DataType.STRING),
        MTRL_MODEL("mtrlModel", "型号", DataType.STRING),
        MTRL_ELEMENT("mtrlElement", "金属元素", DataType.TEXT),
        MTRL_DECIMAL("mtrlDecimal", "小数位数", DataType.NUMBER);

        private final String code;
        private final String name;
        private final DataType dataType;

        MaterialAttrCode(String code, String name, DataType dataType) {
            this.code = code;
            this.name = name;
            this.dataType = dataType;
        }

        // 根据code获取枚举（容错）
        public static MaterialAttrCode getByCode(String code) {
            if (code == null || code.isEmpty()) {
                return null;
            }
            for (MaterialAttrCode attrCode : values()) {
                if (attrCode.code.equals(code)) {
                    return attrCode;
                }
            }
            return null;
        }

        // 获取所有属性编码列表
        public static List<String> getAllCodes() {
            return Arrays.stream(values())
                    .map(MaterialAttrCode::getCode)
                    .collect(Collectors.toList());
        }
    }

    /**
     * 数据类型枚举
     */
    public enum DataType {
        STRING, NUMBER, TEXT, DATETIME
    }

    /**
     * 物料属性封装Record
     * 包含所有属性的安全取值
     */
    public record MaterialAttribute(
            // 基础属性
            String mtrlBaseUnitCode,
            String mtrlBaseUnitName,
            String mtrlShortDesc,
            String mtrlLongDesc,
            String mtrlChalcoCode,
            String mtrlZhongtongCode,
            String mtrlSpecification,
            String mtrlTexture,
            LocalDateTime mtrlRecordTime,
            // 扩展属性
            String mtrlDrawingNumber,
            String mtrlOrderNumber,
            String mtrlOtherParameters,
            String mtrlEquipmentCategory,
            String mtrlManufacturer,
            String mtrlSource,
            String mtrlModel,
            String mtrlElement,
            Integer mtrlDecimal // 小数位数（数字类型）
    ) {
        // 空值默认构造器（避免NPE）
        public static MaterialAttribute empty() {
            return new MaterialAttribute(
                    null, null, null, null, null, null, null, null, null,
                    null, null, null, null, null, null, null, null, null
            );
        }
    }

    /**
     * 从DTO中安全提取所有物料属性
     * @param dto 物料信息DTO
     * @return 封装后的物料属性Record
     */
    public static MaterialAttribute safeExtractAllAttributes(DepartmentMaterialRespDTO dto) {
        // 1. 空值校验
        if (dto == null || dto.getFlatAttributes() == null) {
            return MaterialAttribute.empty();
        }

        Map<String, Object> attrs = dto.getFlatAttributes();

        // 2. 按数据类型安全取值
        return new MaterialAttribute(
                getTypedValue(attrs, MaterialAttrCode.MTRL_BASE_UNIT_CODE),
                getTypedValue(attrs, MaterialAttrCode.MTRL_BASE_UNIT_NAME),
                getTypedValue(attrs, MaterialAttrCode.MTRL_SHORT_DESC),
                getTypedValue(attrs, MaterialAttrCode.MTRL_LONG_DESC),
                getTypedValue(attrs, MaterialAttrCode.MTRL_CHALCO_CODE),
                getTypedValue(attrs, MaterialAttrCode.MTRL_ZHONGTONG_CODE),
                getTypedValue(attrs, MaterialAttrCode.MTRL_SPECIFICATION),
                getTypedValue(attrs, MaterialAttrCode.MTRL_TEXTURE),
                getTypedValue(attrs, MaterialAttrCode.MTRL_RECORD_TIME),
                getTypedValue(attrs, MaterialAttrCode.MTRL_DRAWING_NUMBER),
                getTypedValue(attrs, MaterialAttrCode.MTRL_ORDER_NUMBER),
                getTypedValue(attrs, MaterialAttrCode.MTRL_OTHER_PARAMETERS),
                getTypedValue(attrs, MaterialAttrCode.MTRL_EQUIPMENT_CATEGORY),
                getTypedValue(attrs, MaterialAttrCode.MTRL_MANUFACTURER),
                getTypedValue(attrs, MaterialAttrCode.MTRL_SOURCE),
                getTypedValue(attrs, MaterialAttrCode.MTRL_MODEL),
                getTypedValue(attrs, MaterialAttrCode.MTRL_ELEMENT),
                getTypedValue(attrs, MaterialAttrCode.MTRL_DECIMAL)
        );
    }

    /**
     * 通用类型安全取值方法
     * @param attrs 属性Map
     * @param attrCode 属性编码枚举
     * @return 对应类型的值（空/类型不匹配返回null）
     */
    @SuppressWarnings("unchecked")
    private static <T> T getTypedValue(Map<String, Object> attrs, MaterialAttrCode attrCode) {
        if (attrCode == null) {
            return null;
        }

        Object value = attrs.get(attrCode.getCode());
        if (value == null || value.toString().trim().isEmpty()) {
            return null;
        }

        String strValue = value.toString().trim();
        try {
            // 根据数据类型转换
            return switch (attrCode.getDataType()) {
                case STRING, TEXT -> (T) strValue;
                case NUMBER -> (T) Integer.valueOf(strValue);
                case DATETIME -> (T) LocalDateTime.parse(strValue);
            };
        } catch (NumberFormatException | DateTimeParseException | ClassCastException e) {
            // 类型转换失败返回null，可添加日志
            return null;
        }
    }

    /**
     * 单独获取某个属性值（按需取值）
     * @param dto 物料DTO
     * @param attrCode 属性编码枚举
     * @return 对应类型的值
     */
    public static <T> T getSingleAttribute(MaterialInfomationRespDTO dto, MaterialAttrCode attrCode) {
        if (dto == null || dto.getFlatAttributes() == null || attrCode == null) {
            return null;
        }
        return getTypedValue(dto.getFlatAttributes(), attrCode);
    }

    /**
     * 获取flatAttributes中存在的所有属性编码（过滤空值）
     * @param dto 物料DTO
     * @return 非空属性编码列表
     */
    public static List<String> getExistAttributeCodes(MaterialInfomationRespDTO dto) {
        if (dto == null || dto.getFlatAttributes() == null) {
            return Collections.emptyList();
        }

        return dto.getFlatAttributes().entrySet().stream()
                .filter(entry -> entry.getValue() != null && !entry.getValue().toString().trim().isEmpty())
                .map(Map.Entry::getKey)
                .filter(key -> MaterialAttrCode.getByCode(key) != null) // 只保留枚举中定义的编码
                .collect(Collectors.toList());
    }
}