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

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

public record UpdateSupplierCommand(
    Guid Id,
    string Code,
    string Name,
    SupplierType Type,
    string? TaxCode,
    string? Phone,
    string? Email,
    string? Address,
    string? ContactPerson,
    string? Note,
    // S? go-live expansion — 18 field bổ sung, tất cả TRAILING OPTIONAL (= null). FE sửa tay gửi đủ field.
    string? PackageCategory = null,
    string? OfficeAddress = null,
    string? MailingAddress = null,
    string? Fax = null,
    string? BankAccount = null,
    string? SecondaryBankAccount = null,
    string? LegalRepresentative = null,
    string? LegalRepTitle = null,
    string? AuthorizationNote = null,
    string? LinkGuq = null,
    string? LinkGpkd = null,
    string? LinkHsnl = null,
    string? ContactTitle = null,
    string? ContactPhone = null,
    string? MailRecipient = null,
    string? ReferralSource = null,
    string? OwnerPmh = null,
    SupplierStatus? Status = null) : IRequest;

public class UpdateSupplierCommandValidator : AbstractValidator<UpdateSupplierCommand>
{
    public UpdateSupplierCommandValidator()
    {
        RuleFor(x => x.Id).NotEmpty();
        RuleFor(x => x.Code).NotEmpty().MaximumLength(50);
        RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
        RuleFor(x => x.Type).IsInEnum();
        RuleFor(x => x.Email).EmailAddress().When(x => !string.IsNullOrWhiteSpace(x.Email));
        // S? — new fields OPTIONAL: MaximumLength ONLY, KHÔNG NotEmpty.
        RuleFor(x => x.PackageCategory).MaximumLength(300);
        RuleFor(x => x.OfficeAddress).MaximumLength(500);
        RuleFor(x => x.MailingAddress).MaximumLength(500);
        RuleFor(x => x.Fax).MaximumLength(50);
        RuleFor(x => x.BankAccount).MaximumLength(500);
        RuleFor(x => x.SecondaryBankAccount).MaximumLength(500);
        RuleFor(x => x.LegalRepresentative).MaximumLength(200);
        RuleFor(x => x.LegalRepTitle).MaximumLength(150);
        RuleFor(x => x.AuthorizationNote).MaximumLength(1000);
        RuleFor(x => x.LinkGuq).MaximumLength(1000);
        RuleFor(x => x.LinkGpkd).MaximumLength(1000);
        RuleFor(x => x.LinkHsnl).MaximumLength(1000);
        RuleFor(x => x.ContactTitle).MaximumLength(150);
        RuleFor(x => x.ContactPhone).MaximumLength(50);
        RuleFor(x => x.MailRecipient).MaximumLength(200);
        RuleFor(x => x.ReferralSource).MaximumLength(300);
        RuleFor(x => x.OwnerPmh).MaximumLength(150);
    }
}

public class UpdateSupplierCommandHandler : IRequestHandler<UpdateSupplierCommand>
{
    private readonly IApplicationDbContext _db;

    public UpdateSupplierCommandHandler(IApplicationDbContext db) => _db = db;

    public async Task Handle(UpdateSupplierCommand request, CancellationToken ct)
    {
        var entity = await _db.Suppliers.FirstOrDefaultAsync(x => x.Id == request.Id, ct)
            ?? throw new NotFoundException("Supplier", request.Id);

        if (entity.Code != request.Code &&
            await _db.Suppliers.AnyAsync(x => x.Code == request.Code && x.Id != request.Id, ct))
            throw new ConflictException($"Mã NCC '{request.Code}' đã tồn tại.");

        entity.Code = request.Code;
        entity.Name = request.Name;
        entity.Type = request.Type;
        entity.TaxCode = request.TaxCode;
        entity.Phone = request.Phone;
        entity.Email = request.Email;
        entity.Address = request.Address;
        entity.ContactPerson = request.ContactPerson;
        entity.Note = request.Note;
        entity.PackageCategory = request.PackageCategory;
        entity.OfficeAddress = request.OfficeAddress;
        entity.MailingAddress = request.MailingAddress;
        entity.Fax = request.Fax;
        entity.BankAccount = request.BankAccount;
        entity.SecondaryBankAccount = request.SecondaryBankAccount;
        entity.LegalRepresentative = request.LegalRepresentative;
        entity.LegalRepTitle = request.LegalRepTitle;
        entity.AuthorizationNote = request.AuthorizationNote;
        entity.LinkGuq = request.LinkGuq;
        entity.LinkGpkd = request.LinkGpkd;
        entity.LinkHsnl = request.LinkHsnl;
        entity.ContactTitle = request.ContactTitle;
        entity.ContactPhone = request.ContactPhone;
        entity.MailRecipient = request.MailRecipient;
        entity.ReferralSource = request.ReferralSource;
        entity.OwnerPmh = request.OwnerPmh;
        entity.Status = request.Status;

        await _db.SaveChangesAsync(ct);
    }
}
