package com.social.media.domain.post.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 post content.
 * 
 * Encapsulates the textual content of a post with validation and formatting.
 * 
 * @author Social Media Manager Team
 * @since 2.0.0
 */
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PostContent {
    
    @Column(name = "content_text", nullable = false, length = 10000)
    private String text;
    
    @Column(name = "content_html", length = 15000)
    private String html;
    
    @Column(name = "content_hashtags", length = 2000)
    private String hashtags;
    
    @Column(name = "content_mentions", length = 1000)
    private String mentions;
    
    @Column(name = "content_links", length = 2000)
    private String links;
    
    @Column(name = "character_count", nullable = false)
    private Integer characterCount;
    
    @Column(name = "word_count", nullable = false)
    private Integer wordCount;
    
    @Column(name = "hashtag_count", nullable = false)
    private Integer hashtagCount = 0;
    
    @Column(name = "mention_count", nullable = false)
    private Integer mentionCount = 0;
    
    @Column(name = "link_count", nullable = false)
    private Integer linkCount = 0;
    
    private PostContent(String text) {
        this.text = Objects.requireNonNull(text, "Post text cannot be null").trim();
        validate();
        analyze();
    }
    
    private PostContent(String text, String html) {
        this.text = Objects.requireNonNull(text, "Post text cannot be null").trim();
        this.html = html != null ? html.trim() : null;
        validate();
        analyze();
    }
    
    /**
     * Create post content from text only
     */
    public static PostContent of(String text) {
        return new PostContent(text);
    }
    
    /**
     * Create post content with both text and HTML
     */
    public static PostContent of(String text, String html) {
        return new PostContent(text, html);
    }
    
    /**
     * Validate content constraints
     */
    private void validate() {
        if (text.isEmpty()) {
            throw new IllegalArgumentException("Post content cannot be empty");
        }
        
        if (text.length() > 10000) {
            throw new IllegalArgumentException("Post content cannot exceed 10,000 characters");
        }
        
        if (html != null && html.length() > 15000) {
            throw new IllegalArgumentException("HTML content cannot exceed 15,000 characters");
        }
    }
    
    /**
     * Analyze content and extract metadata
     */
    private void analyze() {
        this.characterCount = text.length();
        this.wordCount = countWords();
        this.hashtags = extractHashtags();
        this.mentions = extractMentions();
        this.links = extractLinks();
        this.hashtagCount = hashtags != null ? hashtags.split(",").length : 0;
        this.mentionCount = mentions != null ? mentions.split(",").length : 0;
        this.linkCount = links != null ? links.split(",").length : 0;
    }
    
    /**
     * Count words in text
     */
    private int countWords() {
        if (text.isEmpty()) return 0;
        return text.trim().split("\\s+").length;
    }
    
    /**
     * Extract hashtags from text
     */
    private String extractHashtags() {
        var hashtagMatches = text.split("\\s+");
        var hashtags = new StringBuilder();
        
        for (String word : hashtagMatches) {
            if (word.startsWith("#") && word.length() > 1) {
                if (hashtags.length() > 0) {
                    hashtags.append(",");
                }
                hashtags.append(word.substring(1)); // Remove # symbol
            }
        }
        
        return hashtags.length() > 0 ? hashtags.toString() : null;
    }
    
    /**
     * Extract mentions from text
     */
    private String extractMentions() {
        var mentionMatches = text.split("\\s+");
        var mentions = new StringBuilder();
        
        for (String word : mentionMatches) {
            if (word.startsWith("@") && word.length() > 1) {
                if (mentions.length() > 0) {
                    mentions.append(",");
                }
                mentions.append(word.substring(1)); // Remove @ symbol
            }
        }
        
        return mentions.length() > 0 ? mentions.toString() : null;
    }
    
    /**
     * Extract links from text
     */
    private String extractLinks() {
        var linkPattern = java.util.regex.Pattern.compile(
            "https?://[\\w\\-._~:/?#\\[\\]@!$&'()*+,;=]+", 
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        var matcher = linkPattern.matcher(text);
        var links = new StringBuilder();
        
        while (matcher.find()) {
            if (links.length() > 0) {
                links.append(",");
            }
            links.append(matcher.group());
        }
        
        return links.length() > 0 ? links.toString() : null;
    }
    
    /**
     * Check if content fits platform character limit
     */
    public boolean fitsInLimit(int maxCharacters) {
        return characterCount <= maxCharacters;
    }
    
    /**
     * Truncate content to fit platform limit
     */
    public PostContent truncateToLimit(int maxCharacters) {
        if (fitsInLimit(maxCharacters)) {
            return this;
        }
        
        String truncatedText = text.substring(0, maxCharacters - 3) + "...";
        return new PostContent(truncatedText);
    }
    
    /**
     * Get content preview (first 100 characters)
     */
    public String getPreview() {
        return getPreview(100);
    }
    
    /**
     * Get content preview with custom length
     */
    public String getPreview(int maxLength) {
        if (text.length() <= maxLength) {
            return text;
        }
        return text.substring(0, maxLength - 3) + "...";
    }
    
    /**
     * Check if content contains hashtags
     */
    public boolean hasHashtags() {
        return hashtagCount > 0;
    }
    
    /**
     * Check if content contains mentions
     */
    public boolean hasMentions() {
        return mentionCount > 0;
    }
    
    /**
     * Check if content contains links
     */
    public boolean hasLinks() {
        return linkCount > 0;
    }
    
    /**
     * Get hashtags as array
     */
    public String[] getHashtagsArray() {
        return hashtags != null ? hashtags.split(",") : new String[0];
    }
    
    /**
     * Get mentions as array
     */
    public String[] getMentionsArray() {
        return mentions != null ? mentions.split(",") : new String[0];
    }
    
    /**
     * Get links as array
     */
    public String[] getLinksArray() {
        return links != null ? links.split(",") : new String[0];
    }
    
    /**
     * Add hashtag to content
     */
    public PostContent addHashtag(String hashtag) {
        String newText = text + " #" + hashtag.replace("#", "");
        return new PostContent(newText, html);
    }
    
    /**
     * Add mention to content
     */
    public PostContent addMention(String username) {
        String newText = text + " @" + username.replace("@", "");
        return new PostContent(newText, html);
    }
    
    /**
     * Replace text while preserving HTML
     */
    public PostContent replaceText(String newText) {
        return new PostContent(newText, html);
    }
    
    /**
     * Update HTML content
     */
    public PostContent updateHtml(String newHtml) {
        return new PostContent(text, newHtml);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        PostContent that = (PostContent) obj;
        return Objects.equals(text, that.text) &&
               Objects.equals(html, that.html);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(text, html);
    }
    
    @Override
    public String toString() {
        return getPreview();
    }
}
