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

namespace ClaudeDo.Data.Tests;

public sealed class CreateChildTests : IDisposable
{
    private readonly string _dbPath;
    private readonly ClaudeDoDbContext _ctx;

    public CreateChildTests()
    {
        _dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_test_{Guid.NewGuid():N}.db");
        var options = new DbContextOptionsBuilder<ClaudeDoDbContext>()
            .UseSqlite($"Data Source={_dbPath}")
            .Options;
        _ctx = new ClaudeDoDbContext(options);
        _ctx.Database.EnsureCreated();
    }

    public void Dispose()
    {
        _ctx.Dispose();
        try { File.Delete(_dbPath); } catch { }
        try { File.Delete(_dbPath + "-wal"); } catch { }
        try { File.Delete(_dbPath + "-shm"); } catch { }
    }

    private async Task<string> SeedListAsync(string id = "l1")
    {
        _ctx.Lists.Add(new ListEntity { Id = id, Name = "Test List", CreatedAt = DateTime.UtcNow });
        await _ctx.SaveChangesAsync();
        return id;
    }

    // ---- Task 1 ----

    [Fact]
    public async Task WaitingForChildren_roundtrips_through_value_converter()
    {
        await SeedListAsync();
        var taskId = Guid.NewGuid().ToString();
        _ctx.Tasks.Add(new TaskEntity
        {
            Id = taskId,
            ListId = "l1",
            Title = "Parent",
            Status = TaskStatus.WaitingForChildren,
            CreatedAt = DateTime.UtcNow,
        });
        await _ctx.SaveChangesAsync();
        _ctx.ChangeTracker.Clear();

        var loaded = await _ctx.Tasks.AsNoTracking().FirstAsync(t => t.Id == taskId);
        Assert.Equal(TaskStatus.WaitingForChildren, loaded.Status);
    }

    // ---- Task 2 ----

    [Fact]
    public async Task CreateChild_attaches_to_non_planning_parent_and_stamps_createdBy()
    {
        await SeedListAsync();
        var parentId = "p1";
        _ctx.Tasks.Add(new TaskEntity
        {
            Id = parentId,
            ListId = "l1",
            Title = "Parent",
            Status = TaskStatus.Running,
            PlanningPhase = PlanningPhase.None,
            CreatedAt = DateTime.UtcNow,
        });
        await _ctx.SaveChangesAsync();

        var child = await new TaskRepository(_ctx).CreateChildAsync(
            "p1", "Refactor X", "desc", commitType: null, createdBy: "p1");

        Assert.Equal("p1", child.ParentTaskId);
        Assert.Equal("p1", child.CreatedBy);
        Assert.Equal(TaskStatus.Idle, child.Status);
        Assert.Equal("l1", child.ListId);
    }

    [Fact]
    public async Task CreateChild_throws_when_parent_missing()
    {
        await SeedListAsync();

        await Assert.ThrowsAsync<InvalidOperationException>(() =>
            new TaskRepository(_ctx).CreateChildAsync("nope", "T", null, null, null));
    }
}
