package com.social.media.domain.content;

import com.social.media.domain.shared.BaseEntity;

import java.time.LocalDateTime;
import java.util.UUID;
import java.util.Objects;

/**
 * Content Category entity representing classification for posts and media.
 * Provides organizational structure for content management.
 */
public class ContentCategory extends BaseEntity {
    
    private UUID companyId;
    private String name;
    private String description;
    private String color;
    private String icon;
    private UUID parentCategoryId;
    private Integer sortOrder;
    private boolean isActive;
    private boolean isDefault;
    private String tags;
    private Integer postCount; // Cached count of posts in this category
    private LocalDateTime lastUsedAt;
    
    // Default constructor for JPA
    protected ContentCategory() {
        super();
    }
    
    public ContentCategory(
            UUID companyId,
            String name,
            String description,
            String color) {
        
        super();
        this.companyId = validateCompanyId(companyId);
        this.name = validateName(name);
        this.description = description != null ? description.trim() : null;
        this.color = validateColor(color);
        this.isActive = true;
        this.isDefault = false;
        this.postCount = 0;
        this.sortOrder = 0;
    }
    
    // Validation methods
    private UUID validateCompanyId(UUID companyId) {
        if (companyId == null) {
            throw new IllegalArgumentException("Company ID cannot be null");
        }
        return companyId;
    }
    
    private String validateName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("Category name cannot be null or empty");
        }
        if (name.length() > 100) {
            throw new IllegalArgumentException("Category name cannot exceed 100 characters");
        }
        return name.trim();
    }
    
    private String validateColor(String color) {
        if (color != null) {
            String trimmedColor = color.trim();
            if (!trimmedColor.matches("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")) {
                throw new IllegalArgumentException("Color must be a valid hex color code (e.g., #FF0000)");
            }
            return trimmedColor.toUpperCase();
        }
        return "#3498DB"; // Default blue color
    }
    
    // Factory methods
    
    /**
     * Creates a default "General" category.
     */
    public static ContentCategory createGeneral(UUID companyId) {
        ContentCategory category = new ContentCategory(
            companyId,
            "General",
            "General content category",
            "#3498DB"
        );
        category.isDefault = true;
        category.icon = "folder";
        return category;
    }
    
    /**
     * Creates a marketing category.
     */
    public static ContentCategory createMarketing(UUID companyId) {
        return new ContentCategory(
            companyId,
            "Marketing",
            "Marketing and promotional content",
            "#E74C3C"
        );
    }
    
    /**
     * Creates a news category.
     */
    public static ContentCategory createNews(UUID companyId) {
        return new ContentCategory(
            companyId,
            "News",
            "News and announcements",
            "#F39C12"
        );
    }
    
    /**
     * Creates an educational category.
     */
    public static ContentCategory createEducational(UUID companyId) {
        return new ContentCategory(
            companyId,
            "Educational",
            "Educational and informational content",
            "#2ECC71"
        );
    }
    
    /**
     * Creates an entertainment category.
     */
    public static ContentCategory createEntertainment(UUID companyId) {
        return new ContentCategory(
            companyId,
            "Entertainment",
            "Entertainment and lifestyle content",
            "#9B59B6"
        );
    }
    
    // Business methods
    
    /**
     * Updates the category information.
     */
    public void updateInfo(String name, String description, String color, String icon) {
        boolean changed = false;
        
        if (name != null) {
            String validatedName = validateName(name);
            if (!this.name.equals(validatedName)) {
                this.name = validatedName;
                changed = true;
            }
        }
        
        if (description != null) {
            if (description.length() > 500) {
                throw new IllegalArgumentException("Description cannot exceed 500 characters");
            }
            String newDescription = description.trim();
            if (!Objects.equals(this.description, newDescription)) {
                this.description = newDescription.isEmpty() ? null : newDescription;
                changed = true;
            }
        }
        
        if (color != null) {
            String validatedColor = validateColor(color);
            if (!this.color.equals(validatedColor)) {
                this.color = validatedColor;
                changed = true;
            }
        }
        
        if (icon != null) {
            if (icon.length() > 50) {
                throw new IllegalArgumentException("Icon cannot exceed 50 characters");
            }
            String newIcon = icon.trim();
            if (!Objects.equals(this.icon, newIcon)) {
                this.icon = newIcon.isEmpty() ? null : newIcon;
                changed = true;
            }
        }
        
        if (changed) {
            this.markAsModified();
        }
    }
    
    /**
     * Sets the parent category for hierarchical organization.
     */
    public void setParentCategory(UUID parentCategoryId) {
        if (parentCategoryId != null && parentCategoryId.equals(this.getId())) {
            throw new IllegalArgumentException("Category cannot be its own parent");
        }
        
        if (!Objects.equals(this.parentCategoryId, parentCategoryId)) {
            this.parentCategoryId = parentCategoryId;
            this.markAsModified();
        }
    }
    
    /**
     * Updates the sort order.
     */
    public void updateSortOrder(Integer sortOrder) {
        if (sortOrder != null && sortOrder < 0) {
            throw new IllegalArgumentException("Sort order cannot be negative");
        }
        
        if (!Objects.equals(this.sortOrder, sortOrder)) {
            this.sortOrder = sortOrder;
            this.markAsModified();
        }
    }
    
    /**
     * Activates the category.
     */
    public void activate() {
        if (!isActive) {
            this.isActive = true;
            this.markAsModified();
        }
    }
    
    /**
     * Deactivates the category.
     */
    public void deactivate() {
        if (isDefault) {
            throw new IllegalStateException("Cannot deactivate default category");
        }
        
        if (isActive) {
            this.isActive = false;
            this.markAsModified();
        }
    }
    
    /**
     * Marks as default category.
     */
    public void markAsDefault() {
        if (!isDefault) {
            this.isDefault = true;
            this.isActive = true; // Default categories must be active
            this.markAsModified();
        }
    }
    
    /**
     * Removes default status.
     */
    public void removeDefaultStatus() {
        if (isDefault) {
            this.isDefault = false;
            this.markAsModified();
        }
    }
    
    /**
     * Updates the tags.
     */
    public void updateTags(String tags) {
        if (tags != null && tags.length() > 500) {
            throw new IllegalArgumentException("Tags cannot exceed 500 characters");
        }
        
        String newTags = tags != null ? tags.trim() : null;
        if (!Objects.equals(this.tags, newTags)) {
            this.tags = newTags;
            this.markAsModified();
        }
    }
    
    /**
     * Increments the post count when a post is added to this category.
     */
    public void incrementPostCount() {
        this.postCount = (this.postCount != null ? this.postCount : 0) + 1;
        this.lastUsedAt = LocalDateTime.now();
        this.markAsModified();
    }
    
    /**
     * Decrements the post count when a post is removed from this category.
     */
    public void decrementPostCount() {
        this.postCount = Math.max(0, (this.postCount != null ? this.postCount : 0) - 1);
        this.markAsModified();
    }
    
    /**
     * Updates the post count directly.
     */
    public void updatePostCount(Integer postCount) {
        if (postCount != null && postCount < 0) {
            throw new IllegalArgumentException("Post count cannot be negative");
        }
        
        if (!Objects.equals(this.postCount, postCount)) {
            this.postCount = postCount;
            this.markAsModified();
        }
    }
    
    /**
     * Records usage of this category.
     */
    public void recordUsage() {
        this.lastUsedAt = LocalDateTime.now();
        this.markAsModified();
    }
    
    // Query methods
    
    /**
     * Checks if this is a root category (no parent).
     */
    public boolean isRootCategory() {
        return parentCategoryId == null;
    }
    
    /**
     * Checks if this is a subcategory.
     */
    public boolean isSubcategory() {
        return parentCategoryId != null;
    }
    
    /**
     * Checks if the category has been used recently.
     */
    public boolean isRecentlyUsed(int days) {
        return lastUsedAt != null && 
               lastUsedAt.isAfter(LocalDateTime.now().minusDays(days));
    }
    
    /**
     * Checks if the category is popular (has many posts).
     */
    public boolean isPopular(int threshold) {
        return postCount != null && postCount >= threshold;
    }
    
    /**
     * Gets a display-friendly name with hierarchy.
     */
    public String getHierarchicalName() {
        // This would typically be resolved by the application service
        // that has access to the parent category data
        return name;
    }
    
    /**
     * Gets the category path for breadcrumbs.
     */
    public String getCategoryPath() {
        // This would be built by the application service
        return name;
    }
    
    // Getters
    public UUID getCompanyId() { return companyId; }
    public String getName() { return name; }
    public String getDescription() { return description; }
    public String getColor() { return color; }
    public String getIcon() { return icon; }
    public UUID getParentCategoryId() { return parentCategoryId; }
    public Integer getSortOrder() { return sortOrder; }
    public boolean isActive() { return isActive; }
    public boolean isDefault() { return isDefault; }
    public String getTags() { return tags; }
    public Integer getPostCount() { return postCount; }
    public LocalDateTime getLastUsedAt() { return lastUsedAt; }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        ContentCategory that = (ContentCategory) o;
        return Objects.equals(companyId, that.companyId) &&
               Objects.equals(name, that.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), companyId, name);
    }
    
    @Override
    public String toString() {
        return "ContentCategory{" +
               "id=" + getId() +
               ", companyId=" + companyId +
               ", name='" + name + '\'' +
               ", color='" + color + '\'' +
               ", isActive=" + isActive +
               ", isDefault=" + isDefault +
               ", postCount=" + postCount +
               '}';
    }
}
