package com.usky.vpp.service.impl;

import com.usky.common.core.exception.BusinessException;
import com.usky.vpp.config.VppUnProperties;
import com.usky.vpp.config.VppUnPropertiesRegistry;
import com.usky.vpp.config.VppUnTenantContext;
import com.usky.vpp.domain.VppDrEvent;
import com.usky.vpp.service.VppDrEventIngestService;
import com.usky.vpp.service.VppUnDnService;
import com.usky.vpp.util.VppUnMessageBuilder;
import com.usky.vpp.util.VppUnPayloadHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 运管平台 UN/DN 对接实现（报文结构对齐联调 JSON 实例 20251127）
 */
@Service
public class VppUnDnServiceImpl implements VppUnDnService {

    private static final Logger log = LoggerFactory.getLogger(VppUnDnServiceImpl.class);

    @Autowired
    private VppUnPropertiesRegistry propertiesRegistry;

    @Autowired
    private VppDrEventIngestService drEventIngestService;

    @Override
    public Map<String, Object> tokenRequest(Map<String, Object> body) {
        return ok("TokenResponse", body);
    }

    @Override
    public Map<String, Object> createRegistration(Map<String, Object> body) {
        VppUnProperties unProperties = bindTenantContext(body);
        Map<String, Object> resp = ok("CreateRegistrationResponse", body);
        resp.put("registrationID", UUID.randomUUID().toString());
        resp.put("pollFreq", "PT" + unProperties.getPollIntervalSec() + "S");
        resp.put("unID", "test_un");
        resp.put("transport", new String[]{"REST"});
        return resp;
    }

    @Override
    public Map<String, Object> registerReport(Map<String, Object> body) {
        return ok("RegisterReportResponse", body);
    }

    @Override
    public Map<String, Object> momentDataReport(Map<String, Object> body) {
        return ok("MomentDataReportResponse", body);
    }

    @Override
    public Map<String, Object> intervalDataReport(Map<String, Object> body) {
        return ok("IntervalDataReportResponse", body);
    }

    @Override
    public Map<String, Object> poll(Map<String, Object> body) {
        return ok("PollResponse", body);
    }

    @Override
    public Map<String, Object> distributeEvent(Map<String, Object> body) {
        return ingestDistributeAndRespond("DistributeEventRequest", body, () ->
                drEventIngestService.ingestDistributeEvent(body, "DistributeEventRequest"));
    }

    @Override
    public Map<String, Object> createOpt(Map<String, Object> body) {
        VppUnProperties unProperties = bindTenantContext(body);
        try {
            VppDrEvent event = drEventIngestService.ingestCreateOptRequest(body, "CreateOptRequest");
            Map<String, Object> resp = VppUnMessageBuilder.buildCreateOptResponse(body, unProperties);
            enrichEventMeta(resp, event);
            return resp;
        } catch (IllegalArgumentException ex) {
            log.warn("CreateOptRequest 处理失败: {}", ex.getMessage());
            return error("CreateOptResponse", body, 400, ex.getMessage());
        } catch (Exception ex) {
            log.error("CreateOptRequest 处理失败", ex);
            return error("CreateOptResponse", body, 500, "处理失败");
        }
    }

    @Override
    public Map<String, Object> createCq(Map<String, Object> body) {
        VppUnProperties unProperties = bindTenantContext(body);
        try {
            VppDrEvent event = drEventIngestService.ingestCreateCqRequest(body, "CreateCqRequest");
            Map<String, Object> resp = VppUnMessageBuilder.buildCreateCqResponse(body, unProperties);
            enrichEventMeta(resp, event);
            return resp;
        } catch (IllegalArgumentException ex) {
            log.warn("CreateCqRequest 处理失败: {}", ex.getMessage());
            return error("CreateCqResponse", body, 400, ex.getMessage());
        } catch (Exception ex) {
            log.error("CreateCqRequest 处理失败", ex);
            return error("CreateCqResponse", body, 500, "处理失败");
        }
    }

    @Override
    public Map<String, Object> createEventResponse(Map<String, Object> body) {
        VppUnProperties unProperties = bindTenantContext(body);
        try {
            String eventId = resolveEventIdForAck(body);
            if (!StringUtils.hasText(eventId)) {
                throw new IllegalArgumentException("CreateEventResponse 缺少 eventID");
            }
            VppDrEvent event = drEventIngestService.acknowledgeClearingPublicity(eventId, body, "CreateEventResponse");
            String requestId = VppUnPayloadHelper.getString(body, "requestID");
            String optType = resolveOptType(body);
            Map<String, Object> resp = VppUnMessageBuilder.buildCreateEventResponse(
                    eventId, requestId, optType, unProperties);
            enrichEventMeta(resp, event);
            return resp;
        } catch (IllegalArgumentException ex) {
            log.warn("CreateEventResponse 处理失败: {}", ex.getMessage());
            return error("CreateEventResponse", body, 400, ex.getMessage());
        } catch (Exception ex) {
            log.error("CreateEventResponse 处理失败", ex);
            return error("CreateEventResponse", body, 500, "处理失败");
        }
    }

    private VppUnProperties bindTenantContext(Map<String, Object> body) {
        Integer tenantId = VppUnTenantContext.getTenantId();
        if (tenantId == null) {
            String dnId = body != null ? VppUnPayloadHelper.getString(body, "dnID", "dnId") : null;
            VppUnProperties byDn = propertiesRegistry.getByDnId(dnId);
            if (byDn != null) {
                tenantId = byDn.getTenantId();
            }
        }
        if (tenantId == null) {
            try {
                tenantId = VppUnTenantContext.resolveTenantId();
            } catch (BusinessException ignored) {
                for (VppUnProperties candidate : propertiesRegistry.getAll()) {
                    tenantId = candidate.getTenantId();
                    break;
                }
            }
        }
        if (tenantId == null) {
            throw new BusinessException("未找到运管平台租户配置");
        }
        VppUnTenantContext.setTenantId(tenantId);
        return propertiesRegistry.require(tenantId);
    }

    private Map<String, Object> ingestDistributeAndRespond(String root, Map<String, Object> body, IngestAction action) {
        bindTenantContext(body);
        try {
            VppDrEvent event = action.run();
            Map<String, Object> resp = ok(root, body);
            enrichEventMeta(resp, event);
            return resp;
        } catch (IllegalArgumentException ex) {
            log.warn("{} 报文解析失败: {}", root, ex.getMessage());
            return error(root, body, 400, ex.getMessage());
        } catch (Exception ex) {
            log.error("{} 入库失败", root, ex);
            return error(root, body, 500, "事件入库失败");
        }
    }

    private void enrichEventMeta(Map<String, Object> resp, VppDrEvent event) {
        if (event != null) {
            resp.put("eventID", event.getEventId());
            resp.put("internalId", event.getId());
            resp.put("eventStatus", event.getEventStatus());
        }
    }

    @SuppressWarnings("unchecked")
    private String resolveEventIdForAck(Map<String, Object> body) {
        String eventId = VppUnPayloadHelper.getString(body, "eventID", "eventId");
        if (StringUtils.hasText(eventId)) {
            return eventId;
        }
        Object eventResponses = body.get("eventResponses");
        if (eventResponses instanceof List && !((List<?>) eventResponses).isEmpty()) {
            Object first = ((List<?>) eventResponses).get(0);
            if (first instanceof Map) {
                Object qualified = ((Map<String, Object>) first).get("qualifiedEventID");
                if (qualified instanceof Map) {
                    return VppUnPayloadHelper.getString((Map<String, Object>) qualified, "eventID", "eventId");
                }
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private String resolveOptType(Map<String, Object> body) {
        String optType = VppUnPayloadHelper.getString(body, "optType");
        if (StringUtils.hasText(optType)) {
            return optType;
        }
        Object eventResponses = body.get("eventResponses");
        if (eventResponses instanceof List && !((List<?>) eventResponses).isEmpty()) {
            Object first = ((List<?>) eventResponses).get(0);
            if (first instanceof Map) {
                return VppUnPayloadHelper.getString((Map<String, Object>) first, "optType");
            }
        }
        return "optIn";
    }

    private Map<String, Object> ok(String root, Map<String, Object> body) {
        VppUnProperties unProperties = bindTenantContext(body);
        Map<String, Object> resp = new HashMap<>();
        resp.put("root", root);
        resp.put("version", 1);
        resp.put("code", 200);
        resp.put("description", "ok");
        resp.put("requestID", body == null ? UUID.randomUUID().toString() : body.get("requestID"));
        resp.put("dnID", unProperties.getDnId());
        return resp;
    }

    private Map<String, Object> error(String root, Map<String, Object> body, int code, String description) {
        VppUnProperties unProperties = bindTenantContext(body);
        Map<String, Object> resp = new HashMap<>();
        resp.put("root", root);
        resp.put("version", 1);
        resp.put("code", code);
        resp.put("description", description);
        resp.put("requestID", body == null ? UUID.randomUUID().toString() : body.get("requestID"));
        resp.put("dnID", unProperties.getDnId());
        return resp;
    }

    @FunctionalInterface
    private interface IngestAction {
        VppDrEvent run();
    }
}
