package com.social.media.domain.company.valueobjects;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Objects;

/**
 * Value object representing a company plan.
 * 
 * Defines the subscription tier and capabilities of a company.
 * 
 * @author Social Media Manager Team
 * @since 2.0.0
 */
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CompanyPlan {
    
    public enum PlanType {
        BASIC("Basic", 1, 3, 50),
        PROFESSIONAL("Professional", 3, 10, 200),
        ENTERPRISE("Enterprise", 10, 50, 1000);
        
        private final String displayName;
        private final int maxUsers;
        private final int maxSocialAccounts;
        private final int maxPostsPerMonth;
        
        PlanType(String displayName, int maxUsers, int maxSocialAccounts, int maxPostsPerMonth) {
            this.displayName = displayName;
            this.maxUsers = maxUsers;
            this.maxSocialAccounts = maxSocialAccounts;
            this.maxPostsPerMonth = maxPostsPerMonth;
        }
        
        public String getDisplayName() { return displayName; }
        public int getMaxUsers() { return maxUsers; }
        public int getMaxSocialAccounts() { return maxSocialAccounts; }
        public int getMaxPostsPerMonth() { return maxPostsPerMonth; }
    }
    
    @Column(name = "plan_type", nullable = false, length = 20)
    private PlanType planType;
    
    @Column(name = "custom_max_users")
    private Integer customMaxUsers;
    
    // Explicit getter methods
    public PlanType getPlanType() {
        return planType;
    }
    
    @Column(name = "custom_max_social_accounts")
    private Integer customMaxSocialAccounts;
    
    @Column(name = "custom_max_posts_per_month")
    private Integer customMaxPostsPerMonth;
    
    private CompanyPlan(PlanType planType) {
        this.planType = Objects.requireNonNull(planType, "Plan type cannot be null");
    }
    
    private CompanyPlan(PlanType planType, Integer customMaxUsers, 
                       Integer customMaxSocialAccounts, Integer customMaxPostsPerMonth) {
        this.planType = Objects.requireNonNull(planType, "Plan type cannot be null");
        this.customMaxUsers = customMaxUsers;
        this.customMaxSocialAccounts = customMaxSocialAccounts;
        this.customMaxPostsPerMonth = customMaxPostsPerMonth;
    }
    
    /**
     * Create a standard plan
     */
    public static CompanyPlan of(PlanType planType) {
        return new CompanyPlan(planType);
    }
    
    /**
     * Create a custom plan with specific limits
     */
    public static CompanyPlan custom(PlanType basePlanType, Integer maxUsers, 
                                   Integer maxSocialAccounts, Integer maxPostsPerMonth) {
        return new CompanyPlan(basePlanType, maxUsers, maxSocialAccounts, maxPostsPerMonth);
    }
    
    /**
     * Get effective maximum users
     */
    public int getEffectiveMaxUsers() {
        return customMaxUsers != null ? customMaxUsers : planType.getMaxUsers();
    }
    
    /**
     * Get effective maximum social accounts
     */
    public int getEffectiveMaxSocialAccounts() {
        return customMaxSocialAccounts != null ? customMaxSocialAccounts : planType.getMaxSocialAccounts();
    }
    
    /**
     * Get effective maximum posts per month
     */
    public int getEffectiveMaxPostsPerMonth() {
        return customMaxPostsPerMonth != null ? customMaxPostsPerMonth : planType.getMaxPostsPerMonth();
    }
    
    /**
     * Check if plan allows more users
     */
    public boolean canAddUser(int currentUserCount) {
        return currentUserCount < getEffectiveMaxUsers();
    }
    
    /**
     * Check if plan allows more social accounts
     */
    public boolean canAddSocialAccount(int currentAccountCount) {
        return currentAccountCount < getEffectiveMaxSocialAccounts();
    }
    
    /**
     * Check if plan allows more posts this month
     */
    public boolean canCreatePost(int currentMonthPosts) {
        return currentMonthPosts < getEffectiveMaxPostsPerMonth();
    }
    
    /**
     * Check if this is a custom plan
     */
    public boolean isCustom() {
        return customMaxUsers != null || customMaxSocialAccounts != null || customMaxPostsPerMonth != null;
    }
    
    /**
     * Upgrade to a higher plan
     */
    public CompanyPlan upgradeTo(PlanType newPlanType) {
        if (newPlanType.ordinal() <= planType.ordinal()) {
            throw new IllegalArgumentException("Cannot downgrade plan");
        }
        
        if (isCustom()) {
            // Preserve custom limits if they're higher than new plan defaults
            Integer newMaxUsers = customMaxUsers != null && customMaxUsers > newPlanType.getMaxUsers() 
                ? customMaxUsers : null;
            Integer newMaxSocialAccounts = customMaxSocialAccounts != null && customMaxSocialAccounts > newPlanType.getMaxSocialAccounts() 
                ? customMaxSocialAccounts : null;
            Integer newMaxPostsPerMonth = customMaxPostsPerMonth != null && customMaxPostsPerMonth > newPlanType.getMaxPostsPerMonth() 
                ? customMaxPostsPerMonth : null;
                
            return new CompanyPlan(newPlanType, newMaxUsers, newMaxSocialAccounts, newMaxPostsPerMonth);
        }
        
        return new CompanyPlan(newPlanType);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        CompanyPlan that = (CompanyPlan) obj;
        return planType == that.planType &&
               Objects.equals(customMaxUsers, that.customMaxUsers) &&
               Objects.equals(customMaxSocialAccounts, that.customMaxSocialAccounts) &&
               Objects.equals(customMaxPostsPerMonth, that.customMaxPostsPerMonth);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(planType, customMaxUsers, customMaxSocialAccounts, customMaxPostsPerMonth);
    }
    
    @Override
    public String toString() {
        if (isCustom()) {
            return String.format("%s (Custom: %d users, %d accounts, %d posts/month)", 
                planType.getDisplayName(), 
                getEffectiveMaxUsers(), 
                getEffectiveMaxSocialAccounts(), 
                getEffectiveMaxPostsPerMonth());
        }
        return planType.getDisplayName();
    }
}
