using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace StellaOps.Cli.Services;

internal sealed class ScannerInstaller : IScannerInstaller
{
    private readonly ILogger<ScannerInstaller> _logger;

    public ScannerInstaller(ILogger<ScannerInstaller> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task InstallAsync(string artifactPath, bool verbose, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(artifactPath) || !File.Exists(artifactPath))
        {
            throw new FileNotFoundException("Scanner artifact not found for installation.", artifactPath);
        }

        // Current implementation assumes docker-based scanner bundle.
        var processInfo = new ProcessStartInfo
        {
            FileName = "docker",
            ArgumentList = { "load", "-i", artifactPath },
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false
        };

        using var process = new Process { StartInfo = processInfo, EnableRaisingEvents = true };

        process.OutputDataReceived += (_, args) =>
        {
            if (args.Data is null)
            {
                return;
            }

            if (verbose)
            {
                _logger.LogInformation("[install] {Line}", args.Data);
            }
        };

        process.ErrorDataReceived += (_, args) =>
        {
            if (args.Data is null)
            {
                return;
            }

            _logger.LogError("[install] {Line}", args.Data);
        };

        _logger.LogInformation("Installing scanner container from {Path}...", artifactPath);
        if (!process.Start())
        {
            throw new InvalidOperationException("Failed to start container installation process.");
        }

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);

        if (process.ExitCode != 0)
        {
            throw new InvalidOperationException($"Container installation failed with exit code {process.ExitCode}.");
        }

        _logger.LogInformation("Scanner container installed successfully.");
    }
}
