package com.social.media.infrastructure.persistence.mapper;

import com.social.media.domain.content.aggregate.Post;
import com.social.media.domain.content.valueobject.*;
import com.social.media.domain.company.valueobject.CompanyId;
import com.social.media.domain.user.valueobject.UserId;
import com.social.media.domain.socialaccount.valueobject.SocialAccountId;
import com.social.media.infrastructure.persistence.entity.PostEntity;
import com.social.media.infrastructure.persistence.entity.PostStatusEntity;
import com.social.media.infrastructure.persistence.entity.PostTypeEntity;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Mapper between Post domain object and PostEntity
 */
@Component
public class PostEntityMapper {
    
    public PostEntity toEntity(Post post) {
        if (post == null) {
            return null;
        }
        
        return new PostEntity(
            post.getId().value(),
            post.getCompanyId().value(),
            post.getAuthorId().value(),
            post.getCategoryId() != null ? post.getCategoryId().value() : null,
            post.getContent().text(),
            mapToEntityPostType(post.getPostType()),
            mapToEntityStatus(post.getStatus()),
            post.getMediaIds().stream().map(MediaId::value).toList(),
            post.getTargetSocialAccounts().stream().map(SocialAccountId::value).collect(Collectors.toSet()),
            post.getScheduledFor(),
            post.getPublishedAt(),
            post.getTags(),
            post.isPinned(),
            post.getViewCount(),
            post.getLikeCount(),
            post.getShareCount(),
            post.getCommentCount()
        );
    }
    
    public Post toDomain(PostEntity entity) {
        if (entity == null) {
            return null;
        }
        
        List<MediaId> mediaIds = entity.getMediaIds().stream()
            .map(MediaId::new)
            .toList();
            
        Set<SocialAccountId> targetAccounts = entity.getTargetSocialAccountIds().stream()
            .map(SocialAccountId::new)
            .collect(Collectors.toSet());
        
        return new Post(
            new PostId(entity.getId()),
            new CompanyId(entity.getCompanyId()),
            new UserId(entity.getAuthorId()),
            entity.getCategoryId() != null ? new ContentCategoryId(entity.getCategoryId()) : null,
            PostContent.of(entity.getContentText() != null ? entity.getContentText() : ""),
            mapToDomainPostType(entity.getPostType()),
            mapToDomainStatus(entity.getStatus()),
            mediaIds,
            targetAccounts,
            entity.getScheduledFor(),
            entity.getPublishedAt(),
            entity.getCreatedAt(),
            entity.getUpdatedAt(),
            entity.getTags(),
            entity.isPinned(),
            entity.getViewCount(),
            entity.getLikeCount(),
            entity.getShareCount(),
            entity.getCommentCount()
        );
    }
    
    private PostStatusEntity mapToEntityStatus(PostStatus status) {
        return switch (status) {
            case DRAFT -> PostStatusEntity.DRAFT;
            case SCHEDULED -> PostStatusEntity.SCHEDULED;
            case PUBLISHING -> PostStatusEntity.PUBLISHING;
            case PUBLISHED -> PostStatusEntity.PUBLISHED;
            case ERROR -> PostStatusEntity.ERROR;
            case FAILED -> PostStatusEntity.FAILED;
            case ARCHIVED -> PostStatusEntity.ARCHIVED;
            case CANCELLED -> PostStatusEntity.CANCELLED;
        };
    }
    
    private PostStatus mapToDomainStatus(PostStatusEntity entityStatus) {
        return switch (entityStatus) {
            case DRAFT -> PostStatus.DRAFT;
            case SCHEDULED -> PostStatus.SCHEDULED;
            case PUBLISHING -> PostStatus.PUBLISHING;
            case PUBLISHED -> PostStatus.PUBLISHED;
            case ERROR -> PostStatus.ERROR;
            case FAILED -> PostStatus.FAILED;
            case ARCHIVED -> PostStatus.ARCHIVED;
            case CANCELLED -> PostStatus.CANCELLED;
        };
    }
    
    private PostTypeEntity mapToEntityPostType(PostType postType) {
        return switch (postType) {
            case FEED -> PostTypeEntity.FEED;
            case STORY -> PostTypeEntity.STORY;
            case REEL -> PostTypeEntity.REEL;
            case VIDEO -> PostTypeEntity.VIDEO;
            case CAROUSEL -> PostTypeEntity.CAROUSEL;
            case LIVE -> PostTypeEntity.LIVE;
        };
    }
    
    private PostType mapToDomainPostType(PostTypeEntity entityType) {
        return switch (entityType) {
            case FEED -> PostType.FEED;
            case STORY -> PostType.STORY;
            case REEL -> PostType.REEL;
            case VIDEO -> PostType.VIDEO;
            case CAROUSEL -> PostType.CAROUSEL;
            case LIVE -> PostType.LIVE;
        };
    }
}
