using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using StorageService.API.Application.Commands.FileShare;
using StorageService.API.Application.Queries;
using StorageService.Domain.AggregatesModel.FileShareAggregate;
using Swashbuckle.AspNetCore.Annotations;
using System.Security.Claims;

namespace StorageService.API.Controllers;

/// <summary>
/// EN: Controller for file sharing operations.
/// VI: Controller cho các thao tác chia sẻ file.
/// </summary>
[ApiController]
[Route("api/v1/storage")]
[Produces("application/json")]
public class FileSharingController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<FileSharingController> _logger;

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

    /// <summary>
    /// EN: Create a share link for a file.
    /// VI: Tạo link chia sẻ cho file.
    /// </summary>
    [HttpPost("files/{fileId:guid}/shares")]
    [Authorize]
    [SwaggerOperation(Summary = "Create file share", Description = "Create a share link for a file")]
    [SwaggerResponse(201, "Share created successfully", typeof(ApiResponse<CreateShareResponse>))]
    [SwaggerResponse(400, "Bad request")]
    [SwaggerResponse(401, "Unauthorized")]
    [SwaggerResponse(404, "File not found")]
    public async Task<ActionResult<ApiResponse<CreateShareResponse>>> CreateShare(
        [FromRoute] Guid fileId,
        [FromBody] CreateShareRequest request)
    {
        var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (string.IsNullOrEmpty(userId))
        {
            return Unauthorized(new ApiResponse<CreateShareResponse> { Success = false, Error = "User ID not found" });
        }

        // EN: Parse permission / VI: Parse permission
        if (!Enum.TryParse<SharePermission>(request.Permission, true, out var permission))
        {
            return BadRequest(new ApiResponse<CreateShareResponse> 
            { 
                Success = false, 
                Error = "Invalid permission. Valid values: View, Download, Edit, Admin" 
            });
        }

        var command = new CreateFileShareCommand(
            FileId: fileId,
            UserId: userId,
            Permission: permission,
            SharedWith: request.SharedWith,
            Password: request.Password,
            ExpiresAt: request.ExpiresAt,
            MaxDownloads: request.MaxDownloads);

        var result = await _mediator.Send(command);

        if (!result.Success)
        {
            if (result.Error == "File not found.")
                return NotFound(new ApiResponse<CreateShareResponse> { Success = false, Error = result.Error });
            
            return BadRequest(new ApiResponse<CreateShareResponse> { Success = false, Error = result.Error });
        }

        return CreatedAtAction(
            nameof(GetFileShares),
            new { fileId },
            new ApiResponse<CreateShareResponse>
            {
                Success = true,
                Data = new CreateShareResponse(
                    result.ShareId!.Value,
                    result.ShareToken!,
                    result.ShareUrl!)
            });
    }

    /// <summary>
    /// EN: Get all shares for a file.
    /// VI: Lấy tất cả shares của một file.
    /// </summary>
    [HttpGet("files/{fileId:guid}/shares")]
    [Authorize]
    [SwaggerOperation(Summary = "Get file shares", Description = "Get all share links for a file")]
    [SwaggerResponse(200, "Shares retrieved", typeof(ApiResponse<IEnumerable<FileShareDto>>))]
    [SwaggerResponse(401, "Unauthorized")]
    public async Task<ActionResult<ApiResponse<IEnumerable<FileShareDto>>>> GetFileShares([FromRoute] Guid fileId)
    {
        var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (string.IsNullOrEmpty(userId))
        {
            return Unauthorized(new ApiResponse<IEnumerable<FileShareDto>> { Success = false, Error = "User ID not found" });
        }

        var query = new GetFileSharesQuery(fileId, userId);
        var shares = await _mediator.Send(query);

        return Ok(new ApiResponse<IEnumerable<FileShareDto>>
        {
            Success = true,
            Data = shares
        });
    }

    /// <summary>
    /// EN: Revoke a file share.
    /// VI: Thu hồi một file share.
    /// </summary>
    [HttpDelete("shares/{shareId:guid}")]
    [Authorize]
    [SwaggerOperation(Summary = "Revoke share", Description = "Revoke a share link")]
    [SwaggerResponse(204, "Share revoked")]
    [SwaggerResponse(401, "Unauthorized")]
    [SwaggerResponse(404, "Share not found")]
    public async Task<IActionResult> RevokeShare([FromRoute] Guid shareId)
    {
        var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (string.IsNullOrEmpty(userId))
        {
            return Unauthorized(new ApiResponse<object> { Success = false, Error = "User ID not found" });
        }

        var command = new RevokeFileShareCommand(shareId, userId);
        var result = await _mediator.Send(command);

        if (!result.Success)
        {
            if (result.Error == "Share not found.")
                return NotFound(new ApiResponse<object> { Success = false, Error = result.Error });
            
            return BadRequest(new ApiResponse<object> { Success = false, Error = result.Error });
        }

        return NoContent();
    }

    /// <summary>
    /// EN: Access a shared file by token (public endpoint).
    /// VI: Truy cập file được chia sẻ bằng token (endpoint công khai).
    /// </summary>
    [HttpGet("shares/public/{token}")]
    [AllowAnonymous]
    [SwaggerOperation(Summary = "Access shared file", Description = "Access a shared file using share token (public)")]
    [SwaggerResponse(200, "File access granted", typeof(ApiResponse<SharedFileAccessResult>))]
    [SwaggerResponse(400, "Invalid password")]
    [SwaggerResponse(404, "Share not found or expired")]
    public async Task<ActionResult<ApiResponse<SharedFileAccessResult>>> AccessSharedFile(
        [FromRoute] string token,
        [FromQuery] string? password = null)
    {
        var query = new AccessSharedFileQuery(token, password);
        var result = await _mediator.Send(query);

        if (!result.Success)
        {
            if (result.Error!.Contains("not found") || result.Error.Contains("expired"))
                return NotFound(new ApiResponse<SharedFileAccessResult> { Success = false, Error = result.Error });
            
            return BadRequest(new ApiResponse<SharedFileAccessResult> { Success = false, Error = result.Error });
        }

        return Ok(new ApiResponse<SharedFileAccessResult>
        {
            Success = true,
            Data = result
        });
    }
}

#region Request/Response DTOs

/// <summary>
/// EN: Request to create a file share.
/// VI: Request tạo file share.
/// </summary>
public record CreateShareRequest(
    string Permission = "Download",
    string? SharedWith = null,
    string? Password = null,
    DateTime? ExpiresAt = null,
    int? MaxDownloads = null);

/// <summary>
/// EN: Response for created share.
/// VI: Response cho share đã tạo.
/// </summary>
public record CreateShareResponse(
    Guid ShareId,
    string ShareToken,
    string ShareUrl);

#endregion

