package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.dto.message.ChatUserDto;
import com.gnx.telemedicine.dto.message.ConversationDto;
import com.gnx.telemedicine.dto.message.MessageRequestDto;
import com.gnx.telemedicine.dto.message.MessageResponseDto;
import com.gnx.telemedicine.service.MessageService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/api/v3/messages")
@RequiredArgsConstructor
@Tag(name = "Messages", description = "Endpoints for messaging between doctors and patients")
public class MessageController {

    private final MessageService messageService;

    @Operation(summary = "Send a message", description = "Send a message to another user")
    @ApiResponse(responseCode = "200", description = "Message sent successfully")
    @PostMapping
    public ResponseEntity<MessageResponseDto> sendMessage(
            @Valid @RequestBody MessageRequestDto requestDto,
            Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.sendMessage(userEmail, requestDto));
    }

    @Operation(summary = "Get conversation", description = "Get all messages in a conversation with another user")
    @ApiResponse(responseCode = "200", description = "Conversation retrieved successfully")
    @GetMapping("/conversation/{otherUserId}")
    public ResponseEntity<List<MessageResponseDto>> getConversation(
            @PathVariable UUID otherUserId,
            Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.getConversation(userEmail, otherUserId));
    }

    @Operation(summary = "Get all conversations", description = "Get all conversations for the current user")
    @ApiResponse(responseCode = "200", description = "Conversations retrieved successfully")
    @GetMapping("/conversations")
    public ResponseEntity<List<ConversationDto>> getConversations(Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.getConversations(userEmail));
    }

    @Operation(summary = "Mark messages as read", description = "Mark all messages from a sender as read")
    @ApiResponse(responseCode = "200", description = "Messages marked as read")
    @PutMapping("/read/{senderId}")
    public ResponseEntity<Void> markAsRead(@PathVariable UUID senderId, Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.markMessagesAsRead(userEmail, senderId);
        return ResponseEntity.ok().build();
    }

    @Operation(summary = "Get unread message count", description = "Get the count of unread messages")
    @ApiResponse(responseCode = "200", description = "Unread count retrieved successfully")
    @GetMapping("/unread/count")
    public ResponseEntity<Long> getUnreadCount(Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.getUnreadMessageCount(userEmail));
    }

    @Operation(summary = "Update online status", description = "Update user's online status")
    @ApiResponse(responseCode = "200", description = "Status updated successfully")
    @PutMapping("/status/online")
    public ResponseEntity<Void> updateOnlineStatus(
            @RequestParam boolean online,
            Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.updateOnlineStatus(userEmail, online);
        return ResponseEntity.ok().build();
    }

    @Operation(summary = "Update user status", description = "Update user's status (ONLINE, OFFLINE, BUSY)")
    @ApiResponse(responseCode = "200", description = "Status updated successfully")
    @ApiResponse(responseCode = "400", description = "Invalid status value")
    @PutMapping("/status")
    public ResponseEntity<Void> updateUserStatus(
            @RequestParam String status,
            Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.updateUserStatus(userEmail, status);
        return ResponseEntity.ok().build();
    }

    @Operation(summary = "Search doctors", description = "Search for doctors to chat with (patients only)")
    @ApiResponse(responseCode = "200", description = "Doctors retrieved successfully")
    @GetMapping("/search/doctors")
    public ResponseEntity<List<ChatUserDto>> searchDoctors(
            @RequestParam(required = false, defaultValue = "") String query,
            Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.searchDoctors(userEmail, query));
    }

    @Operation(summary = "Search patients", description = "Search for patients to chat with (doctors only)")
    @ApiResponse(responseCode = "200", description = "Patients retrieved successfully")
    @GetMapping("/search/patients")
    public ResponseEntity<List<ChatUserDto>> searchPatients(
            @RequestParam(required = false, defaultValue = "") String query,
            Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.searchPatients(userEmail, query));
    }

    @Operation(summary = "Delete a message", description = "Delete a specific message by ID (only if user is sender or receiver)")
    @ApiResponse(responseCode = "200", description = "Message deleted successfully")
    @ApiResponse(responseCode = "404", description = "Message not found")
    @ApiResponse(responseCode = "403", description = "Not authorized to delete this message")
    @DeleteMapping("/message/{messageId}")
    public ResponseEntity<Void> deleteMessage(
            @PathVariable UUID messageId,
            Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.deleteMessage(userEmail, messageId);
        return ResponseEntity.ok().build();
    }

    @Operation(summary = "Delete conversation", description = "Delete all messages in a conversation with another user")
    @ApiResponse(responseCode = "200", description = "Conversation deleted successfully")
    @DeleteMapping("/conversation/{otherUserId}")
    public ResponseEntity<Void> deleteConversation(
            @PathVariable UUID otherUserId,
            Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.deleteConversation(userEmail, otherUserId);
        return ResponseEntity.ok().build();
    }

    @Operation(summary = "Block a user", description = "Block a user from sending messages to you. Blocks are bidirectional - you cannot message them either.")
    @ApiResponse(responseCode = "200", description = "User blocked successfully")
    @ApiResponse(responseCode = "400", description = "Invalid request (e.g., trying to block yourself or user already blocked)")
    @PostMapping("/block/{userId}")
    public ResponseEntity<Map<String, String>> blockUser(
            @PathVariable UUID userId,
            Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.blockUser(userEmail, userId);
        Map<String, String> response = new java.util.HashMap<>();
        response.put("message", "User blocked successfully");
        return ResponseEntity.ok(response);
    }

    @Operation(summary = "Unblock a user", description = "Unblock a user to allow them to send messages to you again.")
    @ApiResponse(responseCode = "200", description = "User unblocked successfully")
    @ApiResponse(responseCode = "400", description = "User is not blocked")
    @DeleteMapping("/block/{userId}")
    public ResponseEntity<Map<String, String>> unblockUser(
            @PathVariable UUID userId,
            Authentication authentication) {
        String userEmail = authentication.getName();
        messageService.unblockUser(userEmail, userId);
        Map<String, String> response = new java.util.HashMap<>();
        response.put("message", "User unblocked successfully");
        return ResponseEntity.ok(response);
    }

    @Operation(summary = "Check if user is blocked", description = "Check if a user is blocked (either by you or you by them)")
    @ApiResponse(responseCode = "200", description = "Block status retrieved successfully")
    @GetMapping("/block/status/{userId}")
    public ResponseEntity<Map<String, Boolean>> isBlocked(
            @PathVariable UUID userId,
            Authentication authentication) {
        String userEmail = authentication.getName();
        boolean blocked = messageService.isBlocked(userEmail, userId);
        Map<String, Boolean> response = new java.util.HashMap<>();
        response.put("blocked", blocked);
        return ResponseEntity.ok(response);
    }

    @Operation(summary = "Get blocked users", description = "Get list of user IDs that the current user has blocked")
    @ApiResponse(responseCode = "200", description = "Blocked users retrieved successfully")
    @GetMapping("/block/list")
    public ResponseEntity<List<UUID>> getBlockedUsers(Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.getBlockedUsers(userEmail));
    }

    @Operation(summary = "Get blocked users with details", description = "Get list of blocked users with full information (name, avatar, etc.)")
    @ApiResponse(responseCode = "200", description = "Blocked users with details retrieved successfully")
    @GetMapping("/block/list/details")
    public ResponseEntity<List<ChatUserDto>> getBlockedUsersWithDetails(Authentication authentication) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(messageService.getBlockedUsersWithDetails(userEmail));
    }
}

