using Database.Models;
using Microsoft.EntityFrameworkCore;

namespace Database.Services
{
    public interface IPublicationRepository
    {
        Task<Publication?> GetByIdAsync(int id);
        Task<List<Publication>> GetByPackageIdAsync(int packageId);
        Task<List<Publication>> GetByStatusAsync(string status);
        Task<List<Publication>> GetRecentPublicationsAsync(int count = 50);
        Task<Publication> CreateAsync(Publication publication);
        Task<Publication> UpdateAsync(Publication publication);
        Task DeleteAsync(int id, string deletedBy);
        Task<bool> ExistsAsync(int id);
        
        Task<List<PublishingStep>> GetStepsByPublicationIdAsync(int publicationId);
        Task<PublishingStep?> GetStepByIdAsync(int stepId);
        Task<PublishingStep> CreateStepAsync(PublishingStep step);
        Task<PublishingStep> UpdateStepAsync(PublishingStep step);
        Task<List<PublishingStep>> CreateStepsAsync(List<PublishingStep> steps);
        Task<PublishingStep?> GetCurrentStepAsync(int publicationId);
        Task<List<PublishingStep>> GetCompletedStepsAsync(int publicationId);
        Task<List<PublishingStep>> GetFailedStepsAsync(int publicationId);
    }
    
    public class PublicationRepository : IPublicationRepository
    {
        private readonly DatabaseContext _context;
        
        public PublicationRepository(DatabaseContext context)
        {
            _context = context;
        }
        
        public async Task<Publication?> GetByIdAsync(int id)
        {
            return await _context.Publications
                .Include(p => p.Package)
                .ThenInclude(pkg => pkg.Project)
                .Include(p => p.Steps.OrderBy(s => s.StepOrder))
                .FirstOrDefaultAsync(p => p.Id == id);
        }
        
        public async Task<List<Publication>> GetByPackageIdAsync(int packageId)
        {
            return await _context.Publications
                .Include(p => p.Package)
                .Include(p => p.Steps)
                .Where(p => p.PackageId == packageId)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }
        
        public async Task<List<Publication>> GetByStatusAsync(string status)
        {
            return await _context.Publications
                .Include(p => p.Package)
                .ThenInclude(pkg => pkg.Project)
                .Where(p => p.Status == status)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }
        
        public async Task<List<Publication>> GetRecentPublicationsAsync(int count = 50)
        {
            return await _context.Publications
                .Include(p => p.Package)
                .ThenInclude(pkg => pkg.Project)
                .OrderByDescending(p => p.CreatedAt)
                .Take(count)
                .ToListAsync();
        }
        
        public async Task<Publication> CreateAsync(Publication publication)
        {
            _context.Publications.Add(publication);
            await _context.SaveChangesAsync();
            return publication;
        }
        
        public async Task<Publication> UpdateAsync(Publication publication)
        {
            publication.UpdateTimestamp(publication.UpdatedBy ?? "System");
            _context.Publications.Update(publication);
            await _context.SaveChangesAsync();
            return publication;
        }
        
        public async Task DeleteAsync(int id, string deletedBy)
        {
            var publication = await GetByIdAsync(id);
            if (publication != null)
            {
                publication.MarkAsDeleted(deletedBy);
                await _context.SaveChangesAsync();
            }
        }
        
        public async Task<bool> ExistsAsync(int id)
        {
            return await _context.Publications.AnyAsync(p => p.Id == id);
        }
        
        public async Task<List<PublishingStep>> GetStepsByPublicationIdAsync(int publicationId)
        {
            return await _context.PublishingSteps
                .Include(s => s.Publication)
                .Where(s => s.PublicationId == publicationId)
                .OrderBy(s => s.StepOrder)
                .ToListAsync();
        }
        
        public async Task<PublishingStep?> GetStepByIdAsync(int stepId)
        {
            return await _context.PublishingSteps
                .Include(s => s.Publication)
                .FirstOrDefaultAsync(s => s.Id == stepId);
        }
        
        public async Task<PublishingStep> CreateStepAsync(PublishingStep step)
        {
            _context.PublishingSteps.Add(step);
            await _context.SaveChangesAsync();
            return step;
        }
        
        public async Task<PublishingStep> UpdateStepAsync(PublishingStep step)
        {
            step.UpdateTimestamp(step.UpdatedBy ?? "System");
            _context.PublishingSteps.Update(step);
            await _context.SaveChangesAsync();
            return step;
        }
        
        public async Task<List<PublishingStep>> CreateStepsAsync(List<PublishingStep> steps)
        {
            _context.PublishingSteps.AddRange(steps);
            await _context.SaveChangesAsync();
            return steps;
        }
        
        public async Task<PublishingStep?> GetCurrentStepAsync(int publicationId)
        {
            return await _context.PublishingSteps
                .Where(s => s.PublicationId == publicationId && 
                           (s.Status == "InProgress" || s.Status == "Pending"))
                .OrderBy(s => s.StepOrder)
                .FirstOrDefaultAsync();
        }
        
        public async Task<List<PublishingStep>> GetCompletedStepsAsync(int publicationId)
        {
            return await _context.PublishingSteps
                .Where(s => s.PublicationId == publicationId && s.Status == "Completed")
                .OrderBy(s => s.StepOrder)
                .ToListAsync();
        }
        
        public async Task<List<PublishingStep>> GetFailedStepsAsync(int publicationId)
        {
            return await _context.PublishingSteps
                .Where(s => s.PublicationId == publicationId && s.Status == "Failed")
                .OrderBy(s => s.StepOrder)
                .ToListAsync();
        }
    }
}