using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using MktXService.API.Application.Commands;
using MktXService.API.Application.Queries;
using MktXService.Domain.AggregatesModel.CampaignAggregate;

namespace MktXService.API.Controllers;

/// <summary>
/// EN: Controller for Campaign management.
/// VI: Controller quản lý chiến dịch.
/// </summary>
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[Produces("application/json")]
public class CampaignsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<CampaignsController> _logger;

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

    /// <summary>
    /// EN: Get all campaigns for a merchant.
    /// VI: Lấy tất cả chiến dịch của merchant.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(IEnumerable<CampaignDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetCampaigns(
        [FromQuery] Guid merchantId,
        [FromQuery] string? status = null,
        [FromQuery] int skip = 0,
        [FromQuery] int take = 20)
    {
        var campaigns = await _mediator.Send(new GetCampaignsQuery(merchantId, status, skip, take));
        return Ok(new { success = true, data = campaigns });
    }

    /// <summary>
    /// EN: Get a campaign by ID.
    /// VI: Lấy chiến dịch theo ID.
    /// </summary>
    [HttpGet("{id:guid}")]
    [ProducesResponseType(typeof(CampaignDetailDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetCampaign(Guid id)
    {
        var campaign = await _mediator.Send(new GetCampaignQuery(id));
        if (campaign == null)
            return NotFound(new { success = false, error = new { code = "CAMPAIGN_NOT_FOUND", message = $"Campaign {id} not found" } });

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

    /// <summary>
    /// EN: Create a new campaign.
    /// VI: Tạo chiến dịch mới.
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(CreateCampaignResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateCampaign([FromBody] CreateCampaignRequest request)
    {
        CampaignSchedule? schedule = null;
        if (request.Schedule != null)
            schedule = new CampaignSchedule(request.Schedule.StartAt, request.Schedule.EndAt, request.Schedule.Recurrence);

        var command = new CreateCampaignCommand(
            request.MerchantId,
            request.Name,
            request.Type,
            request.TemplateId,
            request.SegmentIds,
            schedule);

        var result = await _mediator.Send(command);

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

        return CreatedAtAction(nameof(GetCampaign), new { id = result.CampaignId },
            new { success = true, data = result });
    }

    /// <summary>
    /// EN: Start a campaign.
    /// VI: Bắt đầu chiến dịch.
    /// </summary>
    [HttpPost("{id:guid}/start")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> StartCampaign(Guid id)
    {
        var result = await _mediator.Send(new StartCampaignCommand(id));
        if (!result)
            return BadRequest(new { success = false, error = new { code = "START_FAILED", message = "Failed to start campaign" } });

        return Ok(new { success = true, message = "Campaign started successfully" });
    }

    /// <summary>
    /// EN: Pause a running campaign.
    /// VI: Tạm dừng chiến dịch đang chạy.
    /// </summary>
    [HttpPost("{id:guid}/pause")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> PauseCampaign(Guid id)
    {
        var result = await _mediator.Send(new PauseCampaignCommand(id));
        if (!result)
            return BadRequest(new { success = false, error = new { code = "PAUSE_FAILED", message = "Failed to pause campaign" } });

        return Ok(new { success = true, message = "Campaign paused successfully" });
    }

    /// <summary>
    /// EN: Resume a paused campaign.
    /// VI: Tiếp tục chiến dịch đã tạm dừng.
    /// </summary>
    [HttpPost("{id:guid}/resume")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ResumeCampaign(Guid id)
    {
        var result = await _mediator.Send(new ResumeCampaignCommand(id));
        if (!result)
            return BadRequest(new { success = false, error = new { code = "RESUME_FAILED", message = "Failed to resume campaign" } });

        return Ok(new { success = true, message = "Campaign resumed successfully" });
    }

    /// <summary>
    /// EN: Cancel a campaign.
    /// VI: Hủy chiến dịch.
    /// </summary>
    [HttpPost("{id:guid}/cancel")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CancelCampaign(Guid id, [FromBody] CancelCampaignRequest? request = null)
    {
        var result = await _mediator.Send(new CancelCampaignCommand(id, request?.Reason));
        if (!result)
            return BadRequest(new { success = false, error = new { code = "CANCEL_FAILED", message = "Failed to cancel campaign" } });

        return Ok(new { success = true, message = "Campaign cancelled successfully" });
    }
}

#region Request Models

public record CreateCampaignRequest(
    Guid MerchantId,
    string Name,
    string Type,
    Guid? TemplateId,
    List<Guid> SegmentIds,
    CampaignScheduleRequest? Schedule = null);

public record CampaignScheduleRequest(DateTime? StartAt, DateTime? EndAt, string? Recurrence);

public record CancelCampaignRequest(string? Reason);

#endregion
