using ClaudeDo.Data;
using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels.Islands;
using ClaudeDo.Ui.ViewModels.Modals;
using Microsoft.EntityFrameworkCore;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;

namespace ClaudeDo.Ui.Tests.Services;

// Dedup: five copy-pasted "open this path in the shell" implementations replaced by ShellOpen.
// Process.Start must never fire in tests, so only the "nothing to open" paths are covered here —
// an existing file/directory would actually launch the OS shell handler.
public class ShellOpenTests
{
    private sealed class NoopWorkerClient : StubWorkerClient { }

    [Theory]
    [InlineData(null)]
    [InlineData("")]
    [InlineData("   ")]
    public void Path_BlankInput_ReturnsFalseWithNoError(string? input)
    {
        var (ok, error) = ShellOpen.Path(input);

        Assert.False(ok);
        Assert.Null(error);
    }

    [Fact]
    public void Path_NonExistentPath_ReturnsFalseWithNoError_DoesNotThrow()
    {
        var missing = System.IO.Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_missing_{Guid.NewGuid():N}");

        var (ok, error) = ShellOpen.Path(missing);

        Assert.False(ok);
        Assert.Null(error);
    }

    [Fact]
    public void ListsIslandViewModel_OpenInExplorer_NonExistentDir_StaysSilent()
    {
        var dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_lists_{Guid.NewGuid():N}.db");
        try
        {
            var opts = new DbContextOptionsBuilder<ClaudeDoDbContext>().UseSqlite($"Data Source={dbPath}").Options;
            using (var ctx = new ClaudeDoDbContext(opts)) ctx.Database.EnsureCreated();
            var factory = new TestDbFactory(() => new ClaudeDoDbContext(opts));

            var vm = new ListsIslandViewModel(factory);
            string? reportedError = null;
            vm.ErrorReported += msg => reportedError = msg;
            var row = new ListNavItemViewModel
            {
                Id = "L1",
                Kind = ListKind.User,
                WorkingDir = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_missing_dir_{Guid.NewGuid():N}"),
            };

            vm.OpenInExplorerCommand.Execute(row);

            Assert.Null(reportedError);
        }
        finally
        {
            try { File.Delete(dbPath); } catch { }
            try { File.Delete(dbPath + "-wal"); } catch { }
            try { File.Delete(dbPath + "-shm"); } catch { }
        }
    }

    [Fact]
    public void TasksIslandViewModel_OpenTaskWorktree_NonExistentPath_StaysSilent()
    {
        var dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_tasks_{Guid.NewGuid():N}.db");
        try
        {
            var opts = new DbContextOptionsBuilder<ClaudeDoDbContext>().UseSqlite($"Data Source={dbPath}").Options;
            using (var ctx = new ClaudeDoDbContext(opts)) ctx.Database.EnsureCreated();
            var factory = new TestDbFactory(() => new ClaudeDoDbContext(opts));

            var vm = new TasksIslandViewModel(factory, new NoopWorkerClient());
            string? reportedError = null;
            vm.ErrorReported += msg => reportedError = msg;
            var row = new TaskRowViewModel
            {
                Id = "task-1",
                Status = TaskStatus.Idle,
                WorktreePath = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_missing_wt_{Guid.NewGuid():N}"),
            };

            vm.OpenTaskWorktreeCommand.Execute(row);

            Assert.Null(reportedError);
        }
        finally
        {
            try { File.Delete(dbPath); } catch { }
            try { File.Delete(dbPath + "-wal"); } catch { }
            try { File.Delete(dbPath + "-shm"); } catch { }
        }
    }

    [Fact]
    public void WorktreesOverviewModalViewModel_OpenInExplorer_NonExistentPath_StaysSilent()
    {
        var vm = new WorktreesOverviewModalViewModel(new NoopWorkerClient(), () => null!, new MergeCoordinator());
        string? reportedError = null;
        vm.ErrorReported += msg => reportedError = msg;
        var row = new WorktreeOverviewRowViewModel
        {
            TaskId = "task-1",
            TaskTitle = "Task 1",
            TaskStatus = TaskStatus.Idle,
            State = WorktreeState.Active,
            Path = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_missing_row_{Guid.NewGuid():N}"),
        };

        vm.OpenInExplorerCommand.Execute(row);

        Assert.Null(reportedError);
    }

    [Fact]
    public void AboutModalViewModel_OpenPath_NonExistentPath_StaysSilent()
    {
        var vm = new AboutModalViewModel();
        string? reportedError = null;
        vm.ErrorReported += msg => reportedError = msg;
        var missing = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_missing_about_{Guid.NewGuid():N}");

        vm.OpenPathCommand.Execute(missing);

        Assert.Null(reportedError);
    }

    [Fact]
    public void MergeSectionViewModel_OpenWorktree_NonExistentPath_StaysSilent()
    {
        var vm = new MergeSectionViewModel(new NoopWorkerClient(), services: null!);
        string? reportedError = null;
        vm.ErrorReported += msg => reportedError = msg;
        var missing = Path.Combine(Path.GetTempPath(), $"claudedo_shellopen_missing_merge_{Guid.NewGuid():N}");
        vm.SyncWorktree(missing, null, null, "Active", null);

        vm.OpenWorktreeCommand.Execute(null);

        Assert.Null(reportedError);
    }

}
