using Microsoft.EntityFrameworkCore;
using MktXService.Domain.AggregatesModel.AutomationFlowAggregate;
using MktXService.Domain.SeedWork;

namespace MktXService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for AutomationFlow aggregate.
/// VI: Triển khai repository cho AutomationFlow aggregate.
/// </summary>
public class AutomationFlowRepository : IAutomationFlowRepository
{
    private readonly MktXServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public AutomationFlowRepository(MktXServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public AutomationFlow Add(AutomationFlow flow)
    {
        return _context.AutomationFlows.Add(flow).Entity;
    }

    public void Update(AutomationFlow flow)
    {
        _context.Entry(flow).State = EntityState.Modified;
    }

    public void Delete(AutomationFlow flow)
    {
        _context.AutomationFlows.Remove(flow);
    }

    public async Task<AutomationFlow?> GetByIdAsync(Guid id)
    {
        return await _context.AutomationFlows
            .Include(f => f.Status)
            .FirstOrDefaultAsync(f => f.Id == id);
    }

    public async Task<AutomationFlow?> GetByIdWithNodesAsync(Guid id)
    {
        return await _context.AutomationFlows
            .Include(f => f.Status)
            .Include(f => f.Nodes)
            .Include(f => f.Connections)
            .FirstOrDefaultAsync(f => f.Id == id);
    }

    public async Task<IEnumerable<AutomationFlow>> GetByMerchantIdAsync(Guid merchantId)
    {
        return await _context.AutomationFlows
            .Include(f => f.Status)
            .Where(f => EF.Property<Guid>(f, "_merchantId") == merchantId)
            .OrderByDescending(f => EF.Property<DateTime>(f, "_createdAt"))
            .ToListAsync();
    }

    public async Task<IEnumerable<AutomationFlow>> GetActiveByMerchantIdAsync(Guid merchantId)
    {
        return await _context.AutomationFlows
            .Include(f => f.Status)
            .Include(f => f.Nodes)
            .Include(f => f.Connections)
            .Where(f => EF.Property<Guid>(f, "_merchantId") == merchantId && 
                        f.StatusId == FlowStatus.Active.Id)
            .ToListAsync();
    }

    public async Task<IEnumerable<AutomationFlow>> GetByTriggerTypeAsync(Guid merchantId, string triggerType)
    {
        // EN: For JSONB query, we filter by trigger type
        // VI: Với truy vấn JSONB, chúng ta lọc theo trigger type
        return await _context.AutomationFlows
            .Include(f => f.Status)
            .Include(f => f.Nodes)
            .Include(f => f.Connections)
            .Where(f => EF.Property<Guid>(f, "_merchantId") == merchantId && 
                        f.StatusId == FlowStatus.Active.Id)
            .ToListAsync()
            // EN: Filter in-memory for JSONB trigger type
            // VI: Lọc trong bộ nhớ cho trigger type JSONB
            .ContinueWith(t => t.Result.Where(f => f.Trigger.Type == triggerType));
    }
}
