using System.IO;
using ClaudeDo.Data;
using ClaudeDo.Installer.Core;

namespace ClaudeDo.Installer.Checks;

/// <summary>Without write access nothing can be installed — blocking.</summary>
public sealed class WriteAccessCheck : IEnvironmentCheck
{
    public const string CheckId = "write-access";

    public string Id => CheckId;
    public CheckSeverity Severity => CheckSeverity.Error;

    public Task<CheckResult> RunAsync(InstallContext ctx, CancellationToken ct)
    {
        foreach (var target in new[] { ctx.InstallDirectory, Paths.AppDataRoot() })
        {
            var error = TryWrite(target);
            if (error is not null)
            {
                return Task.FromResult(CheckResult.Fail(Id, Severity, "checks.writeAccess.title",
                    $"Cannot write to '{target}': {error}", "checks.writeAccess.hint"));
            }
        }

        return Task.FromResult(CheckResult.Ok(Id, Severity, "checks.writeAccess.title", "Install directory and data directory are writable."));
    }

    private static string? TryWrite(string path)
    {
        var probeDir = FirstExistingParent(path);
        var probeFile = Path.Combine(probeDir, $".claudedo-write-check-{Guid.NewGuid():N}.tmp");

        try
        {
            File.WriteAllText(probeFile, string.Empty);
            return null;
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
        finally
        {
            try { File.Delete(probeFile); } catch { /* best-effort cleanup */ }
        }
    }

    private static string FirstExistingParent(string path)
    {
        var current = Path.GetFullPath(path);
        while (!Directory.Exists(current))
        {
            var parent = Path.GetDirectoryName(current);
            if (string.IsNullOrEmpty(parent) || parent == current) break;
            current = parent;
        }

        return current;
    }
}
