using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MissionService.Domain.AggregatesModel.CheckInAggregate;
using MissionService.Domain.AggregatesModel.TaskAggregate;
using TaskStatus = MissionService.Domain.AggregatesModel.TaskAggregate.TaskStatus;

namespace MissionService.API.Controllers;

/// <summary>
/// EN: Admin controller for check-in and task management
/// VI: Controller admin để quản lý check-in và task
/// </summary>
[ApiController]
[Route("api/v1/admin")]
[Authorize(Roles = "Admin")]
public class AdminController : ControllerBase
{
    private readonly IUserCheckInRepository _checkInRepository;
    private readonly IUserTaskRepository _taskRepository;
    private readonly ILogger<AdminController> _logger;

    public AdminController(
        IUserCheckInRepository checkInRepository,
        IUserTaskRepository taskRepository,
        ILogger<AdminController> logger)
    {
        _checkInRepository = checkInRepository;
        _taskRepository = taskRepository;
        _logger = logger;
    }

    #region Check-In Admin

    /// <summary>
    /// EN: Get user's check-in details / VI: Lấy chi tiết check-in của user
    /// </summary>
    [HttpGet("checkins/users/{userId:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetUserCheckIn(Guid userId)
    {
        var checkIn = await _checkInRepository.GetByUserIdAsync(userId);
        if (checkIn == null)
        {
            return NotFound(new { Message = "Check-in profile not found" });
        }

        return Ok(new
        {
            checkIn.Id,
            checkIn.UserId,
            checkIn.CurrentStreak,
            checkIn.LongestStreak,
            checkIn.TotalCheckIns,
            checkIn.LastCheckInDate,
            CanCheckInToday = checkIn.CanCheckInToday()
        });
    }

    /// <summary>
    /// EN: Reset user's streak (admin action) / VI: Reset streak của user (hành động admin)
    /// </summary>
    [HttpPost("checkins/users/{userId:guid}/reset-streak")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> ResetUserStreak(Guid userId)
    {
        var checkIn = await _checkInRepository.GetByUserIdAsync(userId);
        if (checkIn == null)
        {
            return NotFound(new { Message = "Check-in profile not found" });
        }

        checkIn.ResetStreak();
        _checkInRepository.Update(checkIn);
        await _checkInRepository.UnitOfWork.SaveEntitiesAsync();

        _logger.LogWarning("Admin reset streak for user {UserId}", userId);

        return Ok(new { Message = "Streak reset successfully", checkIn.CurrentStreak });
    }

    /// <summary>
    /// EN: Get top streaks / VI: Lấy streaks cao nhất
    /// </summary>
    [HttpGet("checkins/top-streaks")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetTopStreaks([FromQuery] int count = 20)
    {
        var topStreaks = await _checkInRepository.GetTopStreaksAsync(Math.Min(count, 100));
        
        return Ok(topStreaks.Select((c, i) => new
        {
            Rank = i + 1,
            c.UserId,
            c.CurrentStreak,
            c.LongestStreak,
            c.TotalCheckIns,
            c.LastCheckInDate
        }));
    }

    #endregion

    #region Task Admin

    /// <summary>
    /// EN: Get pending verification tasks / VI: Lấy tasks đang chờ xác thực
    /// </summary>
    [HttpGet("tasks/pending-verification")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetPendingVerificationTasks()
    {
        var tasks = await _taskRepository.GetPendingVerificationAsync();
        
        return Ok(tasks.Select(t => new
        {
            t.Id,
            t.UserId,
            t.MissionId,
            Status = t.Status.Name,
            Progress = new
            {
                t.Progress.CurrentValue,
                t.Progress.TargetValue,
                t.Progress.PercentComplete
            },
            Evidence = t.Evidence != null ? new
            {
                Type = t.Evidence.Type.ToString(),
                t.Evidence.Data,
                t.Evidence.ScreenshotUrl,
                t.Evidence.VideoUrl,
                t.Evidence.CapturedAt
            } : null,
            t.StartedAt
        }));
    }

    /// <summary>
    /// EN: Approve a task / VI: Duyệt task
    /// </summary>
    [HttpPost("tasks/{taskId:guid}/approve")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ApproveTask(Guid taskId)
    {
        var task = await _taskRepository.GetByIdAsync(taskId);
        if (task == null)
        {
            return NotFound(new { Message = "Task not found" });
        }

        if (task.Status != TaskStatus.PendingVerification)
        {
            return BadRequest(new { Message = "Task is not pending verification" });
        }

        var adminId = GetCurrentUserId();
        task.Complete(VerificationResult.ManualApproved(adminId));
        _taskRepository.Update(task);
        await _taskRepository.UnitOfWork.SaveEntitiesAsync();

        _logger.LogInformation("Task {TaskId} approved by admin {AdminId}", taskId, adminId);

        return Ok(new { Message = "Task approved", Status = task.Status.Name });
    }

    /// <summary>
    /// EN: Reject a task / VI: Từ chối task
    /// </summary>
    [HttpPost("tasks/{taskId:guid}/reject")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> RejectTask(Guid taskId, [FromBody] RejectTaskRequest request)
    {
        var task = await _taskRepository.GetByIdAsync(taskId);
        if (task == null)
        {
            return NotFound(new { Message = "Task not found" });
        }

        if (task.Status != TaskStatus.PendingVerification)
        {
            return BadRequest(new { Message = "Task is not pending verification" });
        }

        var adminId = GetCurrentUserId();
        task.Complete(VerificationResult.Rejected(request.Reason, VerificationMethod.Manual, adminId));
        _taskRepository.Update(task);
        await _taskRepository.UnitOfWork.SaveEntitiesAsync();

        _logger.LogInformation("Task {TaskId} rejected by admin {AdminId}: {Reason}", taskId, adminId, request.Reason);

        return Ok(new { Message = "Task rejected", Status = task.Status.Name, request.Reason });
    }

    /// <summary>
    /// EN: Get user's tasks / VI: Lấy tasks của user
    /// </summary>
    [HttpGet("tasks/users/{userId:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetUserTasks(Guid userId)
    {
        var tasks = await _taskRepository.GetByUserIdAsync(userId);
        
        return Ok(tasks.Select(t => new
        {
            t.Id,
            t.MissionId,
            Status = t.Status.Name,
            Progress = new
            {
                t.Progress.CurrentValue,
                t.Progress.TargetValue,
                t.Progress.PercentComplete
            },
            t.RewardClaimed,
            t.StartedAt,
            t.CompletedAt,
            t.ClaimedAt
        }));
    }

    #endregion

    private Guid GetCurrentUserId()
    {
        var userIdClaim = User.FindFirst("sub") ?? User.FindFirst("user_id");
        if (userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId))
        {
            return userId;
        }
        throw new UnauthorizedAccessException("User ID not found in token");
    }
}

/// <summary>
/// EN: Request to reject a task / VI: Request từ chối task
/// </summary>
public record RejectTaskRequest(string Reason);
