using Database.Models;
using Microsoft.EntityFrameworkCore;

namespace Database.Services
{
    public interface IBuildRepository
    {
        Task<Build?> GetByIdAsync(int id);
        Task<Build?> GetByProjectAndBuildNumberAsync(int projectId, string buildNumber);
        Task<List<Build>> GetByProjectIdAsync(int projectId);
        Task<List<Build>> GetSuccessfulBuildsByProjectIdAsync(int projectId);
        Task<List<Build>> GetRecentBuildsAsync(int count = 50);
        Task<Build> CreateAsync(Build build);
        Task<Build> UpdateAsync(Build build);
        Task DeleteAsync(int id, string deletedBy);
        Task<bool> ExistsAsync(int id);
        Task<List<BuildCommit>> GetCommitsByBuildIdAsync(int buildId);
        Task<BuildCommit> CreateCommitAsync(BuildCommit commit);
        Task<List<BuildCommit>> CreateCommitsAsync(List<BuildCommit> commits);
    }
    
    public class BuildRepository : IBuildRepository
    {
        private readonly DatabaseContext _context;
        
        public BuildRepository(DatabaseContext context)
        {
            _context = context;
        }
        
        public async Task<Build?> GetByIdAsync(int id)
        {
            return await _context.Builds
                .Include(b => b.Project)
                .Include(b => b.Commits)
                .ThenInclude(c => c.FogBugzCase)
                .FirstOrDefaultAsync(b => b.Id == id);
        }
        
        public async Task<Build?> GetByProjectAndBuildNumberAsync(int projectId, string buildNumber)
        {
            return await _context.Builds
                .Include(b => b.Project)
                .Include(b => b.Commits)
                .FirstOrDefaultAsync(b => b.ProjectId == projectId && b.BuildNumber == buildNumber);
        }
        
        public async Task<List<Build>> GetByProjectIdAsync(int projectId)
        {
            return await _context.Builds
                .Include(b => b.Project)
                .Where(b => b.ProjectId == projectId)
                .OrderByDescending(b => b.StartTime)
                .ToListAsync();
        }
        
        public async Task<List<Build>> GetSuccessfulBuildsByProjectIdAsync(int projectId)
        {
            return await _context.Builds
                .Include(b => b.Project)
                .Where(b => b.ProjectId == projectId && b.Status == "Success")
                .OrderByDescending(b => b.StartTime)
                .ToListAsync();
        }
        
        public async Task<List<Build>> GetRecentBuildsAsync(int count = 50)
        {
            return await _context.Builds
                .Include(b => b.Project)
                .OrderByDescending(b => b.StartTime)
                .Take(count)
                .ToListAsync();
        }
        
        public async Task<Build> CreateAsync(Build build)
        {
            _context.Builds.Add(build);
            await _context.SaveChangesAsync();
            return build;
        }
        
        public async Task<Build> UpdateAsync(Build build)
        {
            build.UpdateTimestamp(build.UpdatedBy ?? "System");
            _context.Builds.Update(build);
            await _context.SaveChangesAsync();
            return build;
        }
        
        public async Task DeleteAsync(int id, string deletedBy)
        {
            var build = await GetByIdAsync(id);
            if (build != null)
            {
                build.MarkAsDeleted(deletedBy);
                await _context.SaveChangesAsync();
            }
        }
        
        public async Task<bool> ExistsAsync(int id)
        {
            return await _context.Builds.AnyAsync(b => b.Id == id);
        }
        
        public async Task<List<BuildCommit>> GetCommitsByBuildIdAsync(int buildId)
        {
            return await _context.BuildCommits
                .Include(c => c.Build)
                .Include(c => c.FogBugzCase)
                .Where(c => c.BuildId == buildId)
                .OrderByDescending(c => c.CommitDate)
                .ToListAsync();
        }
        
        public async Task<BuildCommit> CreateCommitAsync(BuildCommit commit)
        {
            _context.BuildCommits.Add(commit);
            await _context.SaveChangesAsync();
            return commit;
        }
        
        public async Task<List<BuildCommit>> CreateCommitsAsync(List<BuildCommit> commits)
        {
            _context.BuildCommits.AddRange(commits);
            await _context.SaveChangesAsync();
            return commits;
        }
    }
}