using ClaudeDo.Data;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;

namespace ClaudeDo.Data.Tests;

/// <summary>
/// Verifies that TaskRepository.DeleteAsync and ListRepository.DeleteAsync
/// delete the on-disk attachment directories for the affected tasks.
/// </summary>
public sealed class RepositoryAttachmentCleanupTests : IDisposable
{
    private readonly string _dbPath;
    private readonly string _attachRoot;
    private readonly ClaudeDoDbContext _ctx;
    private readonly AttachmentStore _store;

    public RepositoryAttachmentCleanupTests()
    {
        _dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_repoclean_{Guid.NewGuid():N}.db");
        _attachRoot = Path.Combine(Path.GetTempPath(), $"claudedo_repoclean_att_{Guid.NewGuid():N}");
        Directory.CreateDirectory(_attachRoot);

        var options = new DbContextOptionsBuilder<ClaudeDoDbContext>()
            .UseSqlite($"Data Source={_dbPath}")
            .Options;
        _ctx = new ClaudeDoDbContext(options);
        _ctx.Database.EnsureCreated();
        _store = new AttachmentStore(_attachRoot);
    }

    public void Dispose()
    {
        _ctx.Dispose();
        foreach (var suffix in new[] { "", "-wal", "-shm" })
            try { File.Delete(_dbPath + suffix); } catch { }
        try { Directory.Delete(_attachRoot, recursive: true); } catch { }
    }

    private async Task<(string listId, string taskId)> SeedAsync()
    {
        var listId = Guid.NewGuid().ToString();
        var taskId = Guid.NewGuid().ToString();
        _ctx.Lists.Add(new ListEntity { Id = listId, Name = "L", CreatedAt = DateTime.UtcNow });
        _ctx.Tasks.Add(new TaskEntity
        {
            Id = taskId, ListId = listId, Title = "T",
            Status = TaskStatus.Idle, CreatedAt = DateTime.UtcNow,
        });
        await _ctx.SaveChangesAsync();
        return (listId, taskId);
    }

    [Fact]
    public async Task TaskRepository_DeleteAsync_RemovesAttachmentDir()
    {
        var (_, taskId) = await SeedAsync();

        var taskDir = _store.TaskDir(taskId);
        Directory.CreateDirectory(taskDir);
        Assert.True(Directory.Exists(taskDir));

        var repo = new TaskRepository(_ctx, _store);
        await repo.DeleteAsync(taskId);

        Assert.False(Directory.Exists(taskDir));
    }

    [Fact]
    public async Task ListRepository_DeleteAsync_RemovesAttachmentDirForEachTask()
    {
        var (listId, taskId) = await SeedAsync();

        var taskDir = _store.TaskDir(taskId);
        Directory.CreateDirectory(taskDir);
        Assert.True(Directory.Exists(taskDir));

        var repo = new ListRepository(_ctx, _store);
        await repo.DeleteAsync(listId);

        Assert.False(Directory.Exists(taskDir));
    }
}
