package com.social.media.interfaces.web.controller;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.social.media.domain.user.valueobject.UserId;
import com.social.media.infrastructure.persistence.entity.PostEntity;
import com.social.media.infrastructure.persistence.repository.PostJpaRepository;

import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;

/**
 * REST Controller for Post operations - REFACTORED VERSION
 * All operations now include security validation with userId and companyId
 */
@RestController
@RequestMapping("/api/v1/posts")
public class PostController {
    
    private final PostJpaRepository postJpaRepository;
    
    public PostController(PostJpaRepository postJpaRepository) {
        this.postJpaRepository = postJpaRepository;
    }
    
    /**
     * Get post by ID with security validation
     */
    @GetMapping("/{id}")
    public ResponseEntity<PostEntity> getPostById(@PathVariable Long id) {
        var authInfo = getAuthenticatedUserInfo();
        PostEntity post = postJpaRepository.findByIdAndCompanyIdAndUserId(
                id, authInfo.companyId(), authInfo.userId().value())
            .orElseThrow(() -> new RuntimeException("Post not found or access denied"));
        return ResponseEntity.ok(post);
    }
    
    /**
     * Get all posts in company with pagination and security validation
     */
    @GetMapping
    public ResponseEntity<Page<PostEntity>> getAllPosts(Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get posts by status with security validation
     */
    @GetMapping("/status/{status}")
    public ResponseEntity<Page<PostEntity>> getPostsByStatus(
            @PathVariable String status,
            Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        // Convert string to enum based on your implementation
        var statusEntity = convertToPostStatusEntity(status);
        Page<PostEntity> posts = postJpaRepository.findByCompanyIdAndStatusAndUserId(
                authInfo.companyId(), statusEntity, authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get posts by author with security validation
     */
    @GetMapping("/author/{authorId}")
    public ResponseEntity<Page<PostEntity>> getPostsByAuthor(
            @PathVariable Long authorId,
            Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findByCompanyIdAndAuthorIdAndUserId(
                authInfo.companyId(), authorId, authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get posts by category with security validation
     */
    @GetMapping("/category/{categoryId}")
    public ResponseEntity<Page<PostEntity>> getPostsByCategory(
            @PathVariable Long categoryId,
            Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findByCompanyIdAndCategoryIdAndUserId(
                authInfo.companyId(), categoryId, authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get scheduled posts with security validation
     */
    @GetMapping("/scheduled")
    public ResponseEntity<Page<PostEntity>> getScheduledPosts(Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findScheduledPostsByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get published posts with security validation
     */
    @GetMapping("/published")
    public ResponseEntity<Page<PostEntity>> getPublishedPosts(Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findPublishedPostsByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get draft posts with security validation
     */
    @GetMapping("/drafts")
    public ResponseEntity<Page<PostEntity>> getDraftPosts(Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findDraftPostsByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get user's own posts
     */
    @GetMapping("/my-posts")
    public ResponseEntity<Page<PostEntity>> getMyPosts(Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findOwnPosts(
                authInfo.companyId(), authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get pinned posts with security validation
     */
    @GetMapping("/pinned")
    public ResponseEntity<Page<PostEntity>> getPinnedPosts(Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findPinnedPostsByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get posts by date range with security validation
     */
    @GetMapping("/date-range")
    public ResponseEntity<Page<PostEntity>> getPostsByDateRange(
            @RequestParam LocalDateTime start,
            @RequestParam LocalDateTime end,
            Pageable pageable) {
        var authInfo = getAuthenticatedUserInfo();
        Page<PostEntity> posts = postJpaRepository.findByCompanyIdAndCreatedAtBetweenAndUserId(
                authInfo.companyId(), start, end, authInfo.userId().value(), pageable);
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Get most engaged posts with security validation
     */
    @GetMapping("/most-engaged")
    public ResponseEntity<List<PostEntity>> getMostEngagedPosts() {
        var authInfo = getAuthenticatedUserInfo();
        List<PostEntity> posts = postJpaRepository.findTop10MostEngagedByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value(), 
                org.springframework.data.domain.PageRequest.of(0, 10));
        return ResponseEntity.ok(posts);
    }
    
    /**
     * Count posts with security validation
     */
    @GetMapping("/count")
    public ResponseEntity<Long> getPostCount() {
        var authInfo = getAuthenticatedUserInfo();
        long count = postJpaRepository.countByCompanyIdAndUserId(
                authInfo.companyId(), authInfo.userId().value());
        return ResponseEntity.ok(count);
    }
    
    /**
     * Count posts by status with security validation
     */
    @GetMapping("/count/status/{status}")
    public ResponseEntity<Long> getPostCountByStatus(@PathVariable String status) {
        var authInfo = getAuthenticatedUserInfo();
        var statusEntity = convertToPostStatusEntity(status);
        long count = postJpaRepository.countByCompanyIdAndStatusAndUserId(
                authInfo.companyId(), statusEntity, authInfo.userId().value());
        return ResponseEntity.ok(count);
    }
    
    /**
     * Count today's published posts with security validation
     */
    @GetMapping("/count/today")
    public ResponseEntity<Long> getTodayPostCount() {
        var authInfo = getAuthenticatedUserInfo();
        LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        long count = postJpaRepository.countPublishedPostsTodayByCompanyIdAndUserId(
                authInfo.companyId(), startOfDay, endOfDay, authInfo.userId().value());
        return ResponseEntity.ok(count);
    }
    
    /**
     * Check if content text exists within company
     */
    @GetMapping("/check-content")
    public ResponseEntity<Boolean> checkContentExists(@RequestParam String contentText) {
        var authInfo = getAuthenticatedUserInfo();
        boolean exists = postJpaRepository.existsByContentTextAndCompanyId(
                contentText, authInfo.companyId());
        return ResponseEntity.ok(exists);
    }
    
    /**
     * Helper method to get authenticated user information
     */
    private AuthenticatedUserInfo getAuthenticatedUserInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new RuntimeException("User not authenticated");
        }
        
        // TODO: Implement proper authentication extraction based on your security setup
        Long userId = extractUserIdFromAuthentication(authentication);
        Long companyId = extractCompanyIdFromAuthentication(authentication);
        
        return new AuthenticatedUserInfo(UserId.of(userId), companyId);
    }
    
    private Long extractUserIdFromAuthentication(Authentication authentication) {
        // TODO: Implement based on your JWT/session structure
        return 1L; // Temporary
    }
    
    private Long extractCompanyIdFromAuthentication(Authentication authentication) {
        // TODO: Implement based on your JWT/session structure
        return 1L; // Temporary
    }
    
    private com.social.media.infrastructure.persistence.entity.PostStatusEntity convertToPostStatusEntity(String status) {
        // TODO: Implement based on your actual enum
        return com.social.media.infrastructure.persistence.entity.PostStatusEntity.valueOf(status.toUpperCase());
    }
    
    /**
     * Record to hold authenticated user information
     */
    private record AuthenticatedUserInfo(UserId userId, Long companyId) {}
}
