using MediatR;
using StorageService.Domain.AggregatesModel.FileAggregate;
using StorageService.Domain.AggregatesModel.FileShareAggregate;

// EN: Alias to avoid collision with System.IO.FileShare
// VI: Alias để tránh xung đột với System.IO.FileShare
using DomainFileShare = StorageService.Domain.AggregatesModel.FileShareAggregate.FileShare;

namespace StorageService.API.Application.Commands.FileShare;

/// <summary>
/// EN: Handler for CreateFileShareCommand.
/// VI: Handler cho CreateFileShareCommand.
/// </summary>
public class CreateFileShareCommandHandler : IRequestHandler<CreateFileShareCommand, CreateFileShareResult>
{
    private readonly IFileRepository _fileRepository;
    private readonly IFileShareRepository _fileShareRepository;
    private readonly ILogger<CreateFileShareCommandHandler> _logger;
    private readonly IConfiguration _configuration;

    public CreateFileShareCommandHandler(
        IFileRepository fileRepository,
        IFileShareRepository fileShareRepository,
        ILogger<CreateFileShareCommandHandler> logger,
        IConfiguration configuration)
    {
        _fileRepository = fileRepository;
        _fileShareRepository = fileShareRepository;
        _logger = logger;
        _configuration = configuration;
    }

    public async Task<CreateFileShareResult> Handle(CreateFileShareCommand request, CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation(
                "Creating file share for file {FileId} by user {UserId}",
                request.FileId, request.UserId);

            // EN: Verify file exists and user owns it / VI: Kiểm tra file tồn tại và user sở hữu
            var file = await _fileRepository.GetByIdAsync(request.FileId, cancellationToken);
            if (file == null)
            {
                return CreateFileShareResult.Fail("File not found.");
            }

            if (file.UserId != request.UserId)
            {
                _logger.LogWarning(
                    "User {UserId} attempted to share file {FileId} owned by {OwnerId}",
                    request.UserId, request.FileId, file.UserId);
                return CreateFileShareResult.Fail("You don't have permission to share this file.");
            }

            // EN: Create file share entity / VI: Tạo entity file share
            var fileShare = new DomainFileShare(
                fileId: request.FileId,
                sharedBy: request.UserId,
                permission: request.Permission,
                sharedWith: request.SharedWith,
                password: request.Password,
                expiresAt: request.ExpiresAt,
                maxDownloads: request.MaxDownloads);

            await _fileShareRepository.AddAsync(fileShare, cancellationToken);
            await _fileShareRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            // EN: Build share URL / VI: Xây dựng URL chia sẻ
            var baseUrl = _configuration["App:BaseUrl"] ?? "http://localhost";
            var shareUrl = $"{baseUrl}/api/v1/storage/shares/public/{fileShare.ShareToken}";

            _logger.LogInformation(
                "File share created successfully: shareId={ShareId}, token={Token}",
                fileShare.Id, fileShare.ShareToken);

            return CreateFileShareResult.Ok(fileShare.Id, fileShare.ShareToken, shareUrl);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating file share for file {FileId}", request.FileId);
            return CreateFileShareResult.Fail("An error occurred while creating the share link.");
        }
    }
}
