using Knot.Shared.Kernel;
using Knot.Contracts.Profiles.Domain;
using Knot.Contracts.Profiles.Application.DTOs;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Knot.Modules.Profiles.Application.Profiles.Avatar;

public sealed record UploadAvatarCommand(
    Guid UserId,
    Stream FileStream,
    string FileName,
    string ContentType) : ICommand<UserProfileDto>;

internal sealed class UploadAvatarCommandHandler : ICommandHandler<UploadAvatarCommand, UserProfileDto>
{
    private readonly IProfileRepository _repository;
    private readonly IAvatarStorageService _avatarStorage;
    private readonly Knot.Contracts.Auth.Domain.IUserRepository _userRepository;

    public UploadAvatarCommandHandler(
        IProfileRepository repository, 
        IAvatarStorageService avatarStorage,
        Knot.Contracts.Auth.Domain.IUserRepository userRepository)
    {
        _repository = repository;
        _avatarStorage = avatarStorage;
        _userRepository = userRepository;
    }

    public async Task<Result<UserProfileDto>> Handle(UploadAvatarCommand request, CancellationToken cancellationToken)
    {
        var profile = await _repository.GetAsync(request.UserId, cancellationToken);
        if (profile is null)
            return Result.Failure<UserProfileDto>(ProfilesErrors.ProfileNotFound);

        if (!string.IsNullOrEmpty(profile.Avatar))
            await _avatarStorage.DeleteAsync(profile.Avatar, cancellationToken);

        var fileId = await _avatarStorage.UploadAsync(request.FileStream, request.FileName, request.ContentType, cancellationToken);
        var avatarUrl = $"/api/files/{fileId}";

        // Синхронизируем с основным модулем пользователей (Auth/Postgres)
        var userContract = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
        if (userContract != null)
        {
            userContract.Avatar = avatarUrl;
            await _userRepository.UpdateAsync(userContract, cancellationToken);
        }

        profile.Avatar = avatarUrl;
        var result = await _repository.UpdateAsync(profile, cancellationToken);
        if (result.IsFailure)
            return Result.Failure<UserProfileDto>(result.Error);

        return Result.Success(result.Value);
    }
}

public sealed record DeleteAvatarCommand(Guid UserId) : ICommand<UserProfileDto>;

internal sealed class DeleteAvatarCommandHandler : ICommandHandler<DeleteAvatarCommand, UserProfileDto>
{
    private readonly IProfileRepository _repository;
    private readonly IAvatarStorageService _avatarStorage;
    private readonly Knot.Contracts.Auth.Domain.IUserRepository _userRepository;

    public DeleteAvatarCommandHandler(
        IProfileRepository repository, 
        IAvatarStorageService avatarStorage,
        Knot.Contracts.Auth.Domain.IUserRepository userRepository)
    {
        _repository = repository;
        _avatarStorage = avatarStorage;
        _userRepository = userRepository;
    }

    public async Task<Result<UserProfileDto>> Handle(DeleteAvatarCommand request, CancellationToken cancellationToken)
    {
        var profile = await _repository.GetAsync(request.UserId, cancellationToken);
        if (profile is null)
            return Result.Failure<UserProfileDto>(ProfilesErrors.ProfileNotFound);

        if (!string.IsNullOrEmpty(profile.Avatar))
            await _avatarStorage.DeleteAsync(profile.Avatar, cancellationToken);

        // Синхронизируем с основным модулем пользователей (Auth/Postgres)
        var userContract = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
        if (userContract != null)
        {
            userContract.Avatar = null;
            await _userRepository.UpdateAsync(userContract, cancellationToken);
        }

        profile.Avatar = null;
        var result = await _repository.UpdateAsync(profile, cancellationToken);
        if (result.IsFailure)
            return Result.Failure<UserProfileDto>(result.Error);

        return Result.Success(result.Value);
    }
}
