package com.seer.teach.mall.util;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.seer.teach.mall.entity.GoodsEntity;
import com.seer.teach.mall.entity.GoodsSpecificationEntity;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@Slf4j
public class GoodChangeUtils {

    /**
     * 构建商品变更日志JSON
     */
    public static JSONObject buildGoodChangeLogJson(GoodsEntity oldGoods, GoodsEntity newGoods) {
        JSONObject changes = new JSONObject();

        compareObjectsByReflection(oldGoods, newGoods, changes, "id", "addTime", "salesCount", "virtualSellVolume", "browseCount", "collectCount");

        return changes;
    }

    /**
     * 构建规格变更日志JSON
     */
    public static JSONObject buildSpecificationChangeLogJson(List<GoodsSpecificationEntity> oldSpecs,
                                                              List<GoodsSpecificationEntity> newSpecs) {
        JSONObject specChanges = new JSONObject();

        // 如果旧规格为空且新规格不为空，则表示新增规格
        if (CollectionUtil.isEmpty(oldSpecs) && CollectionUtil.isNotEmpty(newSpecs)) {
            specChanges.put("action", "add_all");
            specChanges.put("count", newSpecs.size());
            specChanges.put("specifications", convertSpecsToJson(newSpecs));
            return specChanges;
        }

        // 如果旧规格不为空且新规格为空，则表示删除规格
        if (CollectionUtil.isNotEmpty(oldSpecs) && CollectionUtil.isEmpty(newSpecs)) {
            specChanges.put("action", "delete_all");
            specChanges.put("count", oldSpecs.size());
            specChanges.put("specifications", convertSpecsToJson(oldSpecs));
            return specChanges;
        }

        // 找出新增、删除和更新的规格
        List<JSONObject> addedSpecs = new ArrayList<>();
        List<JSONObject> deletedSpecs = new ArrayList<>();
        List<JSONObject> updatedSpecs = new ArrayList<>();

        // 找出删除的规格（在旧规格中但不在新规格中）
        for (GoodsSpecificationEntity oldSpec : oldSpecs) {
            boolean found = false;
            for (GoodsSpecificationEntity newSpec : newSpecs) {
                if (isSameSpecification(oldSpec, newSpec)) {
                    found = true;

                    // 检查是否有字段更新
                    JSONObject specChangesDetail = compareSpecificationDetails(oldSpec, newSpec);
                    if (specChangesDetail.size() > 0) {
                        JSONObject updatedSpec = new JSONObject();
                        updatedSpec.put("old", convertSpecToJson(oldSpec));
                        updatedSpec.put("new", convertSpecToJson(newSpec));
                        updatedSpec.put("changes", specChangesDetail);
                        updatedSpecs.add(updatedSpec);
                    }
                    break;
                }
            }
            if (!found) {
                deletedSpecs.add(convertSpecToJson(oldSpec));
            }
        }

        // 找出新增的规格（在新规格中但不在旧规格中）
        for (GoodsSpecificationEntity newSpec : newSpecs) {
            boolean found = false;
            for (GoodsSpecificationEntity oldSpec : oldSpecs) {
                if (isSameSpecification(oldSpec, newSpec)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                addedSpecs.add(convertSpecToJson(newSpec));
            }
        }

        if (!addedSpecs.isEmpty()) {
            specChanges.put("added", addedSpecs);
        }
        if (!deletedSpecs.isEmpty()) {
            specChanges.put("deleted", deletedSpecs);
        }
        if (!updatedSpecs.isEmpty()) {
            specChanges.put("updated", updatedSpecs);
        }

        if (specChanges.isEmpty()) {
            specChanges.put("action", "no_changes");
        }

        return specChanges;
    }

    /**
     * 使用反射比较两个对象的字段值
     * @param oldObj 旧对象
     * @param newObj 新对象
     * @param changes 存储变更的JSON对象
     * @param excludeFields 要排除的字段名
     */
    private static void compareObjectsByReflection(Object oldObj, Object newObj, JSONObject changes, String... excludeFields) {
        if (oldObj == null || newObj == null) {
            return;
        }

        Set<String> excludeSet = new HashSet<>(Arrays.asList(excludeFields));
        // 获取所有字段
        Field[] fields = oldObj.getClass().getDeclaredFields();
        for (Field field : fields) {
            try {
                String fieldName = field.getName();

                // 跳过排除的字段
                if (excludeSet.contains(fieldName)) {
                    continue;
                }

                // 设置可访问
                field.setAccessible(true);

                // 获取字段值
                Object oldValue = field.get(oldObj);
                Object newValue = field.get(newObj);
                if(Objects.isNull(newValue)){
                    continue;
                }
                // 比较值是否相同
                if (!Objects.equals(oldValue, newValue)) {
                    changes.put(fieldName, createChangeJson(oldValue, newValue));
                }
            } catch (IllegalAccessException e) {
                log.warn("Failed to access field: {}", field.getName(), e);
            }
        }
    }

    /**
     * 比较规格详情变化
     */
    private static JSONObject compareSpecificationDetails(GoodsSpecificationEntity oldSpec, GoodsSpecificationEntity newSpec) {
        JSONObject changes = new JSONObject();

        // 使用反射比较规格字段
        compareObjectsByReflection(oldSpec, newSpec, changes,
                "id", "goodsId", "attributes", "spuName");

        // 比较属性变化
        if (!Objects.equals(oldSpec.getAttributes(), newSpec.getAttributes())) {
            changes.put("attributes", compareAttributes(oldSpec.getAttributes(), newSpec.getAttributes()));
        }

        return changes;
    }

    /**
     * 判断两个规格是否相同（通过属性组合判断）
     */
    private static boolean isSameSpecification(GoodsSpecificationEntity spec1, GoodsSpecificationEntity spec2) {
        if (spec1 == null || spec2 == null) return false;

        // 如果有ID，优先使用ID比较
        if (spec1.getId() != null && spec2.getId() != null) {
            return Objects.equals(spec1.getId(), spec2.getId());
        }

        // 否则通过属性组合判断
        if (CollectionUtil.isNotEmpty(spec1.getAttributes()) && CollectionUtil.isNotEmpty(spec2.getAttributes())) {
            if (spec1.getAttributes().size() != spec2.getAttributes().size()) return false;

            // 比较每个属性
            for (GoodsSpecificationEntity.Attribute attr1 : spec1.getAttributes()) {
                boolean found = false;
                for (GoodsSpecificationEntity.Attribute attr2 : spec2.getAttributes()) {
                    if (Objects.equals(attr1.getAttributeId(), attr2.getAttributeId()) &&
                            Objects.equals(attr1.getValueId(), attr2.getValueId())) {
                        found = true;
                        break;
                    }
                }
                if (!found) return false;
            }
            return true;
        }

        return false;
    }

    /**
     * 比较属性列表变化
     */
    private static JSONObject compareAttributes(List<GoodsSpecificationEntity.Attribute> oldAttrs,
                                         List<GoodsSpecificationEntity.Attribute> newAttrs) {
        JSONObject attrChanges = new JSONObject();

        if (CollectionUtil.isEmpty(oldAttrs) && CollectionUtil.isNotEmpty(newAttrs)) {
            attrChanges.put("action", "add_all");
            attrChanges.put("attributes", newAttrs);
            return attrChanges;
        }

        if (CollectionUtil.isNotEmpty(oldAttrs) && CollectionUtil.isEmpty(newAttrs)) {
            attrChanges.put("action", "delete_all");
            attrChanges.put("attributes", oldAttrs);
            return attrChanges;
        }

        List<JSONObject> addedAttrs = new ArrayList<>();
        List<JSONObject> deletedAttrs = new ArrayList<>();

        // 找出删除的属性
        for (GoodsSpecificationEntity.Attribute oldAttr : oldAttrs) {
            boolean found = false;
            for (GoodsSpecificationEntity.Attribute newAttr : newAttrs) {
                if (Objects.equals(oldAttr.getAttributeId(), newAttr.getAttributeId()) &&
                        Objects.equals(oldAttr.getValueId(), newAttr.getValueId())) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                deletedAttrs.add(convertAttrToJson(oldAttr));
            }
        }

        // 找出新增的属性
        for (GoodsSpecificationEntity.Attribute newAttr : newAttrs) {
            boolean found = false;
            for (GoodsSpecificationEntity.Attribute oldAttr : oldAttrs) {
                if (Objects.equals(oldAttr.getAttributeId(), newAttr.getAttributeId()) &&
                        Objects.equals(oldAttr.getValueId(), newAttr.getValueId())) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                addedAttrs.add(convertAttrToJson(newAttr));
            }
        }

        if (!addedAttrs.isEmpty()) {
            attrChanges.put("added", addedAttrs);
        }
        if (!deletedAttrs.isEmpty()) {
            attrChanges.put("deleted", deletedAttrs);
        }

        return attrChanges;
    }

    /**
     * 转换规格列表为JSON
     */
    private static List<JSONObject> convertSpecsToJson(List<GoodsSpecificationEntity> specs) {
        List<JSONObject> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(specs)) {
            for (GoodsSpecificationEntity spec : specs) {
                result.add(convertSpecToJson(spec));
            }
        }
        return result;
    }

    /**
     * 转换单个规格为JSON
     */
    private static JSONObject convertSpecToJson(GoodsSpecificationEntity spec) {
        JSONObject json = new JSONObject();
        if (spec != null) {
            // 使用反射设置字段值
            Field[] fields = spec.getClass().getDeclaredFields();
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    json.put(field.getName(), field.get(spec));
                } catch (IllegalAccessException e) {
                    log.warn("Failed to access field: {}", field.getName(), e);
                }
            }
        }
        return json;
    }

    /**
     * 转换属性为JSON
     */
    private static JSONObject convertAttrToJson(GoodsSpecificationEntity.Attribute attr) {
        JSONObject json = new JSONObject();
        if (attr != null) {
            // 使用反射设置字段值
            Field[] fields = attr.getClass().getDeclaredFields();
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    json.put(field.getName(), field.get(attr));
                } catch (IllegalAccessException e) {
                    log.warn("Failed to access field: {}", field.getName(), e);
                }
            }
        }
        return json;
    }

    /**
     * 创建变更JSON
     */
    private static JSONObject createChangeJson(Object oldValue, Object newValue) {
        JSONObject change = new JSONObject();
        change.put("old", oldValue);
        change.put("new", newValue);
        return change;
    }
}
