package com.usky.vpp.util;

import com.usky.vpp.constant.VppDrEventStatus;
import com.usky.vpp.enums.VppUnEventPhase;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 解析运管平台 DistributeEventRequest / Event 结构（DLT 1867 联调 JSON 实例）
 */
public final class VppUnEventParser {

    private VppUnEventParser() {
    }

    @SuppressWarnings("unchecked")
    public static List<Map<String, Object>> extractEvents(Map<String, Object> body) {
        if (body == null) {
            return Collections.emptyList();
        }
        Object events = body.get("events");
        if (events instanceof List) {
            return (List<Map<String, Object>>) events;
        }
        if (body.containsKey("descriptor") || body.containsKey("activePeriod")) {
            return Collections.singletonList(body);
        }
        return Collections.emptyList();
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> getDescriptor(Map<String, Object> event) {
        if (event == null) {
            return Collections.emptyMap();
        }
        Object descriptor = event.get("descriptor");
        if (descriptor instanceof Map) {
            return (Map<String, Object>) descriptor;
        }
        return event;
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> getTarget(Map<String, Object> event) {
        if (event == null) {
            return Collections.emptyMap();
        }
        Object target = event.get("target");
        return target instanceof Map ? (Map<String, Object>) target : Collections.emptyMap();
    }

    @SuppressWarnings("unchecked")
    public static List<String> getTargetResourceIds(Map<String, Object> event) {
        Map<String, Object> target = getTarget(event);
        Object resourceIds = target.get("resourceID");
        if (resourceIds == null) {
            resourceIds = target.get("resourceId");
        }
        if (!(resourceIds instanceof List)) {
            return Collections.emptyList();
        }
        List<String> result = new ArrayList<>();
        for (Object item : (List<?>) resourceIds) {
            if (item == null) {
                continue;
            }
            String value = String.valueOf(item).trim();
            if (StringUtils.hasText(value)) {
                result.add(value);
            }
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public static List<Map<String, Object>> getTargetResources(Map<String, Object> event) {
        Map<String, Object> target = getTarget(event);
        Object resources = target.get("resources");
        if (!(resources instanceof List)) {
            return Collections.emptyList();
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for (Object item : (List<?>) resources) {
            if (item instanceof Map) {
                list.add((Map<String, Object>) item);
            }
        }
        return list;
    }

    public static VppUnEventPhase detectPhase(Map<String, Object> event) {
        Map<String, Object> descriptor = getDescriptor(event);
        Boolean filing = VppUnPayloadHelper.getBoolean(descriptor, "filing");
        Boolean lastFiling = VppUnPayloadHelper.getBoolean(descriptor, "lastFiling");
        List<Map<String, Object>> resources = getTargetResources(event);
        boolean hasValues = hasResourceValues(resources);

        if (Boolean.TRUE.equals(filing) && !hasValues) {
            return VppUnEventPhase.INVITATION;
        }
        if (Boolean.TRUE.equals(filing) && hasValues) {
            return VppUnEventPhase.DECLARE_FEEDBACK;
        }
//        if (Boolean.FALSE.equals(filing) && Boolean.TRUE.equals(lastFiling) && hasValues) {
//            return VppUnEventPhase.SPLIT_RESULT;
//        }
        if (Boolean.FALSE.equals(filing) && Boolean.TRUE.equals(lastFiling)) {
            return VppUnEventPhase.SPLIT_NOTICE;
        }
        if (hasValues) {
            return VppUnEventPhase.CLEARING_PUBLICITY;
        }
        return VppUnEventPhase.UNKNOWN;
    }

    public static String getEventId(Map<String, Object> event) {
        Map<String, Object> descriptor = getDescriptor(event);
        return VppUnPayloadHelper.getString(descriptor, "eventID", "eventId", "event_id");
    }

    public static Integer mapResponseType(Map<String, Object> descriptor) {
        Object notification = VppUnPayloadHelper.getRaw(descriptor, "notification");
        Integer mapped = VppUnPayloadHelper.parseResponseType(notification);
        if (mapped != null) {
            return mapped;
        }
        return 1;
    }

    public static Integer mapEventType(Map<String, Object> descriptor) {
        Object control = VppUnPayloadHelper.getRaw(descriptor, "control");
        Integer mapped = VppUnPayloadHelper.parseEventType(control);
        if (mapped != null) {
            return mapped;
        }
        String text = control == null ? "" : String.valueOf(control);
        if (text.contains("fillValley")) {
            return 2;
        }
        return 1;
    }

    public static Integer mapPlatformStatus(Map<String, Object> descriptor) {
        String status = VppUnPayloadHelper.getString(descriptor, "status");
        if (!StringUtils.hasText(status)) {
            return null;
        }
        switch (status.trim().toLowerCase()) {
            case "cancelled":
                return VppDrEventStatus.CANCELLED;
            case "completed":
                return VppDrEventStatus.ENDED;
            case "active":
                return VppDrEventStatus.EXECUTING;
            case "far":
            case "near":
            case "none":
            default:
                return 0;
        }
    }

    @SuppressWarnings("unchecked")
    public static LocalDateTime[] resolveActivePeriod(Map<String, Object> event) {
        Object periods = event.get("activePeriod");
        if (!(periods instanceof List) || ((List<?>) periods).isEmpty()) {
            return new LocalDateTime[]{null, null};
        }
        Object first = ((List<?>) periods).get(0);
        if (!(first instanceof Map)) {
            return new LocalDateTime[]{null, null};
        }
        Map<String, Object> period = (Map<String, Object>) first;
        LocalDateTime start = VppUnPayloadHelper.getDateTime(period, "dtstart", "startTime");
        LocalDateTime end = VppUnPayloadHelper.getDateTime(period, "dtend", "endTime");
        return new LocalDateTime[]{start, end};
    }

    @SuppressWarnings("unchecked")
    public static BigDecimal extractDemandChargeKw(Map<String, Object> event) {
        BigDecimal maxAbs = null;
        Object signals = event.get("signals");
        if (!(signals instanceof Map)) {
            return null;
        }
        Object signal = ((Map<String, Object>) signals).get("signal");
        List<?> signalList;
        if (signal instanceof List) {
            signalList = (List<?>) signal;
        } else if (signal instanceof Map) {
            signalList = Collections.singletonList(signal);
        } else {
            return null;
        }
        for (Object sigObj : signalList) {
            if (!(sigObj instanceof Map)) {
                continue;
            }
            Map<String, Object> sig = (Map<String, Object>) sigObj;
            String signalName = VppUnPayloadHelper.getString(sig, "signalName");
            if (!"DEMAND_CHARGE".equalsIgnoreCase(signalName)) {
                continue;
            }
            maxAbs = maxAbs(maxAbs, maxAbsFromIntervals(sig));
        }
        return maxAbs;
    }

    @SuppressWarnings("unchecked")
    public static BigDecimal extractEnergyPrice(Map<String, Object> event) {
        Object signals = event.get("signals");
        if (!(signals instanceof Map)) {
            return null;
        }
        Object signal = ((Map<String, Object>) signals).get("signal");
        List<?> signalList;
        if (signal instanceof List) {
            signalList = (List<?>) signal;
        } else if (signal instanceof Map) {
            signalList = Collections.singletonList(signal);
        } else {
            return null;
        }
        BigDecimal sum = BigDecimal.ZERO;
        int count = 0;
        for (Object sigObj : signalList) {
            if (!(sigObj instanceof Map)) {
                continue;
            }
            Map<String, Object> sig = (Map<String, Object>) sigObj;
            String signalName = VppUnPayloadHelper.getString(sig, "signalName");
            if (!"ENERGY_PRICE".equalsIgnoreCase(signalName)) {
                continue;
            }
            List<BigDecimal> values = valuesFromIntervals(sig);
            for (BigDecimal value : values) {
                sum = sum.add(value);
                count++;
            }
        }
        if (count == 0) {
            return null;
        }
        return sum.divide(BigDecimal.valueOf(count), 4, RoundingMode.HALF_UP);
    }

    public static BigDecimal sumResourceLoadKw(List<Map<String, Object>> resources, boolean absolute) {
        BigDecimal total = BigDecimal.ZERO;
        for (Map<String, Object> resource : resources) {
            BigDecimal load = maxAbsFromResourceValues(resource);
            if (load == null) {
                load = VppUnPayloadHelper.getDecimal(resource, "load");
            }
            if (load == null) {
                continue;
            }
            total = total.add(absolute ? load.abs() : load);
        }
        return total;
    }

    @SuppressWarnings("unchecked")
    private static List<BigDecimal> valuesFromIntervals(Map<String, Object> signal) {
        Object intervals = signal.get("intervals");
        if (!(intervals instanceof Map)) {
            return Collections.emptyList();
        }
        Object irregular = ((Map<String, Object>) intervals).get("irregular");
        if (!(irregular instanceof Map)) {
            return Collections.emptyList();
        }
        Object values = ((Map<String, Object>) irregular).get("values");
        if (!(values instanceof List)) {
            return Collections.emptyList();
        }
        List<BigDecimal> result = new ArrayList<>();
        for (Object item : (List<?>) values) {
            if (item instanceof Map) {
                BigDecimal value = VppUnPayloadHelper.getDecimal((Map<String, Object>) item, "value");
                if (value != null) {
                    result.add(value);
                }
            }
        }
        return result;
    }

    private static BigDecimal maxAbsFromIntervals(Map<String, Object> signal) {
        BigDecimal max = null;
        for (BigDecimal value : valuesFromIntervals(signal)) {
            max = maxAbs(max, value.abs());
        }
        return max;
    }

    @SuppressWarnings("unchecked")
    private static BigDecimal maxAbsFromResourceValues(Map<String, Object> resource) {
        Object values = resource.get("values");
        if (!(values instanceof List)) {
            return null;
        }
        BigDecimal max = null;
        for (Object item : (List<?>) values) {
            if (item instanceof Map) {
                BigDecimal value = VppUnPayloadHelper.getDecimal((Map<String, Object>) item, "value");
                if (value != null) {
                    max = maxAbs(max, value.abs());
                }
            }
        }
        return max;
    }

    private static boolean hasResourceValues(List<Map<String, Object>> resources) {
        for (Map<String, Object> resource : resources) {
            if (maxAbsFromResourceValues(resource) != null) {
                return true;
            }
            if (VppUnPayloadHelper.getDecimal(resource, "load") != null) {
                return true;
            }
        }
        return false;
    }

    private static BigDecimal maxAbs(BigDecimal current, BigDecimal candidate) {
        if (candidate == null) {
            return current;
        }
        if (current == null || candidate.compareTo(current) > 0) {
            return candidate;
        }
        return current;
    }
}
