package com.usky.cdi.service.sip.sdp;

import com.usky.cdi.service.sip.model.SdpMediaInfo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class SdpUtils {

    private static final Pattern CONNECTION_PATTERN =
            Pattern.compile("c=IN IP4 ([\\d.]+)", Pattern.CASE_INSENSITIVE);
    /** GB28181 常见：RTP/AVP、TCP/RTP/AVP、RTP/AVP/TCP、UDP/RTP/AVP */
    private static final Pattern MEDIA_PATTERN = Pattern.compile(
            "m=video\\s+(\\d+)\\s+((?:UDP/|TCP/)?RTP/AVP(?:/(?:UDP|TCP))?)\\s+([\\d\\s]+)",
            Pattern.CASE_INSENSITIVE);
    private static final Pattern RTPMAP_PATTERN =
            Pattern.compile("a=rtpmap:(\\d+)\\s+([^/\\s]+)/\\d+", Pattern.CASE_INSENSITIVE);
    private static final Pattern Y_PATTERN =
            Pattern.compile("y=([0-9]+)", Pattern.CASE_INSENSITIVE);
    private static final Pattern SETUP_PATTERN =
            Pattern.compile("a=setup:(\\w+)", Pattern.CASE_INSENSITIVE);

    private SdpUtils() {
    }

    public static SdpMediaInfo parseVideoMedia(String sdp) {
        if (sdp == null || sdp.isEmpty()) {
            return null;
        }
        String normalized = sdp.replace("\n", "\r\n");
        if (!normalized.contains("\r\n")) {
            normalized = sdp;
        }

        SdpMediaInfo info = new SdpMediaInfo();
        info.setMediaType("video");

        Matcher connMatcher = CONNECTION_PATTERN.matcher(normalized);
        if (connMatcher.find()) {
            info.setConnectionAddress(connMatcher.group(1));
        }

        Matcher mediaMatcher = MEDIA_PATTERN.matcher(normalized);
        if (!mediaMatcher.find()) {
            return null;
        }

        info.setPort(Integer.parseInt(mediaMatcher.group(1)));
        String protocol = mediaMatcher.group(2).trim();
        info.setMediaProtocol(protocol);
        info.setTcpMedia(protocol.toUpperCase().contains("TCP"));

        String payloadPart = mediaMatcher.group(3).trim();
        int payloadType = parseFirstPayloadType(payloadPart);
        if (payloadType <= 0) {
            return null;
        }
        info.setPayloadType(payloadType);

        String codec = findCodec(normalized, payloadType);
        if (codec == null) {
            codec = payloadType == 96 ? "PS" : "H264";
        }
        info.setCodec(codec.toUpperCase());

        Matcher setupMatcher = SETUP_PATTERN.matcher(normalized);
        if (setupMatcher.find()) {
            info.setSetup(setupMatcher.group(1).toLowerCase());
        }

        Matcher yMatcher = Y_PATTERN.matcher(normalized);
        if (yMatcher.find()) {
            info.setSsrc(yMatcher.group(1));
        }

        info.setSendOnly(normalized.contains("a=sendonly") || normalized.contains("a=recvonly"));
        return info;
    }

    /**
     * 构建 GB28181 200 OK SDP，尽量与平台 INVITE 的传输/编码一致。
     */
    public static String buildGb28181AnswerSdp(String localIp, int localRtpPort,
                                                SdpMediaInfo media, String deviceId, String defaultSsrc) {
        int payloadType = media != null && media.getPayloadType() > 0 ? media.getPayloadType() : 96;
        String codec = resolveAnswerCodec(media, payloadType);
        String ssrc = media != null && media.getSsrc() != null ? media.getSsrc() : defaultSsrc;
        boolean tcp = media != null && media.isTcpMedia();
        String mediaLine = tcp
                ? "m=video " + localRtpPort + " TCP/RTP/AVP " + payloadType + "\r\n"
                : "m=video " + localRtpPort + " RTP/AVP " + payloadType + "\r\n";

        StringBuilder sb = new StringBuilder();
        sb.append("v=0\r\n");
        sb.append("o=").append(deviceId).append(" 0 0 IN IP4 ").append(localIp).append("\r\n");
        sb.append("s=Play\r\n");
        sb.append("u=").append(deviceId).append(":0\r\n");
        sb.append("c=IN IP4 ").append(localIp).append("\r\n");
        sb.append("t=0 0\r\n");
        sb.append(mediaLine);
        sb.append("a=rtpmap:").append(payloadType).append(" ").append(codec).append("/90000\r\n");
        sb.append("a=sendonly\r\n");
        if (tcp) {
            String answerSetup = resolveAnswerSetup(media != null ? media.getSetup() : null);
            sb.append("a=setup:").append(answerSetup).append("\r\n");
            sb.append("a=connection:new\r\n");
        }
        sb.append("y=").append(ssrc).append("\r\n");
        return sb.toString();
    }

    public static long parseSsrcValue(String ssrcStr, long defaultValue) {
        if (ssrcStr == null || ssrcStr.isEmpty()) {
            return defaultValue;
        }
        try {
            return Long.parseLong(ssrcStr.trim());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    private static int parseFirstPayloadType(String payloadPart) {
        String[] parts = payloadPart.split("\\s+");
        for (String part : parts) {
            if (!part.isEmpty()) {
                return Integer.parseInt(part);
            }
        }
        return 0;
    }

    private static String findCodec(String sdp, int payloadType) {
        Matcher rtpmapMatcher = RTPMAP_PATTERN.matcher(sdp);
        String fallback = null;
        while (rtpmapMatcher.find()) {
            int pt = Integer.parseInt(rtpmapMatcher.group(1));
            String name = rtpmapMatcher.group(2).toUpperCase();
            if (pt == payloadType) {
                return name;
            }
            if ("PS".equals(name)) {
                fallback = name;
            }
        }
        return fallback;
    }

    private static String resolveAnswerCodec(SdpMediaInfo media, int payloadType) {
        if (media != null && media.getCodec() != null) {
            String codec = media.getCodec().toUpperCase();
            if ("PS".equals(codec) || "H264".equals(codec) || "MPEG4".equals(codec)) {
                return codec;
            }
        }
        return payloadType == 96 ? "PS" : "H264";
    }

    /** 平台 passive -> 设备 active；平台 active -> 设备 passive */
    private static String resolveAnswerSetup(String inviteSetup) {
        if ("active".equalsIgnoreCase(inviteSetup)) {
            return "passive";
        }
        return "active";
    }

    /** SIP 服务端 200 OK 应答 SDP（简化版） */
    public static String buildVideoAnswerSdp(String localIp, int localRtpPort,
                                             int payloadType, String codec) {
        SdpMediaInfo media = new SdpMediaInfo();
        media.setPayloadType(payloadType);
        media.setCodec(codec != null ? codec : (payloadType == 96 ? "PS" : "H264"));
        media.setSsrc("0100000001");
        return buildGb28181AnswerSdp(localIp, localRtpPort, media, "34020000001320000001", media.getSsrc());
    }

    /** @deprecated 使用 {@link #buildGb28181AnswerSdp} */
    public static String buildGb28181InviteSdp(String localIp, int localRtpPort,
                                                int payloadType, String deviceId, String ssrc) {
        SdpMediaInfo media = new SdpMediaInfo();
        media.setPayloadType(payloadType);
        media.setCodec(payloadType == 96 ? "PS" : "H264");
        media.setSsrc(ssrc);
        return buildGb28181AnswerSdp(localIp, localRtpPort, media, deviceId, ssrc);
    }

    /** @deprecated 使用 {@link #buildGb28181InviteSdp} */
    public static String buildInviteSdp(String localIp, int localRtpPort, int payloadType, String deviceId) {
        return buildGb28181InviteSdp(localIp, localRtpPort, payloadType, deviceId, "0100000001");
    }
}
