package com.social.media.application.bot.handler;

import com.social.media.application.bot.command.UpdateBotCommand;
import com.social.media.application.bot.dto.BotResponseDto;
import com.social.media.domain.bot.aggregate.Bot;
import com.social.media.domain.bot.repository.BotRepository;
import com.social.media.domain.bot.valueobject.UserListId;
import com.social.media.domain.socialaccount.valueobject.SocialAccountId;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class UpdateBotCommandHandler {
    
    private final BotRepository botRepository;
    
    public UpdateBotCommandHandler(BotRepository botRepository) {
        this.botRepository = botRepository;
    }
    
    public BotResponseDto handle(UpdateBotCommand command) {
        // Find existing bot
        Bot bot = botRepository.findById(command.botId())
            .orElseThrow(() -> new RuntimeException(
                "Bot not found: " + command.botId()
            ));
        
        // Update basic info if provided
        if (command.name() != null || command.description() != null) {
            bot.updateInfo(
                command.name() != null ? command.name() : bot.getName(),
                command.description() != null ? command.description() : bot.getDescription()
            );
        }
        
        // Update configuration if provided
        if (command.configuration() != null) {
            bot.updateConfiguration(command.configuration());
        }
        
        // Update target social accounts if provided
        if (command.targetSocialAccountIds() != null) {
            bot.clearTargetSocialAccounts();
            command.targetSocialAccountIds().stream()
                .map(SocialAccountId::of)
                .forEach(bot::addTargetSocialAccount);
        }
        
        // Update target user lists if provided
        if (command.targetUserListIds() != null) {
            bot.clearTargetUserLists();
            command.targetUserListIds().stream()
                .map(UserListId::of)
                .forEach(bot::addTargetUserList);
        }
        
        // Save updated bot
        Bot updatedBot = botRepository.save(bot);
        
        // Return DTO
        return mapToDto(updatedBot);
    }
    
    private BotResponseDto mapToDto(Bot bot) {
        return BotResponseDto.builder()
            .id(bot.getId().value().toString())
            .companyId(bot.getCompanyId().value().toString())
            .createdBy(bot.getCreatedBy().value().toString())
            .name(bot.getName())
            .description(bot.getDescription())
            .botType(bot.getBotType().name())
            .status(bot.getStatus().name())
            .configuration(bot.getConfiguration() != null ? Map.of("hasConfig", true) : Collections.emptyMap())
            .targetSocialAccountIds(bot.getTargetSocialAccounts().stream()
                .map(id -> id.value().toString())
                .collect(Collectors.toSet()))
            .targetUserListIds(bot.getTargetUserLists().stream()
                .map(id -> id.value().toString())
                .collect(Collectors.toSet()))
            .lastExecutionAt(bot.getLastExecutionAt())
            .nextExecutionAt(bot.getNextExecutionAt())
            .totalExecutions(bot.getTotalExecutions())
            .successfulExecutions(bot.getSuccessfulExecutions())
            .failedExecutions(bot.getFailedExecutions())
            .successRate(bot.getSuccessRate())
            .failureRate(bot.getFailureRate())
            .createdAt(bot.getCreatedAt())
            .updatedAt(bot.getUpdatedAt())
            .build();
    }
}

