using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MktXService.API.Application.Commands;
using MktXService.API.Application.Queries;

namespace MktXService.API.Controllers;

/// <summary>
/// EN: Controller for Conversation management.
/// VI: Controller quản lý hội thoại.
/// </summary>
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[Produces("application/json")]
[Authorize]
public class ConversationsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<ConversationsController> _logger;

    public ConversationsController(IMediator mediator, ILogger<ConversationsController> logger)
    {
        _mediator = mediator;
        _logger = logger;
    }

    /// <summary>
    /// EN: Get all conversations for an account.
    /// VI: Lấy tất cả hội thoại của tài khoản.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(IEnumerable<ConversationDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetConversations(
        [FromQuery] Guid accountId,
        [FromQuery] string? status = null,
        [FromQuery] Guid? assignedToUserId = null,
        [FromQuery] int skip = 0,
        [FromQuery] int take = 20)
    {
        var conversations = await _mediator.Send(
            new GetConversationsQuery(accountId, status, assignedToUserId, skip, take));
        return Ok(new { success = true, data = conversations });
    }

    /// <summary>
    /// EN: Get a conversation by ID with messages.
    /// VI: Lấy hội thoại theo ID với tin nhắn.
    /// </summary>
    [HttpGet("{id:guid}")]
    [ProducesResponseType(typeof(ConversationDetailDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetConversation(Guid id, [FromQuery] bool includeMessages = true)
    {
        var conversation = await _mediator.Send(new GetConversationQuery(id, includeMessages));
        if (conversation == null)
            return NotFound(new { success = false, error = new { code = "CONVERSATION_NOT_FOUND", message = $"Conversation {id} not found" } });

        return Ok(new { success = true, data = conversation });
    }

    /// <summary>
    /// EN: Send a message in a conversation.
    /// VI: Gửi tin nhắn trong hội thoại.
    /// </summary>
    [HttpPost("{id:guid}/messages")]
    [ProducesResponseType(typeof(SendMessageResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> SendMessage(Guid id, [FromBody] SendMessageRequest request)
    {
        var command = new SendMessageCommand(id, request.Content, request.IsFromBot, request.MediaUrls);
        var result = await _mediator.Send(command);

        if (!result.Success)
            return BadRequest(new { success = false, error = new { code = "SEND_FAILED", message = result.Error } });

        return Created($"/api/v1/conversations/{id}/messages/{result.MessageId}",
            new { success = true, data = result });
    }

    /// <summary>
    /// EN: Close a conversation.
    /// VI: Đóng hội thoại.
    /// </summary>
    [HttpPost("{id:guid}/close")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> CloseConversation(Guid id, [FromBody] CloseConversationRequest? request = null)
    {
        var result = await _mediator.Send(new CloseConversationCommand(id, request?.Reason));
        if (!result)
            return NotFound(new { success = false, error = new { code = "CONVERSATION_NOT_FOUND", message = $"Conversation {id} not found" } });

        return Ok(new { success = true, message = "Conversation closed successfully" });
    }

    /// <summary>
    /// EN: Reopen a closed conversation.
    /// VI: Mở lại hội thoại đã đóng.
    /// </summary>
    [HttpPost("{id:guid}/reopen")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ReopenConversation(Guid id)
    {
        var result = await _mediator.Send(new ReopenConversationCommand(id));
        if (!result)
            return BadRequest(new { success = false, error = new { code = "REOPEN_FAILED", message = "Failed to reopen conversation" } });

        return Ok(new { success = true, message = "Conversation reopened successfully" });
    }

    /// <summary>
    /// EN: Assign conversation to an agent.
    /// VI: Gán hội thoại cho agent.
    /// </summary>
    [HttpPost("{id:guid}/assign")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> AssignConversation(Guid id, [FromBody] AssignConversationRequest request)
    {
        var result = await _mediator.Send(new AssignConversationCommand(id, request.UserId));
        if (!result)
            return NotFound(new { success = false, error = new { code = "CONVERSATION_NOT_FOUND", message = $"Conversation {id} not found" } });

        return Ok(new { success = true, message = "Conversation assigned successfully" });
    }

    /// <summary>
    /// EN: Mark conversation as pending.
    /// VI: Đánh dấu hội thoại đang chờ.
    /// </summary>
    [HttpPost("{id:guid}/pending")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> MarkAsPending(Guid id)
    {
        var result = await _mediator.Send(new MarkConversationPendingCommand(id));
        if (!result)
            return BadRequest(new { success = false, error = new { code = "MARK_PENDING_FAILED", message = "Failed to mark conversation as pending" } });

        return Ok(new { success = true, message = "Conversation marked as pending" });
    }
}

#region Request Models

public record SendMessageRequest(string Content, bool IsFromBot = false, List<string>? MediaUrls = null);
public record CloseConversationRequest(string? Reason);
public record AssignConversationRequest(Guid UserId);

#endregion
