package com.social.media.application.content.handler;

import com.social.media.application.content.command.UpdatePostCommand;
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 UpdatePostCommandHandler {
    
    private final PostRepository postRepository;
    
    public UpdatePostCommandHandler(PostRepository postRepository) {
        this.postRepository = postRepository;
    }
    
    public PostResponseDto handle(UpdatePostCommand command) {
        // Find existing post
        Post post = postRepository.findById(command.postId())
            .orElseThrow(() -> new RuntimeException(
                "Post not found: " + command.postId()
            ));
        
        // Update content if provided
        if (command.content() != null && !command.content().trim().isEmpty()) {
            PostContent newContent = PostContent.of(command.content());
            post.updateContent(newContent);
        }
        
        // Update category if provided
        if (command.categoryId() != null) {
            post.updateCategory(command.categoryId());
        }
        
        // Update media if provided
        if (command.mediaIds() != null) {
            // Clear existing media and add new ones
            post.getMediaIds().forEach(post::removeMedia);
            command.mediaIds().stream()
                .map(MediaId::of)
                .forEach(post::addMedia);
        }
        
        // Update target social accounts if provided
        if (command.targetSocialAccountIds() != null) {
            // Clear existing targets and add new ones
            post.clearTargetSocialAccounts();
            command.targetSocialAccountIds().stream()
                .map(SocialAccountId::of)
                .forEach(post::addTargetSocialAccount);
        }
        
        // Update scheduling if provided
        if (command.scheduledFor() != null) {
            post.scheduleFor(command.scheduledFor());
        }
        
        // Update tags if provided
        if (command.tags() != null) {
            post.updateTags(command.tags());
        }
        
        // Update pinned status if provided
        if (command.isPinned() != null) {
            if (command.isPinned() && !post.isPinned() && post.isPublished()) {
                post.pin();
            } else if (!command.isPinned() && post.isPinned()) {
                post.unpin();
            }
        }
        
        // Save updated post
        Post updatedPost = postRepository.save(post);
        
        // Return DTO
        return mapToDto(updatedPost);
    }
    
    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("")
            .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();
    }
}

