package com.social.media.application.content.handler;

import com.social.media.application.content.command.CreatePostCommand;
import com.social.media.application.content.dto.PostResponseDto;
import com.social.media.domain.content.aggregate.Post;
import com.social.media.domain.content.repository.PostRepository;
import com.social.media.domain.content.valueobject.MediaId;
import com.social.media.domain.content.valueobject.PostContent;
import com.social.media.domain.socialaccount.valueobject.SocialAccountId;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.stream.Collectors;

@Service
@Transactional
public class CreatePostCommandHandler {
    
    private final PostRepository postRepository;
    
    public CreatePostCommandHandler(PostRepository postRepository) {
        this.postRepository = postRepository;
    }
    
    public PostResponseDto handle(CreatePostCommand command) {
        // Create PostContent value object using factory method
        PostContent postContent = PostContent.of(command.content());
        
        // Create Post aggregate
        Post post = new Post(
            command.companyId(),
            command.authorId(),
            postContent,
            command.postType(),
            command.categoryId()
        );
        
        // Add media if provided
        if (command.mediaIds() != null && !command.mediaIds().isEmpty()) {
            command.mediaIds().stream()
                .map(MediaId::of)
                .forEach(post::addMedia);
        }
        
        // Set target social accounts if provided
        if (command.targetSocialAccountIds() != null && !command.targetSocialAccountIds().isEmpty()) {
            command.targetSocialAccountIds().stream()
                .map(SocialAccountId::of)
                .forEach(post::addTargetSocialAccount);
        }
        
        // Set scheduling if provided
        if (command.scheduledFor() != null) {
            post.scheduleFor(command.scheduledFor());
        }
        
        // Set tags if provided
        if (command.tags() != null && !command.tags().trim().isEmpty()) {
            post.updateTags(command.tags());
        }
        
        // Pin post if requested (but only after publishing)
        // Note: We'll set isPinned flag but pin() can only be called on published posts
        
        // Save post
        Post savedPost = postRepository.save(post);
        
        // Return DTO
        return mapToDto(savedPost);
    }
    
    private PostResponseDto mapToDto(Post post) {
        return PostResponseDto.builder()
            .id(post.getId().value().toString())
            .companyId(post.getCompanyId().value().toString())
            .authorId(post.getAuthorId().value().toString())
            .categoryId(post.getCategoryId() != null ? post.getCategoryId().value().toString() : null)
            .title("") // No separate title field in Post aggregate
            .content(post.getContent().text())
            .postType(post.getPostType().name())
            .status(post.getStatus().name())
            .mediaIds(post.getMediaIds().stream().map(id -> id.value().toString()).toList())
            .targetSocialAccountIds(post.getTargetSocialAccounts().stream()
                .map(id -> id.value().toString())
                .collect(Collectors.toSet()))
            .scheduledFor(post.getScheduledFor())
            .publishedAt(post.getPublishedAt())
            .createdAt(post.getCreatedAt())
            .updatedAt(post.getUpdatedAt())
            .tags(post.getTags())
            .isPinned(post.isPinned())
            .viewCount(post.getViewCount())
            .likeCount(post.getLikeCount())
            .shareCount(post.getShareCount())
            .commentCount(post.getCommentCount())
            .hashtags(post.getHashtags())
            .mentions(post.getMentions())
            .build();
    }
}

