package com.social.media.domain.campaign.aggregate;

import com.social.media.domain.campaign.valueobject.*;
import com.social.media.domain.user.valueobject.UserId;
import com.social.media.domain.socialaccount.valueobject.SocialAccountId;
import com.social.media.domain.bot.valueobject.BotId;
import com.social.media.domain.shared.exception.BusinessRuleViolationException;
import com.social.media.domain.shared.kernel.AggregateRoot;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;

/**
 * Campaign aggregate representing a set of instructions for specific interactions based on a list
 * Core entity for managing automated social media campaigns
 */
public class Campaign extends AggregateRoot<CampaignId> {
    
    private String name;
    private String description;
    private UserId userId;
    private SocialAccountId accountNetworkId;
    private BotId botId;
    private Long scriptId;
    private Long listId; // target_account_id
    private CampaignInteractionType typeInteration;
    private CampaignInteractionStatus statusInteration;
    private LocalDate dateInteration;
    private LocalTime hourInteration;
    private String textInteration;
    private LocalDate dateStart;
    private LocalTime hourStart;
    private LocalDate dateEnd;
    private LocalTime hourEnd;
    
    // Audit fields
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    private Long version;
    
    // Constructor for new campaign
    public Campaign(String name, String description, UserId userId, 
                   SocialAccountId accountNetworkId, BotId botId, 
                   CampaignInteractionType typeInteration) {
        super(CampaignId.of(System.currentTimeMillis())); // Temporary ID generation
        LocalDateTime now = LocalDateTime.now();
        
        this.name = validateName(name);
        this.description = validateDescription(description);
        this.userId = validateUserId(userId);
        this.accountNetworkId = validateAccountNetworkId(accountNetworkId);
        this.botId = validateBotId(botId);
        this.typeInteration = validateTypeInteration(typeInteration);
        this.statusInteration = CampaignInteractionStatus.WAIT; // Default status
        
        this.createdAt = now;
        this.updatedAt = now;
        this.version = 0L;
    }
    
    // Constructor for existing campaign
    public Campaign(CampaignId id, String name, String description, UserId userId,
                   SocialAccountId accountNetworkId, BotId botId, Long scriptId, Long listId,
                   CampaignInteractionType typeInteration, CampaignInteractionStatus statusInteration,
                   LocalDate dateInteration, LocalTime hourInteration, String textInteration,
                   LocalDate dateStart, LocalTime hourStart, LocalDate dateEnd, LocalTime hourEnd,
                   LocalDateTime createdAt, LocalDateTime updatedAt, Long version) {
        super(id);
        this.name = name;
        this.description = description;
        this.userId = userId;
        this.accountNetworkId = accountNetworkId;
        this.botId = botId;
        this.scriptId = scriptId;
        this.listId = listId;
        this.typeInteration = typeInteration;
        this.statusInteration = statusInteration;
        this.dateInteration = dateInteration;
        this.hourInteration = hourInteration;
        this.textInteration = textInteration;
        this.dateStart = dateStart;
        this.hourStart = hourStart;
        this.dateEnd = dateEnd;
        this.hourEnd = hourEnd;
        this.createdAt = createdAt;
        this.updatedAt = updatedAt;
        this.version = version;
    }
    
    // Business methods
    public void updateBasicInfo(String name, String description) {
        if (!canBeModified()) {
            throw new BusinessRuleViolationException("Campaign cannot be modified in current status: " + statusInteration);
        }
        
        this.name = validateName(name);
        this.description = validateDescription(description);
        this.updatedAt = LocalDateTime.now();
    }
    
    public void updateSchedule(LocalDate dateInteration, LocalTime hourInteration, 
                             LocalDate dateStart, LocalTime hourStart,
                             LocalDate dateEnd, LocalTime hourEnd) {
        if (!canBeModified()) {
            throw new BusinessRuleViolationException("Campaign cannot be modified in current status: " + statusInteration);
        }
        
        validateScheduleDates(dateStart, dateEnd);
        
        this.dateInteration = dateInteration;
        this.hourInteration = hourInteration;
        this.dateStart = dateStart;
        this.hourStart = hourStart;
        this.dateEnd = dateEnd;
        this.hourEnd = hourEnd;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void updateInteractionDetails(String textInteration, Long scriptId, Long listId) {
        if (!canBeModified()) {
            throw new BusinessRuleViolationException("Campaign cannot be modified in current status: " + statusInteration);
        }
        
        this.textInteration = textInteration;
        this.scriptId = scriptId;
        this.listId = listId;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void updateStatus(CampaignInteractionStatus newStatus) {
        if (!statusInteration.canTransitionTo(newStatus)) {
            throw new BusinessRuleViolationException(
                String.format("Cannot transition from %s to %s", statusInteration, newStatus));
        }
        
        this.statusInteration = newStatus;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void start() {
        updateStatus(CampaignInteractionStatus.RUNNING);
    }
    
    public void pause() {
        updateStatus(CampaignInteractionStatus.PAUSED);
    }
    
    public void complete() {
        updateStatus(CampaignInteractionStatus.COMPLETED);
    }
    
    public void cancel() {
        updateStatus(CampaignInteractionStatus.CANCELLED);
    }
    
    public void resume() {
        if (statusInteration != CampaignInteractionStatus.PAUSED) {
            throw new BusinessRuleViolationException("Can only resume paused campaigns");
        }
        updateStatus(CampaignInteractionStatus.RUNNING);
    }
    
    // Query methods
    public boolean belongsToUser(UserId userId) {
        return this.userId.equals(userId);
    }
    
    public boolean isActive() {
        return statusInteration.isActive();
    }
    
    public boolean isFinished() {
        return statusInteration.isFinished();
    }
    
    public boolean canBeModified() {
        return statusInteration.canBeModified();
    }
    
    public boolean isScheduledFor(LocalDate date) {
        return dateInteration != null && dateInteration.equals(date);
    }
    
    public boolean isInExecutionPeriod(LocalDateTime dateTime) {
        if (dateStart == null || dateEnd == null) {
            return false;
        }
        
        LocalDateTime startDateTime = LocalDateTime.of(dateStart, hourStart != null ? hourStart : LocalTime.MIN);
        LocalDateTime endDateTime = LocalDateTime.of(dateEnd, hourEnd != null ? hourEnd : LocalTime.MAX);
        
        return dateTime.isAfter(startDateTime) && dateTime.isBefore(endDateTime);
    }
    
    public boolean usesBot(BotId botId) {
        return this.botId != null && this.botId.equals(botId);
    }
    
    public boolean usesAccount(SocialAccountId accountId) {
        return this.accountNetworkId != null && this.accountNetworkId.equals(accountId);
    }
    
    public boolean isOfType(CampaignInteractionType type) {
        return this.typeInteration == type;
    }
    
    // Validation methods
    private String validateName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new BusinessRuleViolationException("Campaign name is required");
        }
        if (name.length() > 50) {
            throw new BusinessRuleViolationException("Campaign name must not exceed 50 characters");
        }
        return name.trim();
    }
    
    private String validateDescription(String description) {
        if (description != null && description.length() > 255) {
            throw new BusinessRuleViolationException("Campaign description must not exceed 255 characters");
        }
        return description != null ? description.trim() : null;
    }
    
    private UserId validateUserId(UserId userId) {
        if (userId == null) {
            throw new BusinessRuleViolationException("User ID is required");
        }
        return userId;
    }
    
    private SocialAccountId validateAccountNetworkId(SocialAccountId accountNetworkId) {
        if (accountNetworkId == null) {
            throw new BusinessRuleViolationException("Account Network ID is required");
        }
        return accountNetworkId;
    }
    
    private BotId validateBotId(BotId botId) {
        if (botId == null) {
            throw new BusinessRuleViolationException("Bot ID is required");
        }
        return botId;
    }
    
    private CampaignInteractionType validateTypeInteration(CampaignInteractionType typeInteration) {
        if (typeInteration == null) {
            throw new BusinessRuleViolationException("Interaction type is required");
        }
        return typeInteration;
    }
    
    private void validateScheduleDates(LocalDate dateStart, LocalDate dateEnd) {
        if (dateStart != null && dateEnd != null && dateStart.isAfter(dateEnd)) {
            throw new BusinessRuleViolationException("Start date cannot be after end date");
        }
    }
    
    // Getters
    public String getName() { return name; }
    public String getDescription() { return description; }
    public UserId getUserId() { return userId; }
    public SocialAccountId getAccountNetworkId() { return accountNetworkId; }
    public BotId getBotId() { return botId; }
    public Long getScriptId() { return scriptId; }
    public Long getListId() { return listId; }
    public CampaignInteractionType getTypeInteration() { return typeInteration; }
    public CampaignInteractionStatus getStatusInteration() { return statusInteration; }
    public LocalDate getDateInteration() { return dateInteration; }
    public LocalTime getHourInteration() { return hourInteration; }
    public String getTextInteration() { return textInteration; }
    public LocalDate getDateStart() { return dateStart; }
    public LocalTime getHourStart() { return hourStart; }
    public LocalDate getDateEnd() { return dateEnd; }
    public LocalTime getHourEnd() { return hourEnd; }
    public LocalDateTime getCreatedAt() { return createdAt; }
    public LocalDateTime getUpdatedAt() { return updatedAt; }
    public Long getVersion() { return version; }
}
