using ScadaLink.TemplateEngine;

namespace ScadaLink.CentralUI.ScriptAnalysis;

/// <summary>
/// Indirection so ScriptAnalysisService can be unit-tested without standing
/// up SharedScriptService and its EF Core repository chain.
/// </summary>
public interface ISharedScriptCatalog
{
    Task<IReadOnlyList<ScriptShape>> GetShapesAsync();

    /// <summary>
    /// Returns the source code and metadata for a named shared script, or
    /// null if no shared script with that name exists. Used by Test Run to
    /// compile and execute nested CallShared invocations.
    /// </summary>
    Task<SharedScriptSource?> GetByNameAsync(string name, CancellationToken cancellationToken = default);
}

public record SharedScriptSource(string Name, string Code, string? ParameterDefinitions, string? ReturnDefinition);

public class SharedScriptCatalog : ISharedScriptCatalog
{
    private readonly SharedScriptService _service;

    public SharedScriptCatalog(SharedScriptService service) => _service = service;

    public async Task<IReadOnlyList<ScriptShape>> GetShapesAsync()
    {
        var scripts = await _service.GetAllSharedScriptsAsync();
        return scripts
            .Select(s => ScriptShapeParser.Parse(s.Name, s.ParameterDefinitions, s.ReturnDefinition))
            .ToList();
    }

    public async Task<SharedScriptSource?> GetByNameAsync(string name, CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrEmpty(name)) return null;
        var scripts = await _service.GetAllSharedScriptsAsync(cancellationToken);
        var s = scripts.FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.Ordinal));
        return s == null ? null : new SharedScriptSource(s.Name, s.Code, s.ParameterDefinitions, s.ReturnDefinition);
    }
}
