package com.social.media.domain.company.aggregate;

import java.time.LocalDateTime;
import java.util.Objects;

import com.social.media.domain.company.valueobject.Address;
import com.social.media.domain.company.valueobject.Cnpj;
import com.social.media.domain.company.valueobject.CompanyId;
import com.social.media.domain.company.valueobject.CompanyPlan;
import com.social.media.domain.company.valueobject.CompanyStatus;
import com.social.media.domain.shared.valueobject.Email;
import com.social.media.domain.shared.valueobject.Phone;

/**
 * Company Aggregate Root
 * Represents a client company in the social media management system
 */
public class Company {
    
    private CompanyId id;
    private String name;
    private Cnpj cnpj;
    private String stateRegistration;
    private Phone phone;
    private Email email;
    private Address address;
    private String logoUrl;
    private String website;
    private String activitySector;
    private CompanyPlan activePlan;
    private Integer socialAccountsLimit;
    private Integer monthlyPostsLimit;
    private LocalDateTime registrationDate;
    private LocalDateTime expirationDate;
    private CompanyStatus status;
    private boolean deleted;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    
    // Private constructor for builder pattern
    private Company() {}
    
    /**
     * Creates a new company (factory method)
     */
    public static Company create(String name, Email email, Cnpj cnpj, Phone phone, 
                               String website, String activitySector, CompanyPlan plan, Address address) {
        Company company = new Company();
        company.name = validateName(name);
        company.email = Objects.requireNonNull(email, "Email cannot be null");
        company.cnpj = cnpj;
        company.activePlan = Objects.requireNonNull(plan, "Plan cannot be null");
        company.phone = phone;
        company.website = website;
        company.activitySector = activitySector;
        company.address = address;
        company.status = CompanyStatus.ATIVO;
        company.registrationDate = LocalDateTime.now();
        company.socialAccountsLimit = plan.getAccountLimit();
        company.monthlyPostsLimit = plan.getMonthlyPostLimit();
        company.deleted = false;
        company.createdAt = LocalDateTime.now();
        company.updatedAt = LocalDateTime.now();
        
        return company;
    }
    
    /**
     * Reconstructs company from persistence (for repository)
     */
    public static Company reconstruct(CompanyId id, String name, Cnpj cnpj, 
                                    String stateRegistration, Phone phone, Email email,
                                    Address address, String logoUrl, String website, 
                                    String activitySector, CompanyPlan activePlan,
                                    Integer socialAccountsLimit, Integer monthlyPostsLimit,
                                    LocalDateTime registrationDate, LocalDateTime expirationDate,
                                    CompanyStatus status, boolean deleted,
                                    LocalDateTime createdAt, LocalDateTime updatedAt) {
        Company company = new Company();
        company.id = id;
        company.name = name;
        company.cnpj = cnpj;
        company.stateRegistration = stateRegistration;
        company.phone = phone;
        company.email = email;
        company.address = address;
        company.logoUrl = logoUrl;
        company.website = website;
        company.activitySector = activitySector;
        company.activePlan = activePlan;
        company.socialAccountsLimit = socialAccountsLimit;
        company.monthlyPostsLimit = monthlyPostsLimit;
        company.registrationDate = registrationDate;
        company.expirationDate = expirationDate;
        company.status = status;
        company.deleted = deleted;
        company.createdAt = createdAt;
        company.updatedAt = updatedAt;
        
        return company;
    }
    
    // Business Methods
    
    public void activate() {
        if (deleted) {
            throw new CompanyDomainException("Cannot activate deleted company");
        }
        this.status = CompanyStatus.ATIVO;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void suspend() {
        if (deleted) {
            throw new CompanyDomainException("Cannot suspend deleted company");
        }
        this.status = CompanyStatus.SUSPENSO;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void cancel() {
        this.status = CompanyStatus.CANCELADO;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void upgradePlan(CompanyPlan newPlan) {
        if (!status.isActive()) {
            throw new CompanyDomainException("Cannot upgrade plan for inactive company");
        }
        
        this.activePlan = newPlan;
        this.socialAccountsLimit = newPlan.getAccountLimit();
        this.monthlyPostsLimit = newPlan.getMonthlyPostLimit();
        this.updatedAt = LocalDateTime.now();
    }
    
    public void updateContactInfo(Phone phone, Email email, String website) {
        if (email != null) {
            this.email = email;
        }
        this.phone = phone;
        this.website = website;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void setAddress(Address address) {
        this.address = address;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void setCnpj(Cnpj cnpj) {
        this.cnpj = cnpj;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void setLogo(String logoUrl) {
        this.logoUrl = logoUrl;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void softDelete() {
        this.deleted = true;
        this.status = CompanyStatus.INATIVO;
        this.updatedAt = LocalDateTime.now();
    }
    
    public boolean canCreateAccount() {
        return status.canCreateAccounts();
    }
    
    public boolean canPublishPost() {
        return status.canPublishPosts();
    }
    
    public boolean hasReachedAccountLimit(int currentAccounts) {
        return socialAccountsLimit != Integer.MAX_VALUE && currentAccounts >= socialAccountsLimit;
    }
    
    public boolean hasReachedPostLimit(int currentMonthlyPosts) {
        return monthlyPostsLimit != Integer.MAX_VALUE && currentMonthlyPosts >= monthlyPostsLimit;
    }
    
    // Validation methods
    
    private static String validateName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new CompanyDomainException("Company name cannot be null or empty");
        }
        if (name.trim().length() < 2) {
            throw new CompanyDomainException("Company name must have at least 2 characters");
        }
        return name.trim();
    }
    
    // Getters
    
    public CompanyId getId() { return id; }
    public String getName() { return name; }
    public Cnpj getCnpj() { return cnpj; }
    public String getStateRegistration() { return stateRegistration; }
    public Phone getPhone() { return phone; }
    public Email getEmail() { return email; }
    public Address getAddress() { return address; }
    public String getLogoUrl() { return logoUrl; }
    public String getWebsite() { return website; }
    public String getActivitySector() { return activitySector; }
    public CompanyPlan getActivePlan() { return activePlan; }
    public Integer getSocialAccountsLimit() { return socialAccountsLimit; }
    public Integer getMonthlyPostsLimit() { return monthlyPostsLimit; }
    public LocalDateTime getRegistrationDate() { return registrationDate; }
    public LocalDateTime getExpirationDate() { return expirationDate; }
    public CompanyStatus getStatus() { return status; }
    public boolean isDeleted() { return deleted; }
    public LocalDateTime getCreatedAt() { return createdAt; }
    public LocalDateTime getUpdatedAt() { return updatedAt; }
    
    // Setters for reconstruction only
    void setId(CompanyId id) { this.id = id; }
    void setStateRegistration(String stateRegistration) { this.stateRegistration = stateRegistration; }
    void setExpirationDate(LocalDateTime expirationDate) { this.expirationDate = expirationDate; }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Company company = (Company) o;
        return Objects.equals(id, company.id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
    
    @Override
    public String toString() {
        return "Company{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email=" + email +
                ", activePlan=" + activePlan +
                ", status=" + status +
                '}';
    }
    
    /**
     * Domain exception specific to Company aggregate
     */
    public static class CompanyDomainException extends RuntimeException {
        public CompanyDomainException(String message) {
            super(message);
        }
    }
}
