using Microsoft.EntityFrameworkCore;
using WhatsAppService.Domain.AggregatesModel.CustomerAggregate;
using WhatsAppService.Domain.SeedWork;

namespace WhatsAppService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Customer aggregate.
/// VI: Triển khai repository cho Customer aggregate.
/// </summary>
public class CustomerRepository : ICustomerRepository
{
    private readonly WhatsAppServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public CustomerRepository(WhatsAppServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<Customer> AddAsync(Customer customer, CancellationToken cancellationToken = default)
    {
        var entry = await _context.Customers.AddAsync(customer, cancellationToken);
        return entry.Entity;
    }

    public void Update(Customer customer)
    {
        _context.Entry(customer).State = EntityState.Modified;
    }

    public async Task<Customer?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.Customers.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
    }

    public async Task<Customer?> GetByWaIdAsync(Guid shopId, string waId, CancellationToken cancellationToken = default)
    {
        return await _context.Customers
            .FirstOrDefaultAsync(c => 
                EF.Property<Guid>(c, "_shopId") == shopId && 
                EF.Property<string>(c, "_waId") == waId, 
                cancellationToken);
    }

    public async Task<IReadOnlyList<Customer>> GetByShopIdAsync(Guid shopId, int skip, int take, CancellationToken cancellationToken = default)
    {
        return await _context.Customers
            .Where(c => EF.Property<Guid>(c, "_shopId") == shopId)
            .OrderByDescending(c => EF.Property<DateTime>(c, "_createdAt"))
            .Skip(skip)
            .Take(take)
            .ToListAsync(cancellationToken);
    }

    public async Task<IReadOnlyList<Customer>> GetByTagsAsync(Guid shopId, IEnumerable<string> tags, CancellationToken cancellationToken = default)
    {
        var tagList = tags.ToList();
        return await _context.Customers
            .Where(c => EF.Property<Guid>(c, "_shopId") == shopId)
            .ToListAsync(cancellationToken);
        // Note: Full JSONB tag filtering would require raw SQL for optimal performance
    }
}
