package com.social.media.domain.campaign.aggregate;

import com.social.media.domain.campaign.valueobject.*;
import com.social.media.domain.shared.exception.BusinessRuleViolationException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * Automation Campaign Aggregate Root
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AutomationCampaign {
    
    private Long id;
    private String campaignCode;
    private Long companyId;
    private Long socialAccountId;
    private String name;
    private String description;
    private CampaignType type;
    private CampaignStatus status;
    private TargetConfiguration targetConfig;
    private ActionConfiguration actionConfig;
    private ScheduleConfiguration scheduleConfig;
    private Integer totalPlannedActions;
    private Integer totalExecutedActions;
    private Integer successfulActions;
    private Integer failedActions;
    private LocalDateTime plannedStartDate;
    private LocalDateTime plannedEndDate;
    private LocalDateTime actualStartDate;
    private LocalDateTime actualEndDate;
    private LocalDateTime lastExecutionDate;
    private Boolean isActive;
    private Boolean autoRestart;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    
    /**
     * Start the campaign
     */
    public void start() {
        if (status != CampaignStatus.DRAFT) {
            throw new BusinessRuleViolationException("Campaign can only be started from DRAFT status");
        }
        this.status = CampaignStatus.ACTIVE;
        this.actualStartDate = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Pause the campaign
     */
    public void pause() {
        if (status != CampaignStatus.ACTIVE) {
            throw new BusinessRuleViolationException("Campaign can only be paused when ACTIVE");
        }
        this.status = CampaignStatus.PAUSED;
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Resume the campaign
     */
    public void resume() {
        if (status != CampaignStatus.PAUSED) {
            throw new BusinessRuleViolationException("Campaign can only be resumed when PAUSED");
        }
        this.status = CampaignStatus.ACTIVE;
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Complete the campaign
     */
    public void complete() {
        if (status != CampaignStatus.ACTIVE && status != CampaignStatus.PAUSED) {
            throw new BusinessRuleViolationException("Campaign can only be completed when ACTIVE or PAUSED");
        }
        this.status = CampaignStatus.COMPLETED;
        this.actualEndDate = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Cancel the campaign
     */
    public void cancel() {
        if (status == CampaignStatus.COMPLETED || status == CampaignStatus.CANCELLED) {
            throw new BusinessRuleViolationException("Campaign cannot be cancelled when " + status);
        }
        this.status = CampaignStatus.CANCELLED;
        this.actualEndDate = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Update execution metrics
     */
    public void updateExecutionMetrics(Integer executed, Integer successful, Integer failed) {
        this.totalExecutedActions = executed;
        this.successfulActions = successful;
        this.failedActions = failed;
        this.lastExecutionDate = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Check if campaign is active
     */
    public boolean isActive() {
        return status == CampaignStatus.ACTIVE && (isActive != null && isActive);
    }
    
    /**
     * Check if campaign can be executed
     */
    public boolean canExecute() {
        return isActive() && 
               (plannedStartDate == null || plannedStartDate.isBefore(LocalDateTime.now())) &&
               (plannedEndDate == null || plannedEndDate.isAfter(LocalDateTime.now()));
    }
    
    /**
     * Get success rate
     */
    public double getSuccessRate() {
        if (totalExecutedActions == null || totalExecutedActions == 0) {
            return 0.0;
        }
        return (double) (successfulActions != null ? successfulActions : 0) / totalExecutedActions * 100;
    }
}
