using Microsoft.EntityFrameworkCore;
using MktZaloService.Domain.AggregatesModel.ConversationAggregate;
using MktZaloService.Domain.Enums;
using MktZaloService.Domain.SeedWork;

namespace MktZaloService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Conversation aggregate.
/// VI: Repository implementation cho Conversation aggregate.
/// </summary>
public class ConversationRepository : IConversationRepository
{
    private readonly MktZaloServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public ConversationRepository(MktZaloServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    /// <summary>
    /// EN: Get conversation by ID (without messages).
    /// VI: Lấy cuộc hội thoại theo ID (không bao gồm tin nhắn).
    /// </summary>
    public async Task<Conversation?> GetByIdAsync(Guid id, CancellationToken ct = default)
    {
        return await _context.Conversations
            .FirstOrDefaultAsync(c => c.Id == id, ct);
    }

    /// <summary>
    /// EN: Get conversation by ID with paginated messages.
    /// VI: Lấy cuộc hội thoại theo ID với tin nhắn phân trang.
    /// </summary>
    public async Task<Conversation?> GetByIdWithMessagesAsync(
        Guid id,
        int skip = 0,
        int take = 50,
        CancellationToken ct = default)
    {
        var conversation = await _context.Conversations
            .FirstOrDefaultAsync(c => c.Id == id, ct);

        if (conversation == null) return null;

        // EN: Load messages separately with pagination (most recent first)
        // VI: Load tin nhắn riêng với phân trang (mới nhất trước)
        await _context.Entry(conversation)
            .Collection(c => c.Messages)
            .Query()
            .OrderByDescending(m => m.SentAt)
            .Skip(skip)
            .Take(take)
            .LoadAsync(ct);

        return conversation;
    }

    /// <summary>
    /// EN: Find active conversation by Zalo user ID.
    /// VI: Tìm cuộc hội thoại đang hoạt động theo Zalo user ID.
    /// </summary>
    public async Task<Conversation?> FindActiveByZaloUserIdAsync(
        string zaloUserId,
        CancellationToken ct = default)
    {
        return await _context.Conversations
            .Where(c => c.ZaloUserId == zaloUserId && c.Status == ConversationStatus.Active)
            .OrderByDescending(c => c.StartedAt)
            .FirstOrDefaultAsync(ct);
    }

    /// <summary>
    /// EN: Add a new conversation.
    /// VI: Thêm cuộc hội thoại mới.
    /// </summary>
    public Conversation Add(Conversation conversation)
    {
        return _context.Conversations.Add(conversation).Entity;
    }

    /// <summary>
    /// EN: Update an existing conversation.
    /// VI: Cập nhật cuộc hội thoại hiện có.
    /// </summary>
    public void Update(Conversation conversation)
    {
        _context.Entry(conversation).State = EntityState.Modified;
    }
}
