package com.pablotj.ai.chat.presentation.rest;

import com.pablotj.ai.chat.application.dto.ConversationDto;
import com.pablotj.ai.chat.application.dto.ConversationMessageDto;
import com.pablotj.ai.chat.application.dto.ConversationSummaryDto;
import com.pablotj.ai.chat.application.usecase.CreateConversationUseCase;
import com.pablotj.ai.chat.application.usecase.GetConversationHistoryUseCase;
import com.pablotj.ai.chat.application.usecase.GetConversationMessagesUseCase;
import com.pablotj.ai.chat.application.usecase.ProcessUserMessageUseCase;
import com.pablotj.ai.chat.presentation.dto.CreateConversationRequest;
import com.pablotj.ai.chat.presentation.dto.SendMessageRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * REST controller for conversation management operations.
 * Provides endpoints for creating, retrieving, and managing conversations.
 */
@RestController
@RequestMapping("/v1/conversations")
@Tag(name = "Conversations", description = "Conversation management operations")
@CrossOrigin(origins = "*", maxAge = 3600)
public class ConversationController {

    private static final Logger logger = LoggerFactory.getLogger(ConversationController.class);

    private final CreateConversationUseCase createConversationUseCase;
    private final GetConversationHistoryUseCase getConversationHistoryUseCase;
    private final GetConversationMessagesUseCase getConversationMessagesUseCase;
    private final ProcessUserMessageUseCase processUserMessageUseCase;

    public ConversationController(
            CreateConversationUseCase createConversationUseCase,
            GetConversationHistoryUseCase getConversationHistoryUseCase,
            GetConversationMessagesUseCase getConversationMessagesUseCase,
            ProcessUserMessageUseCase processUserMessageUseCase) {
        this.createConversationUseCase = createConversationUseCase;
        this.getConversationHistoryUseCase = getConversationHistoryUseCase;
        this.getConversationMessagesUseCase = getConversationMessagesUseCase;
        this.processUserMessageUseCase = processUserMessageUseCase;
    }

    @Operation(
            summary = "Create a new conversation",
            description = "Creates a new conversation with optional title and description"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "Conversation created successfully",
                    content = @Content(schema = @Schema(implementation = ConversationDto.class))),
            @ApiResponse(responseCode = "400", description = "Invalid request data"),
            @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @PostMapping
    public ResponseEntity<ConversationDto> createConversation(
            @Valid @RequestBody(required = false) CreateConversationRequest request) {

        logger.debug("Creating new conversation with request: {}", request);

        ConversationDto conversation = request != null && request.title() != null ?
                createConversationUseCase.execute(request.toConversationSummary()) :
                createConversationUseCase.execute();

        logger.info("Successfully created conversation: {}", conversation.conversationId());

        return ResponseEntity.status(HttpStatus.CREATED).body(conversation);
    }

    @Operation(
            summary = "Get conversation history",
            description = "Retrieves a list of all active conversations ordered by creation date"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Conversation history retrieved successfully"),
            @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @GetMapping
    public ResponseEntity<List<ConversationSummaryDto>> getConversationHistory() {
        logger.debug("Retrieving conversation history");

        List<ConversationSummaryDto> conversations = getConversationHistoryUseCase.execute();

        logger.debug("Retrieved {} conversations", conversations.size());

        return ResponseEntity.ok(conversations);
    }

    @Operation(
            summary = "Get conversation messages",
            description = "Retrieves all messages from a specific conversation"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Messages retrieved successfully"),
            @ApiResponse(responseCode = "404", description = "Conversation not found"),
            @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @GetMapping("/{conversationId}/messages")
    public ResponseEntity<List<ConversationMessageDto>> getConversationMessages(
            @Parameter(description = "Unique conversation identifier", required = true)
            @PathVariable String conversationId) {

        logger.debug("Retrieving messages for conversation: {}", conversationId);

        List<ConversationMessageDto> messages = getConversationMessagesUseCase.execute(conversationId);

        logger.debug("Retrieved {} messages for conversation: {}", messages.size(), conversationId);

        return ResponseEntity.ok(messages);
    }

    @Operation(
            summary = "Send a message to a conversation",
            description = "Sends a user message to the specified conversation and returns the AI response"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Message processed and AI response generated",
                    content = @Content(schema = @Schema(implementation = ConversationMessageDto.class))),
            @ApiResponse(responseCode = "400", description = "Invalid request data"),
            @ApiResponse(responseCode = "404", description = "Conversation not found"),
            @ApiResponse(responseCode = "503", description = "AI service unavailable"),
            @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @PostMapping("/{conversationId}/messages")
    public ResponseEntity<ConversationMessageDto> sendMessage(
            @Parameter(description = "Unique conversation identifier", required = true)
            @PathVariable String conversationId,
            @Valid @RequestBody SendMessageRequest request) {

        logger.debug("Processing message for conversation: {}", conversationId);

        ConversationMessageDto aiResponse = processUserMessageUseCase.execute(
                conversationId, request.content());

        logger.info("Successfully processed message for conversation: {}", conversationId);

        return ResponseEntity.ok(aiResponse);
    }
}
