package com.petshop.backend.controller;

import com.petshop.backend.dto.chat.ConversationRequest;
import com.petshop.backend.dto.chat.ConversationResponse;
import com.petshop.backend.dto.chat.MessageRequest;
import com.petshop.backend.dto.chat.MessageResponse;
import com.petshop.backend.dto.chat.UpdateConversationRequest;
import com.petshop.backend.entity.Message;
import com.petshop.backend.entity.User;
import com.petshop.backend.exception.ResourceNotFoundException;
import com.petshop.backend.repository.MessageRepository;
import com.petshop.backend.repository.UserRepository;
import com.petshop.backend.service.ChatAttachmentStorageService;
import com.petshop.backend.service.ChatRealtimeService;
import com.petshop.backend.service.ChatService;
import com.petshop.backend.service.OpenRouterAiService;
import com.petshop.backend.util.AuthenticationHelper;
import jakarta.validation.Valid;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@RestController
@RequestMapping("/api/v1/chat")
public class ChatController {

    private final ChatService chatService;
    private final ChatRealtimeService chatRealtimeService;
    private final OpenRouterAiService openRouterAiService;
    private final UserRepository userRepository;
    private final ChatAttachmentStorageService attachmentStorageService;
    private final MessageRepository messageRepository;

    public ChatController(ChatService chatService, ChatRealtimeService chatRealtimeService, 
                          OpenRouterAiService openRouterAiService, UserRepository userRepository, ChatAttachmentStorageService attachmentStorageService,
                          MessageRepository messageRepository) {
        this.chatService = chatService;
        this.chatRealtimeService = chatRealtimeService;
        this.openRouterAiService = openRouterAiService;
        this.userRepository = userRepository;
        this.attachmentStorageService = attachmentStorageService;
        this.messageRepository = messageRepository;
    }

    private User getCurrentUser() {
        try {
            return AuthenticationHelper.getAuthenticatedUser(userRepository);
        } catch (RuntimeException ex) {
            throw new UsernameNotFoundException(ex.getMessage(), ex);
        }
    }

    @PostMapping("/conversations")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity<ConversationResponse> createConversation(@Valid @RequestBody ConversationRequest request) {
        User user = getCurrentUser();
        ConversationResponse response = chatService.createConversation(user.getId(), request);
        chatRealtimeService.publishNewConversation(response);
        return ResponseEntity.status(HttpStatus.CREATED).body(response);
    }

    @GetMapping("/conversations")
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<List<ConversationResponse>> getConversations(
            @RequestParam(required = false, defaultValue = "false") boolean mine) {
        User user = getCurrentUser();
        List<ConversationResponse> conversations = chatService.getConversations(user.getId(), user.getRole(), mine);
        return ResponseEntity.ok(conversations);
    }

    @GetMapping("/conversations/{id}")
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<ConversationResponse> getConversation(@PathVariable Long id) {
        User user = getCurrentUser();
        ConversationResponse conversation = chatService.getConversation(id, user.getId(), user.getRole());
        return ResponseEntity.ok(conversation);
    }

    @PostMapping("/conversations/{id}/messages")
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<MessageResponse> sendMessage(
            @PathVariable Long id,
            @Valid @RequestBody MessageRequest request) {
        User user = getCurrentUser();
        MessageResponse message = chatService.sendMessage(id, user.getId(), user.getRole(), request);
        chatRealtimeService.publishMessage(id, message);
        chatRealtimeService.publishConversationUpdate(id);
        openRouterAiService.generateAndSendReply(id, message.getId());
        return ResponseEntity.status(HttpStatus.CREATED).body(message);
    }

    @PostMapping(value = "/conversations/{id}/attachments", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<MessageResponse> sendMessageWithAttachment(
            @PathVariable Long id,
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "content", required = false) String content) {
        User user = getCurrentUser();
        MessageResponse message = chatService.sendMessageWithAttachment(id, user.getId(), user.getRole(), file, content);
        chatRealtimeService.publishMessage(id, message);
        chatRealtimeService.publishConversationUpdate(id);
        openRouterAiService.generateAndSendReply(id, message.getId());
        return ResponseEntity.status(HttpStatus.CREATED).body(message);
    }

    @GetMapping("/messages/{messageId}/attachment")
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<Resource> getMessageAttachment(@PathVariable Long messageId) {
        User user = getCurrentUser();
        Message message = messageRepository.findById(messageId)
                .orElseThrow(() -> new ResourceNotFoundException("Message not found with id: " + messageId));

        if (!chatService.hasConversationAccess(message.getConversationId(), user.getId(), user.getRole())) {
            throw new AccessDeniedException("Access denied to this message attachment");
        }

        if (message.getAttachmentUrl() == null) {
            return ResponseEntity.notFound().build();
        }

        try {
            Resource resource = attachmentStorageService.loadAttachmentResource(message.getAttachmentUrl());
            return ResponseEntity.ok()
                    .contentType(attachmentStorageService.resolveMediaType(message.getAttachmentUrl()))
                    .header("Content-Disposition", "attachment; filename=\"" + message.getAttachmentName() + "\"")
                    .body(resource);
        } catch (IllegalArgumentException ex) {
            return ResponseEntity.notFound().build();
        }
    }

    @GetMapping("/conversations/{id}/messages")
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<List<MessageResponse>> getMessages(@PathVariable Long id) {
        User user = getCurrentUser();
        List<MessageResponse> messages = chatService.getMessages(id, user.getId(), user.getRole());
        return ResponseEntity.ok(messages);
    }

    @PostMapping("/conversations/{id}/request-human")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity<ConversationResponse> requestHumanTakeover(@PathVariable Long id) {
        User user = getCurrentUser();
        ConversationResponse conversation = chatService.requestHumanTakeover(id, user.getId(), user.getRole());
        chatRealtimeService.publishConversationUpdate(id);
        return ResponseEntity.ok(conversation);
    }

    @PutMapping("/conversations/{id}")
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<ConversationResponse> updateConversation(@PathVariable Long id, @Valid @RequestBody UpdateConversationRequest request) {
        User user = getCurrentUser();
        ConversationResponse conversation = chatService.updateConversation(id, user.getId(), user.getRole(), request);
        chatRealtimeService.publishConversationUpdate(id);
        return ResponseEntity.ok(conversation);
    }
}
