using FluentValidation;
using MediatR;
using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Exceptions;
using SolutionErp.Application.Common.Interfaces;

namespace SolutionErp.Application.Master.Suppliers.Commands.PublishSupplier;

/// <summary>
/// Công bố / ẩn 1 NCC (Supplier import v2, S113). KHÔNG dùng UpdateSupplierCommand (blind absolute-set
/// mọi field → clobber data nháp, gotcha #73). Chỉ set Mã NCC (nếu gửi) + IsPublic.
/// <para>Gate D2: publish=true bắt buộc Code non-empty (thiếu Mã NCC → không công bố được).</para>
/// </summary>
/// <param name="Id">Supplier cần công bố/ẩn.</param>
/// <param name="MaNcc">Mã NCC mới (null = giữ nguyên Code hiện tại). Nếu gửi non-empty → unique-CI-check.</param>
/// <param name="Publish">true = công bố · false = ẩn (đưa về nháp).</param>
public sealed record PublishSupplierCommand(Guid Id, string? MaNcc, bool Publish) : IRequest;

/// <summary>Body cho endpoint POST /suppliers/{id}/publish (Id lấy từ route).</summary>
public sealed record PublishSupplierBody(string? MaNcc, bool Publish);

public sealed class PublishSupplierCommandValidator : AbstractValidator<PublishSupplierCommand>
{
    public PublishSupplierCommandValidator()
    {
        RuleFor(x => x.Id).NotEmpty();
        RuleFor(x => x.MaNcc).MaximumLength(50);   // khớp Supplier.Code HasMaxLength(50)
    }
}

public sealed class PublishSupplierCommandHandler(IApplicationDbContext db)
    : IRequestHandler<PublishSupplierCommand>
{
    public async Task Handle(PublishSupplierCommand request, CancellationToken ct)
    {
        var entity = await db.Suppliers.FirstOrDefaultAsync(x => x.Id == request.Id, ct)
            ?? throw new NotFoundException("Supplier", request.Id);

        // Đặt Mã NCC nếu gửi (blank = xóa Code → ẩn). Unique-CI-check chỉ khi non-empty
        // (Code="" bị loại khỏi filtered-unique index nên không cần check).
        if (request.MaNcc is not null)
        {
            var newCode = request.MaNcc.Trim();
            if (newCode.Length > 0 && newCode != entity.Code &&
                await db.Suppliers.AnyAsync(x => x.Code == newCode && x.Id != entity.Id, ct))
                throw new ConflictException($"Mã NCC '{newCode}' đã tồn tại.");
            entity.Code = newCode;
        }

        // Gate D2: công bố bắt buộc có Mã NCC.
        if (request.Publish && string.IsNullOrWhiteSpace(entity.Code))
            throw new ConflictException("Cần Mã NCC để công bố nhà cung cấp.");

        entity.IsPublic = request.Publish;
        await db.SaveChangesAsync(ct);
    }
}
