package de.assecutor.votianlt.dto;

import de.assecutor.votianlt.model.MessageContentType;
import java.util.Map;
import org.bson.types.ObjectId;

/**
 * Normalized payload for chat messages sent by mobile clients via WebSocket.
 * receiver = AppUser ID (clientId) extracted from topic
 */
public record ChatMessageInboundPayload(String receiver, String content, MessageContentType contentType,
        String messageId, ObjectId jobId, String jobNumber) {

    public ChatMessageInboundPayload {
        contentType = contentType != null ? contentType : MessageContentType.TEXT;
    }

    public static ChatMessageInboundPayload fromPayload(Map<String, Object> payload) {
        if (payload == null) {
            throw new IllegalArgumentException("payload must not be null");
        }

        String receiver = extractRequiredString(payload, "receiver");
        String content = extractRequiredString(payload, "content");
        MessageContentType contentType = extractContentType(payload.get("contentType"));
        String messageId = extractOptionalString(payload.get("messageId"));
        ObjectId jobId = extractObjectId(payload.get("jobId"), "jobId");
        String jobNumber = extractOptionalString(payload.get("jobNumber"));

        return new ChatMessageInboundPayload(receiver, content, contentType, messageId, jobId, jobNumber);
    }

    public boolean hasJobContext() {
        return jobId != null;
    }

    private static String extractRequiredString(Map<String, Object> payload, String key) {
        Object value = payload.get(key);
        String asString = value != null ? value.toString().trim() : null;
        if (asString == null || asString.isEmpty()) {
            throw new IllegalArgumentException("Missing required field '%s'".formatted(key));
        }
        return asString;
    }

    private static String extractOptionalString(Object value) {
        if (value == null) {
            return null;
        }
        String asString = value.toString().trim();
        return asString.isEmpty() ? null : asString;
    }

    private static ObjectId extractObjectId(Object value, String fieldName) {
        String candidate = extractOptionalString(value);
        if (candidate == null) {
            return null;
        }
        try {
            return new ObjectId(candidate);
        } catch (IllegalArgumentException ex) {
            throw new IllegalArgumentException("Field '%s' must be a valid MongoDB ObjectId".formatted(fieldName), ex);
        }
    }

    private static MessageContentType extractContentType(Object value) {
        String candidate = extractOptionalString(value);
        if (candidate == null) {
            return MessageContentType.TEXT;
        }
        try {
            return MessageContentType.valueOf(candidate.trim().toUpperCase());
        } catch (IllegalArgumentException ex) {
            throw new IllegalArgumentException("Unsupported contentType '%s'".formatted(candidate), ex);
        }
    }
}
