using ClaudeDo.Data;
using ClaudeDo.Ui.ViewModels.Modals;
using Microsoft.EntityFrameworkCore;

namespace ClaudeDo.Ui.Tests.ViewModels;

public sealed class RepoImportModalViewModelTests : IDisposable
{
    private readonly string _dbPath;

    public RepoImportModalViewModelTests()
    {
        _dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_repoimport_{Guid.NewGuid():N}.db");
        using var ctx = NewContext();
        ctx.Database.EnsureCreated();
    }

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

    private ClaudeDoDbContext NewContext()
    {
        var opts = new DbContextOptionsBuilder<ClaudeDoDbContext>()
            .UseSqlite($"Data Source={_dbPath}")
            .Options;
        return new ClaudeDoDbContext(opts);
    }


    private sealed class FakeWorkerClient : StubWorkerClient
    {
        public List<string> Folders = new();
        public Exception? ThrowOnGet;
        public Exception? ThrowOnSet;
        public List<string>? LastSaved;

        public override Task<List<string>> GetRepoImportFoldersAsync()
            => ThrowOnGet is not null ? throw ThrowOnGet : Task.FromResult(Folders);

        public override Task SetRepoImportFoldersAsync(List<string> folders)
        {
            LastSaved = folders;
            if (ThrowOnSet is not null) throw ThrowOnSet;
            return Task.CompletedTask;
        }
    }

    [Fact]
    public async Task LoadAsync_Success_PopulatesFoldersWithoutReportingError()
    {
        var worker = new FakeWorkerClient { Folders = new List<string> { @"C:\src" } };
        var vm = new RepoImportModalViewModel(new TestDbFactory(NewContext), worker);
        string? reportedError = null;
        vm.ErrorReported += msg => reportedError = msg;

        await vm.LoadAsync();

        Assert.True(vm.HasFolders);
        Assert.Null(reportedError);
    }

    [Fact]
    public async Task LoadAsync_ScanCompletes_ScanOpIsRunningResetToFalse()
    {
        var worker = new FakeWorkerClient { Folders = new List<string> { @"C:\src" } };
        var vm = new RepoImportModalViewModel(new TestDbFactory(NewContext), worker);

        await vm.LoadAsync();

        Assert.False(vm.ScanOp.IsRunning);
        Assert.False(vm.ScanOp.ShowIndicator);
    }

    [Fact]
    public async Task LoadAsync_HubFailure_ReportsErrorInsteadOfSilentEmptyList()
    {
        var worker = new FakeWorkerClient { ThrowOnGet = new InvalidOperationException("worker offline") };
        var vm = new RepoImportModalViewModel(new TestDbFactory(NewContext), worker);
        string? reportedError = null;
        vm.ErrorReported += msg => reportedError = msg;

        await vm.LoadAsync();

        Assert.False(vm.HasFolders);
        Assert.NotNull(reportedError);
        Assert.Contains("worker offline", reportedError);
    }

    [Fact]
    public async Task AddFoldersAsync_SavesThroughWorkerClient()
    {
        var worker = new FakeWorkerClient();
        var vm = new RepoImportModalViewModel(new TestDbFactory(NewContext), worker);
        await vm.LoadAsync();

        await vm.AddFoldersAsync(new[] { @"C:\src\new-folder" });

        Assert.NotNull(worker.LastSaved);
        Assert.Contains(@"C:\src\new-folder", worker.LastSaved!);
    }

    [Fact]
    public async Task AddFoldersAsync_SaveFailure_ReportsError()
    {
        var worker = new FakeWorkerClient { ThrowOnSet = new InvalidOperationException("write failed") };
        var vm = new RepoImportModalViewModel(new TestDbFactory(NewContext), worker);
        await vm.LoadAsync();
        string? reportedError = null;
        vm.ErrorReported += msg => reportedError = msg;

        await vm.AddFoldersAsync(new[] { @"C:\src\new-folder" });

        Assert.NotNull(reportedError);
        Assert.Contains("write failed", reportedError);
    }
}
