package online.wesal.wesal.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import online.wesal.wesal.dto.ApiResponse;
import online.wesal.wesal.dto.PostCreateRequestDTO;
import online.wesal.wesal.dto.PostLikeRequestDTO;
import online.wesal.wesal.dto.PostResponseDTO;
import online.wesal.wesal.dto.PostWithLikesResponseDTO;
import online.wesal.wesal.entity.Post;
import online.wesal.wesal.service.PostService;
import online.wesal.wesal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/posts")
@CrossOrigin(origins = "*")
@Tag(name = "Posts", description = "Post management endpoints")
public class PostController {
    
    @Autowired
    private PostService postService;
    
    @Autowired
    private UserService userService;
    
    @PostMapping(value = "/create", consumes = "application/json", produces = "application/json")
    @Operation(summary = "Create post", description = "Create a new post")
    public ResponseEntity<ApiResponse<PostResponseDTO>> createPost(
            @Valid @RequestBody PostCreateRequestDTO request,
            BindingResult bindingResult,
            Authentication authentication) {
        
        if (bindingResult.hasErrors()) {
            String errorMessage = bindingResult.getFieldErrors().stream()
                .map(error -> {
                    String field = error.getField();
                    if ("body".equals(field)) return "Post body is required and cannot exceed 2000 characters";
                    return error.getDefaultMessage();
                })
                .findFirst()
                .orElse("Invalid input");
            return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage));
        }
        
        try {
            PostResponseDTO response = postService.createPostWithResponse(request.getBody());
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            String message;
            if (e.getMessage().contains("User not found")) {
                message = "Authentication error. Please log in again.";
            } else {
                message = "Something went wrong.. We're sorry but try again later";
            }
            return ResponseEntity.badRequest().body(ApiResponse.error(message));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @GetMapping("/all")
    @Operation(summary = "Get all recent posts", description = "Get all posts from the last 7 days, ordered by creation date (latest first)")
    public ResponseEntity<ApiResponse<List<PostResponseDTO>>> getAllRecentPosts() {
        try {
            List<PostResponseDTO> response = postService.getAllRecentPosts();
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @GetMapping("/user")
    @Operation(summary = "Get user posts", description = "Get all posts by a specific user, ordered by creation date (latest first). If no id provided, returns authenticated user's posts.")
    public ResponseEntity<ApiResponse<List<PostResponseDTO>>> getUserPosts(
            @RequestParam(required = false) Long id,
            Authentication authentication) {
        
        try {
            Long targetUserId;
            if (id == null) {
                // Use authenticated user's ID when no id is provided
                String userEmail = authentication.getName();
                targetUserId = userService.getCurrentUser().getId();
            } else {
                if (id <= 0) {
                    return ResponseEntity.badRequest().body(ApiResponse.error("Valid user ID is required"));
                }
                targetUserId = id;
            }
            
            List<PostResponseDTO> response = postService.getUserPosts(targetUserId);
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            String message;
            if (e.getMessage().contains("User not found")) {
                message = "User not found";
            } else {
                message = "Something went wrong.. We're sorry but try again later";
            }
            return ResponseEntity.badRequest().body(ApiResponse.error(message));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @PostMapping(value = "/like", consumes = "application/json", produces = "application/json")
    @Operation(summary = "Like post", description = "Like a post. Returns the updated post with new like count.")
    public ResponseEntity<ApiResponse<PostResponseDTO>> likePost(
            @Valid @RequestBody PostLikeRequestDTO request,
            BindingResult bindingResult,
            Authentication authentication) {
        
        if (bindingResult.hasErrors()) {
            String errorMessage = bindingResult.getFieldErrors().stream()
                .map(error -> {
                    String field = error.getField();
                    if ("postId".equals(field)) return "Valid post ID is required";
                    return error.getDefaultMessage();
                })
                .findFirst()
                .orElse("Invalid input");
            return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage));
        }
        
        try {
            PostResponseDTO response = postService.likePost(request.getPostId());
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            String message;
            if (e.getMessage().contains("Post not found")) {
                message = "Post not found";
            } else if (e.getMessage().contains("User not found")) {
                message = "Authentication error. Please log in again.";
            } else {
                message = "Something went wrong.. We're sorry but try again later";
            }
            return ResponseEntity.badRequest().body(ApiResponse.error(message));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @PostMapping(value = "/unlike", consumes = "application/json", produces = "application/json")
    @Operation(summary = "Unlike post", description = "Unlike a post. Returns the updated post with new like count.")
    public ResponseEntity<ApiResponse<PostResponseDTO>> unlikePost(
            @Valid @RequestBody PostLikeRequestDTO request,
            BindingResult bindingResult,
            Authentication authentication) {
        
        if (bindingResult.hasErrors()) {
            String errorMessage = bindingResult.getFieldErrors().stream()
                .map(error -> {
                    String field = error.getField();
                    if ("postId".equals(field)) return "Valid post ID is required";
                    return error.getDefaultMessage();
                })
                .findFirst()
                .orElse("Invalid input");
            return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage));
        }
        
        try {
            PostResponseDTO response = postService.unlikePost(request.getPostId());
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            String message;
            if (e.getMessage().contains("Post not found")) {
                message = "Post not found";
            } else if (e.getMessage().contains("User not found")) {
                message = "Authentication error. Please log in again.";
            } else {
                message = "Something went wrong.. We're sorry but try again later";
            }
            return ResponseEntity.badRequest().body(ApiResponse.error(message));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @GetMapping("/get")
    @Operation(summary = "Get post by ID", description = "Get a specific post by ID with all liked users (limit 100)")
    public ResponseEntity<ApiResponse<PostWithLikesResponseDTO>> getPostById(
            @RequestParam Long id,
            Authentication authentication) {
        
        try {
            if (id == null || id <= 0) {
                return ResponseEntity.badRequest().body(ApiResponse.error("Valid post ID is required"));
            }
            
            PostWithLikesResponseDTO response = postService.getPostById(id);
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            String message;
            if (e.getMessage().contains("Post not found")) {
                message = "Post not found";
            } else if (e.getMessage().contains("User not found") || e.getMessage().contains("Creator not found")) {
                message = "Authentication error. Please log in again.";
            } else {
                message = "Something went wrong.. We're sorry but try again later";
            }
            return ResponseEntity.badRequest().body(ApiResponse.error(message));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
}