using ClaudeDo.Data.Models;
using Microsoft.EntityFrameworkCore;

namespace ClaudeDo.Data.Repositories;

public sealed class WorktreeRepository
{
    private readonly ClaudeDoDbContext _context;

    public WorktreeRepository(ClaudeDoDbContext context) => _context = context;

    public async Task AddAsync(WorktreeEntity entity, CancellationToken ct = default)
    {
        _context.Worktrees.Add(entity);
        await _context.SaveChangesAsync(ct);
    }

    public async Task<WorktreeEntity?> GetByTaskIdAsync(string taskId, CancellationToken ct = default)
    {
        return await _context.Worktrees.FirstOrDefaultAsync(w => w.TaskId == taskId, ct);
    }

    public async Task UpdateHeadAsync(string taskId, string headCommit, string? diffStat, CancellationToken ct = default)
    {
        await _context.Worktrees
            .Where(w => w.TaskId == taskId)
            .ExecuteUpdateAsync(s => s
                .SetProperty(w => w.HeadCommit, headCommit)
                .SetProperty(w => w.DiffStat, diffStat), ct);
    }

    public async Task SetStateAsync(string taskId, WorktreeState state, CancellationToken ct = default)
    {
        await _context.Worktrees
            .Where(w => w.TaskId == taskId)
            .ExecuteUpdateAsync(s => s.SetProperty(w => w.State, state), ct);
    }

    public async Task SetMergedAsync(string taskId, string mergeCommit, CancellationToken ct = default)
    {
        await _context.Worktrees
            .Where(w => w.TaskId == taskId)
            .ExecuteUpdateAsync(s => s
                .SetProperty(w => w.State, WorktreeState.Merged)
                .SetProperty(w => w.MergeCommit, mergeCommit), ct);
    }

    /// <summary>Records a successful auto-rebase: the branch's fork point moves to the rebased-onto
    /// commit and its head moves to the new tip <c>git rebase</c> produced.</summary>
    public async Task SetRebasedAsync(string taskId, string baseCommit, string headCommit, CancellationToken ct = default)
    {
        await _context.Worktrees
            .Where(w => w.TaskId == taskId)
            .ExecuteUpdateAsync(s => s
                .SetProperty(w => w.BaseCommit, baseCommit)
                .SetProperty(w => w.HeadCommit, headCommit), ct);
    }

    public async Task DeleteAsync(string taskId, CancellationToken ct = default)
    {
        await _context.Worktrees.Where(w => w.TaskId == taskId).ExecuteDeleteAsync(ct);
    }

    public async Task<List<WorktreeEntity>> GetAllAsync(CancellationToken ct = default)
    {
        return await _context.Worktrees.AsNoTracking().ToListAsync(ct);
    }
}
