using Database.Models;
using Microsoft.EntityFrameworkCore;

namespace Database.Services
{
    public interface IPackageRepository
    {
        Task<Package?> GetByIdAsync(int id);
        Task<List<Package>> GetAllAsync();
        Task<List<Package>> GetByProjectIdAsync(int projectId);
        Task<List<Package>> GetByStatusAsync(string status);
        Task<Package> CreateAsync(Package package);
        Task<Package> UpdateAsync(Package package);
        Task DeleteAsync(int id, string deletedBy);
        Task<bool> ExistsAsync(int id);
        Task<PackageConfiguration?> GetConfigurationAsync(int packageId);
        Task<PackageConfiguration> SaveConfigurationAsync(PackageConfiguration config);
    }
    
    public class PackageRepository : IPackageRepository
    {
        private readonly DatabaseContext _context;
        
        public PackageRepository(DatabaseContext context)
        {
            _context = context;
        }
        
        public async Task<Package?> GetByIdAsync(int id)
        {
            return await _context.Packages
                .Include(p => p.Project)
                .Include(p => p.SourceBuild)
                .Include(p => p.Configuration)
                .Include(p => p.Publications)
                .FirstOrDefaultAsync(p => p.Id == id);
        }
        
        public async Task<List<Package>> GetAllAsync()
        {
            return await _context.Packages
                .Include(p => p.Project)
                .Include(p => p.SourceBuild)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }
        
        public async Task<List<Package>> GetByProjectIdAsync(int projectId)
        {
            return await _context.Packages
                .Include(p => p.Project)
                .Include(p => p.SourceBuild)
                .Where(p => p.ProjectId == projectId)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }
        
        public async Task<List<Package>> GetByStatusAsync(string status)
        {
            return await _context.Packages
                .Include(p => p.Project)
                .Include(p => p.SourceBuild)
                .Where(p => p.Status == status)
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();
        }
        
        public async Task<Package> CreateAsync(Package package)
        {
            _context.Packages.Add(package);
            await _context.SaveChangesAsync();
            return package;
        }
        
        public async Task<Package> UpdateAsync(Package package)
        {
            package.UpdateTimestamp(package.UpdatedBy ?? "System");
            _context.Packages.Update(package);
            await _context.SaveChangesAsync();
            return package;
        }
        
        public async Task DeleteAsync(int id, string deletedBy)
        {
            var package = await GetByIdAsync(id);
            if (package != null)
            {
                package.MarkAsDeleted(deletedBy);
                await _context.SaveChangesAsync();
            }
        }
        
        public async Task<bool> ExistsAsync(int id)
        {
            return await _context.Packages.AnyAsync(p => p.Id == id);
        }
        
        public async Task<PackageConfiguration?> GetConfigurationAsync(int packageId)
        {
            return await _context.PackageConfigurations
                .FirstOrDefaultAsync(pc => pc.PackageId == packageId);
        }
        
        public async Task<PackageConfiguration> SaveConfigurationAsync(PackageConfiguration config)
        {
            var existing = await GetConfigurationAsync(config.PackageId);
            
            if (existing != null)
            {
                existing.BuildFolder = config.BuildFolder;
                existing.ZipContents = config.ZipContents;
                existing.DeleteOldPublishedBuilds = config.DeleteOldPublishedBuilds;
                existing.ReleaseNoteTemplate = config.ReleaseNoteTemplate;
                existing.StorageSettings = config.StorageSettings;
                existing.HelpCenterSettings = config.HelpCenterSettings;
                existing.UpdateTimestamp(config.UpdatedBy ?? "System");
                
                _context.PackageConfigurations.Update(existing);
                await _context.SaveChangesAsync();
                return existing;
            }
            else
            {
                _context.PackageConfigurations.Add(config);
                await _context.SaveChangesAsync();
                return config;
            }
        }
    }
}