package com.social.media.application.usecases.post;

import com.social.media.application.ports.out.CompanyRepositoryPort;
import com.social.media.application.ports.out.PostRepositoryPort;
import com.social.media.application.ports.out.UserRepositoryPort;
import com.social.media.domain.company.entities.Company;
import com.social.media.domain.post.entities.Post;
import com.social.media.domain.user.entities.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;

/**
 * Use case for creating a new post.
 * 
 * Handles the business logic for post creation including
 * validation, company limits check, and approval requirements.
 * 
 * @author Social Media Manager Team
 * @since 2.0.0
 */
@Service
@RequiredArgsConstructor
@Transactional
public class CreatePostUseCase {
    
    private final PostRepositoryPort postRepository;
    private final CompanyRepositoryPort companyRepository;
    private final UserRepositoryPort userRepository;
    
    public record CreatePostCommand(
        String userUuid,
        String title,
        String content,
        Post.PostType postType,
        String mediaUrls,
        Post.MediaType mediaType,
        String linkUrl,
        String linkTitle,
        String linkDescription,
        String linkImageUrl,
        Long campaignId,
        Boolean autoPublish,
        Integer priority,
        String tags,
        String notes,
        Instant scheduledFor
    ) {}
    
    public record CreatePostResult(
        String postUuid,
        String title,
        String content,
        Post.PostType postType,
        Post.PostStatus status,
        boolean requiresApproval,
        String createdBy,
        Instant scheduledFor
    ) {}
    
    /**
     * Execute the create post use case
     */
    public CreatePostResult execute(CreatePostCommand command) {
        // Validate command
        validateCreatePostCommand(command);
        
        // Find user
        User user = userRepository.findByUuid(command.userUuid())
            .orElseThrow(() -> new IllegalArgumentException("User not found"));
        
        // Check if user is active
        if (!user.isActive()) {
            throw new IllegalArgumentException("User is not active");
        }
        
        // Check user permissions
        if (!user.canPerformAction("create_posts")) {
            throw new IllegalArgumentException("User does not have permission to create posts");
        }
        
        // Find company
        Company company = companyRepository.findById(user.getCompanyIdAsLong())
            .orElseThrow(() -> new IllegalArgumentException("Company not found"));
        
        // Check if company is active
        if (!company.isActive()) {
            throw new IllegalArgumentException("Company is not active");
        }
        
        // Check company subscription
        if (!company.hasActiveSubscription()) {
            throw new IllegalArgumentException("Company subscription is not active");
        }
        
        // Check monthly post limit
        long currentMonthPosts = postRepository.countPublishedThisMonthByCompanyId(company.getId().getValueAsLong());
        if (currentMonthPosts >= company.getEffectiveMaxPostsPerMonth()) {
            throw new IllegalArgumentException("Company has reached monthly post limit");
        }
        
        // Determine if approval is required
        boolean approvalRequired = determineApprovalRequired(user, company);
        
        // Create new post
        Post post = Post.create(
            company.getId().getValueAsLong(),
            Long.valueOf(user.getId().getValueAsString().hashCode()),
            command.title(),
            command.content(),
            command.postType(),
            approvalRequired
        );
        
        // Set optional fields
        if (command.mediaUrls() != null && command.mediaType() != null) {
            post.updateMedia(command.mediaUrls(), command.mediaType());
        }
        
        if (command.linkUrl() != null) {
            post.updateLink(command.linkUrl(), command.linkTitle(), 
                          command.linkDescription(), command.linkImageUrl());
        }
        
        if (command.campaignId() != null) {
            post.setCampaignId(command.campaignId());
        }
        
        if (command.autoPublish() != null) {
            post.setAutoPublish(command.autoPublish());
        }
        
        if (command.priority() != null) {
            post.setPriority(command.priority());
        }
        
        if (command.tags() != null) {
            post.setTags(command.tags());
        }
        
        if (command.notes() != null) {
            post.setNotes(command.notes());
        }
        
        // Handle scheduling
        if (command.scheduledFor() != null) {
            if (approvalRequired) {
                // Submit for approval first
                post.submitForApproval();
            } else {
                // Schedule directly
                post.schedule(command.scheduledFor());
            }
        } else if (approvalRequired) {
            // Submit for approval
            post.submitForApproval();
        }
        
        // Save post
        Post savedPost = postRepository.save(post);
        
        // Return result
        return new CreatePostResult(
            savedPost.getPostUuid(),
            savedPost.getTitle(),
            savedPost.getContent(),
            savedPost.getPostType(),
            savedPost.getPostStatus(),
            savedPost.getApprovalRequired(),
            user.getFullName(),
            savedPost.getScheduledForInstant()
        );
    }
    
    /**
     * Validate the create post command
     */
    private void validateCreatePostCommand(CreatePostCommand command) {
        if (command.userUuid() == null || command.userUuid().trim().isEmpty()) {
            throw new IllegalArgumentException("User UUID is required");
        }
        
        if (command.content() == null || command.content().trim().isEmpty()) {
            throw new IllegalArgumentException("Post content is required");
        }
        
        if (command.postType() == null) {
            throw new IllegalArgumentException("Post type is required");
        }
        
        // Validate content length (basic validation)
        if (command.content().length() > 10000) {
            throw new IllegalArgumentException("Post content cannot exceed 10,000 characters");
        }
        
        // Validate scheduled time if provided
        if (command.scheduledFor() != null) {
            if (command.scheduledFor().isBefore(Instant.now())) {
                throw new IllegalArgumentException("Cannot schedule post in the past");
            }
            
            // Don't allow scheduling more than 1 year in advance
            Instant oneYearFromNow = Instant.now().plusSeconds(365 * 24 * 60 * 60);
            if (command.scheduledFor().isAfter(oneYearFromNow)) {
                throw new IllegalArgumentException("Cannot schedule post more than 1 year in advance");
            }
        }
        
        // Validate priority if provided
        if (command.priority() != null && (command.priority() < 1 || command.priority() > 10)) {
            throw new IllegalArgumentException("Priority must be between 1 and 10");
        }
        
        // Validate media type matches media URLs
        if (command.mediaUrls() != null && !command.mediaUrls().trim().isEmpty()) {
            if (command.mediaType() == null) {
                throw new IllegalArgumentException("Media type is required when media URLs are provided");
            }
        }
        
        // Validate link URL format if provided
        if (command.linkUrl() != null && !command.linkUrl().trim().isEmpty()) {
            if (!isValidUrl(command.linkUrl())) {
                throw new IllegalArgumentException("Invalid link URL format");
            }
        }
    }
    
    /**
     * Determine if approval is required for this post
     */
    private boolean determineApprovalRequired(User user, Company company) {
        // Admin users don't need approval
        if (user.isAdmin()) {
            return false;
        }
        
        // Check user role permissions
        if (user.canPerformAction("publish_posts")) {
            return false;
        }
        
        // Default to requiring approval for other roles
        return true;
    }
    
    /**
     * Basic URL validation
     */
    private boolean isValidUrl(String url) {
        try {
            new java.net.URL(url);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
