package com.pablotj.ai.chat.domain.model;

import java.time.Instant;
import java.util.Objects;

/**
 * Domain entity representing a message within a conversation.
 * Encapsulates message data with rich domain behavior.
 */
public final class ConversationMessage {

    private final MessageId messageId;
    private final ConversationId conversationId;
    private final MessageRole role;
    private final MessageContent content;
    private final Instant createdAt;
    private final MessageMetadata metadata;

    private ConversationMessage(Builder builder) {
        this.messageId = Objects.requireNonNull(builder.messageId, "Message ID is required");
        this.conversationId = Objects.requireNonNull(builder.conversationId, "Conversation ID is required");
        this.role = Objects.requireNonNull(builder.role, "Message role is required");
        this.content = Objects.requireNonNull(builder.content, "Message content is required");
        this.createdAt = Objects.requireNonNull(builder.createdAt, "Created timestamp is required");
        this.metadata = builder.metadata != null ? builder.metadata : MessageMetadata.empty();
    }

    public static Builder builder() {
        return new Builder();
    }

    public static ConversationMessage createUserMessage(
            ConversationId conversationId,
            MessageContent content) {
        return builder()
                .messageId(MessageId.generate())
                .conversationId(conversationId)
                .role(MessageRole.USER)
                .content(content)
                .createdAt(Instant.now())
                .build();
    }

    public static ConversationMessage createAssistantMessage(
            ConversationId conversationId,
            MessageContent content) {
        return builder()
                .messageId(MessageId.generate())
                .conversationId(conversationId)
                .role(MessageRole.ASSISTANT)
                .content(content)
                .createdAt(Instant.now())
                .build();
    }

    // Getters
    public MessageId getMessageId() {
        return messageId;
    }

    public ConversationId getConversationId() {
        return conversationId;
    }

    public MessageRole getRole() {
        return role;
    }

    public MessageContent getContent() {
        return content;
    }

    public Instant getCreatedAt() {
        return createdAt;
    }

    public MessageMetadata getMetadata() {
        return metadata;
    }

    // Domain behavior
    public boolean isFromUser() {
        return role.isUser();
    }

    public boolean isFromAssistant() {
        return role.isAssistant();
    }

    public ConversationMessage withMetadata(MessageMetadata metadata) {
        return builder()
                .messageId(this.messageId)
                .conversationId(this.conversationId)
                .role(this.role)
                .content(this.content)
                .createdAt(this.createdAt)
                .metadata(metadata)
                .build();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        ConversationMessage that = (ConversationMessage) obj;
        return Objects.equals(messageId, that.messageId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(messageId);
    }

    @Override
    public String toString() {
        return String.format("ConversationMessage{id=%s, role=%s, content='%s'}",
                messageId, role, content.truncate(50));
    }

    public static final class Builder {
        private MessageId messageId;
        private ConversationId conversationId;
        private MessageRole role;
        private MessageContent content;
        private Instant createdAt;
        private MessageMetadata metadata;

        private Builder() {
        }

        public Builder messageId(MessageId messageId) {
            this.messageId = messageId;
            return this;
        }

        public Builder conversationId(ConversationId conversationId) {
            this.conversationId = conversationId;
            return this;
        }

        public Builder role(MessageRole role) {
            this.role = role;
            return this;
        }

        public Builder content(MessageContent content) {
            this.content = content;
            return this;
        }

        public Builder createdAt(Instant createdAt) {
            this.createdAt = createdAt;
            return this;
        }

        public Builder metadata(MessageMetadata metadata) {
            this.metadata = metadata;
            return this;
        }

        public ConversationMessage build() {
            return new ConversationMessage(this);
        }
    }
}
