using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MissionService.Domain.AggregatesModel.MissionAggregate;

namespace MissionService.API.Controllers;

/// <summary>
/// EN: Admin controller for mission management
/// VI: Controller admin để quản lý mission
/// </summary>
[ApiController]
[Route("api/v1/admin/missions")]
[Authorize(Roles = "Admin")]
public class AdminMissionsController : ControllerBase
{
    private readonly IMissionRepository _missionRepository;
    private readonly ILogger<AdminMissionsController> _logger;

    public AdminMissionsController(
        IMissionRepository missionRepository,
        ILogger<AdminMissionsController> logger)
    {
        _missionRepository = missionRepository;
        _logger = logger;
    }

    /// <summary>
    /// EN: Get all missions (admin) / VI: Lấy tất cả missions (admin)
    /// </summary>
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetAllMissions()
    {
        var missions = await _missionRepository.GetActiveMissionsAsync();
        return Ok(missions.Select(m => MapToAdminDto(m)));
    }

    /// <summary>
    /// EN: Create new mission / VI: Tạo mission mới
    /// </summary>
    [HttpPost]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateMission([FromBody] CreateMissionRequest request)
    {
        try
        {
            var reward = MissionReward.Create(
                request.RewardPoints,
                request.RewardMiningBoost,
                request.RewardXp,
                request.RewardBadgeId);

            var mission = new Mission(
                code: request.Code,
                titleEn: request.TitleEn,
                titleVi: request.TitleVi,
                type: MissionType.FromValue<MissionType>(request.TypeId),
                category: MissionCategory.FromValue<MissionCategory>(request.CategoryId),
                reward: reward,
                frequency: FrequencyType.FromValue<FrequencyType>(request.FrequencyId),
                maxCompletions: request.MaxCompletions,
                startDate: request.StartDate,
                endDate: request.EndDate,
                priority: request.Priority);

            _missionRepository.Add(mission);
            await _missionRepository.UnitOfWork.SaveEntitiesAsync();

            _logger.LogInformation("Mission {Code} created by admin", request.Code);

            return CreatedAtAction(nameof(GetMissionById), new { id = mission.Id }, MapToAdminDto(mission));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to create mission {Code}", request.Code);
            return BadRequest(new { Message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Get mission by ID / VI: Lấy mission theo ID
    /// </summary>
    [HttpGet("{id:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetMissionById(Guid id)
    {
        var mission = await _missionRepository.GetByIdAsync(id);
        if (mission == null)
        {
            return NotFound();
        }
        return Ok(MapToAdminDto(mission));
    }

    /// <summary>
    /// EN: Activate a mission / VI: Kích hoạt mission
    /// </summary>
    [HttpPost("{id:guid}/activate")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ActivateMission(Guid id)
    {
        var mission = await _missionRepository.GetByIdAsync(id);
        if (mission == null)
        {
            return NotFound();
        }

        try
        {
            mission.Activate();
            _missionRepository.Update(mission);
            await _missionRepository.UnitOfWork.SaveEntitiesAsync();

            _logger.LogInformation("Mission {Id} activated", id);
            return Ok(MapToAdminDto(mission));
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { Message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Pause a mission / VI: Tạm dừng mission
    /// </summary>
    [HttpPost("{id:guid}/pause")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> PauseMission(Guid id)
    {
        var mission = await _missionRepository.GetByIdAsync(id);
        if (mission == null)
        {
            return NotFound();
        }

        try
        {
            mission.Pause();
            _missionRepository.Update(mission);
            await _missionRepository.UnitOfWork.SaveEntitiesAsync();

            _logger.LogInformation("Mission {Id} paused", id);
            return Ok(MapToAdminDto(mission));
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { Message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Archive a mission / VI: Lưu trữ mission
    /// </summary>
    [HttpPost("{id:guid}/archive")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> ArchiveMission(Guid id)
    {
        var mission = await _missionRepository.GetByIdAsync(id);
        if (mission == null)
        {
            return NotFound();
        }

        mission.Archive();
        _missionRepository.Update(mission);
        await _missionRepository.UnitOfWork.SaveEntitiesAsync();

        _logger.LogInformation("Mission {Id} archived", id);
        return Ok(MapToAdminDto(mission));
    }

    private static object MapToAdminDto(Mission m) => new
    {
        m.Id,
        m.Code,
        m.TitleEn,
        m.TitleVi,
        m.DescriptionEn,
        m.DescriptionVi,
        Type = m.Type.Name,
        Category = m.Category.Name,
        Status = m.Status.Name,
        Frequency = m.Frequency.Name,
        Reward = new
        {
            m.Reward.Points,
            m.Reward.MiningBoostPercent,
            m.Reward.ExperiencePoints,
            m.Reward.BadgeId
        },
        m.MaxCompletions,
        m.StartDate,
        m.EndDate,
        m.Priority,
        Rules = m.Rules.Select(r => new { r.RuleType, r.Operator, r.Value })
    };
}

/// <summary>
/// EN: Request to create a new mission / VI: Request tạo mission mới
/// </summary>
public record CreateMissionRequest(
    string Code,
    string TitleEn,
    string TitleVi,
    string? DescriptionEn,
    string? DescriptionVi,
    int TypeId,
    int CategoryId,
    int FrequencyId,
    decimal RewardPoints,
    decimal RewardMiningBoost,
    int RewardXp,
    string? RewardBadgeId,
    int MaxCompletions,
    DateTime StartDate,
    DateTime? EndDate,
    int Priority = 0);
