using MediatR;
using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Application.Common.Models;
using SolutionErp.Application.Master.Suppliers.Dtos;
using SolutionErp.Domain.Master;

namespace SolutionErp.Application.Master.Suppliers.Queries.ListSuppliers;

// Published: null = tất cả (admin quản lý, thấy cả nháp) · true = chỉ NCC đã công bố (picker/consumer) · false = chỉ nháp.
public record ListSuppliersQuery(SupplierType? Type = null, bool? Published = null) : PagedRequest, IRequest<PagedResult<SupplierDto>>;

public class ListSuppliersQueryHandler : IRequestHandler<ListSuppliersQuery, PagedResult<SupplierDto>>
{
    private readonly IApplicationDbContext _db;

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

    public async Task<PagedResult<SupplierDto>> Handle(ListSuppliersQuery request, CancellationToken ct)
    {
        var query = _db.Suppliers.AsNoTracking();

        if (request.Type is not null)
            query = query.Where(x => x.Type == request.Type);

        if (request.Published is not null)
        {
            var pub = request.Published.Value;            // local → EF dịch được (tránh nullable bool trong expr)
            query = query.Where(x => x.IsPublic == pub);
        }

        if (!string.IsNullOrWhiteSpace(request.Search))
        {
            var s = request.Search.Trim();
            query = query.Where(x =>
                x.Code.Contains(s) || x.Name.Contains(s) ||
                (x.TaxCode != null && x.TaxCode.Contains(s)));
        }

        query = (request.SortBy, request.SortDesc) switch
        {
            ("code", true) => query.OrderByDescending(x => x.Code),
            ("code", false) => query.OrderBy(x => x.Code),
            ("name", true) => query.OrderByDescending(x => x.Name),
            ("name", false) => query.OrderBy(x => x.Name),
            ("type", true) => query.OrderByDescending(x => x.Type),
            ("type", false) => query.OrderBy(x => x.Type),
            _ => query.OrderByDescending(x => x.CreatedAt),
        };

        var total = await query.CountAsync(ct);
        var items = await query
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .Select(x => new SupplierDto(
                x.Id, x.Code, x.Name, x.Type, x.TaxCode, x.Phone, x.Email, x.Address, x.ContactPerson, x.Note,
                x.PackageCategory, x.OfficeAddress, x.MailingAddress, x.Fax, x.BankAccount, x.SecondaryBankAccount,
                x.LegalRepresentative, x.LegalRepTitle, x.AuthorizationNote, x.LinkGuq, x.LinkGpkd, x.LinkHsnl,
                x.ContactTitle, x.ContactPhone, x.MailRecipient, x.ReferralSource, x.OwnerPmh, x.Status,
                x.SourceUpdatedAt, x.SourceUpdatedBy,
                x.CreatedAt, x.UpdatedAt, x.IsPublic))
            .ToListAsync(ct);

        return new PagedResult<SupplierDto>(items, total, request.Page, request.PageSize);
    }
}
