#nullable enable

namespace MBN_STOCK_WEBVIEW.Core.Playout.Scenes;

public enum S5025ManualAudience
{
    Individual,
    Foreign,
    Institution
}

public sealed record S5025ManualSceneLoadRequest(S5025ManualAudience Audience);

public sealed record S5025TrustedManualRow(
    string LeftName,
    string LeftAmount,
    string RightName,
    string RightAmount);

/// <summary>
/// Composition-root contract for the approved manual-data store. It deliberately
/// exposes a closed audience key and no path so a WebView request cannot choose a file.
/// </summary>
public interface IS5025TrustedManualDataSource
{
    Task<IReadOnlyList<S5025TrustedManualRow>> ReadAsync(
        S5025ManualAudience audience,
        CancellationToken cancellationToken = default);
}

public sealed class S5025SceneDataLoader
{
    private const int RowCount = 5;
    private const int MaximumCellLength = 256;

    private readonly IS5025TrustedManualDataSource _source;

    public S5025SceneDataLoader(IS5025TrustedManualDataSource source)
    {
        _source = source ?? throw new ArgumentNullException(nameof(source));
    }

    public async Task<S5025SceneData> LoadAsync(
        S5025ManualSceneLoadRequest request,
        CancellationToken cancellationToken = default)
    {
        ArgumentNullException.ThrowIfNull(request);
        var title = request.Audience switch
        {
            S5025ManualAudience.Individual => "\uAC1C\uC778",
            S5025ManualAudience.Foreign => "\uC678\uAD6D\uC778",
            S5025ManualAudience.Institution => "\uAE30\uAD00",
            _ => throw LegacyTabularSceneLoaderReader.InvalidRequest()
        };
        var sourceRows = await _source.ReadAsync(request.Audience, cancellationToken)
            .ConfigureAwait(false);
        if (sourceRows is null || sourceRows.Count != RowCount || sourceRows.Any(row => row is null))
        {
            throw LegacyTabularSceneLoaderReader.InvalidResult();
        }

        var rows = sourceRows.Select((row, index) => new ManualNetSellPairData(
            Cell(row.LeftName, index, nameof(row.LeftName)),
            Cell(row.LeftAmount, index, nameof(row.LeftAmount)),
            Cell(row.RightName, index, nameof(row.RightName)),
            Cell(row.RightAmount, index, nameof(row.RightAmount))))
            .ToArray();
        var data = new S5025SceneData(title, rows);
        return LegacyTabularSceneLoaderReader.Preflight(new S5025SceneMutationBuilder(), data);
    }

    private static string Cell(string? value, int row, string field)
    {
        if (value is null || value.Length > MaximumCellLength || value.Any(char.IsControl))
        {
            throw LegacyTabularSceneLoaderReader.InvalidResult();
        }

        try
        {
            return LegacySceneBuilderGuard.Text(
                value,
                $"Rows[{row}].{field}",
                allowEmpty: true);
        }
        catch (LegacySceneDataException)
        {
            throw LegacyTabularSceneLoaderReader.InvalidResult();
        }
    }
}
