package com.pablotj.ai.chat.infrastructure.persistence.mapper;

import com.pablotj.ai.chat.domain.model.Conversation;
import com.pablotj.ai.chat.domain.model.ConversationId;
import com.pablotj.ai.chat.domain.model.ConversationMessage;
import com.pablotj.ai.chat.domain.model.ConversationStatus;
import com.pablotj.ai.chat.domain.model.ConversationSummary;
import com.pablotj.ai.chat.domain.model.MessageContent;
import com.pablotj.ai.chat.domain.model.MessageId;
import com.pablotj.ai.chat.domain.model.MessageMetadata;
import com.pablotj.ai.chat.domain.model.MessageRole;
import com.pablotj.ai.chat.infrastructure.persistence.entity.ConversationEntity;
import com.pablotj.ai.chat.infrastructure.persistence.entity.ConversationMessageEntity;
import com.pablotj.ai.chat.infrastructure.persistence.entity.ConversationStatusEntity;
import com.pablotj.ai.chat.infrastructure.persistence.entity.MessageRoleEntity;
import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;

/**
 * MapStruct mapper for converting between domain models and JPA entities.
 */
@Mapper(componentModel = "spring", imports = {ConversationId.class, MessageId.class})
public interface ConversationEntityMapper {

    // Conversation mappings
    @Mapping(source = "conversationId.id", target = "id")
    @Mapping(source = "conversationId.uuid", target = "uuid")
    @Mapping(source = "summary.title", target = "title")
    @Mapping(source = "summary.description", target = "description")
    @Mapping(source = "status", target = "status", qualifiedByName = "domainStatusToEntity")
    @Mapping(source = "messages", target = "messages")
    ConversationEntity toEntity(Conversation conversation);

    @Mapping(target = "conversationId", expression = "java( new ConversationId( entity.getId(), entity.getUuid() ) )")
    @Mapping(source = "title", target = "summary.title")
    @Mapping(source = "status", target = "status", qualifiedByName = "entityStatusToDomain")
    @Mapping(source = "messages", target = "messages")
    Conversation toDomain(ConversationEntity entity);

    // Message mappings
    @Mapping(source = "messageId.id", target = "id")
    @Mapping(source = "messageId.uuid", target = "uuid")
    @Mapping(source = "role", target = "role", qualifiedByName = "domainRoleToEntity")
    @Mapping(source = "content.text", target = "content")
    @Mapping(source = "metadata.allProperties", target = "metadata")
    @Mapping(target = "conversation.id", source = "conversationId.id")
    @Mapping(target = "conversation.uuid", source = "conversationId.uuid")
    ConversationMessageEntity toMessageEntity(ConversationMessage message);

    @Mapping(target = "messageId", expression = "java( new MessageId( entity.getId(), entity.getUuid() ) )")
    @Mapping(target = "conversationId", expression = "java( new ConversationId( entity.getConversation().getId(), entity.getConversation().getUuid() ) )")
    @Mapping(source = "role", target = "role", qualifiedByName = "entityRoleToDomain")
    @Mapping(source = "content", target = "content", qualifiedByName = "stringToMessageContent")
    @Mapping(source = "metadata", target = "metadata", qualifiedByName = "mapToMessageMetadata")
    ConversationMessage toMessageDomain(ConversationMessageEntity entity);

    List<ConversationMessageEntity> toMessageEntities(List<ConversationMessage> messages);

    List<ConversationMessage> toMessageDomains(List<ConversationMessageEntity> entities);

    // Status mappings
    ConversationStatusEntity toEntityStatus(ConversationStatus status);

    ConversationStatus toDomainStatus(ConversationStatusEntity status);

    MessageRoleEntity toEntityRole(MessageRole role);

    MessageRole toDomainRole(MessageRoleEntity role);

    // Named mapping methods
    @Named("stringToMessageContent")
    default MessageContent stringToMessageContent(String value) {
        return value != null ? MessageContent.of(value) : null;
    }

    @Named("titleAndDescriptionToSummary")
    default ConversationSummary titleAndDescriptionToSummary(ConversationEntity entity) {
        return ConversationSummary.of(entity.getTitle(), entity.getDescription());
    }

    @Named("mapToMessageMetadata")
    default MessageMetadata mapToMessageMetadata(java.util.Map<String, Object> map) {
        return map != null ? MessageMetadata.of(map) : MessageMetadata.empty();
    }

    @Named("domainStatusToEntity")
    default ConversationStatusEntity domainStatusToEntity(ConversationStatus status) {
        return status != null ? ConversationStatusEntity.valueOf(status.name()) : null;
    }

    @Named("entityStatusToDomain")
    default ConversationStatus entityStatusToDomain(ConversationStatusEntity status) {
        return status != null ? ConversationStatus.valueOf(status.name()) : null;
    }

    @Named("domainRoleToEntity")
    default MessageRoleEntity domainRoleToEntity(MessageRole role) {
        return role != null ? MessageRoleEntity.valueOf(role.name()) : null;
    }

    @Named("entityRoleToDomain")
    default MessageRole entityRoleToDomain(MessageRoleEntity role) {
        return role != null ? MessageRole.valueOf(role.name()) : null;
    }
}
