using RolemasterDb.App.Features;
using RolemasterDb.App.Frontend.AppState;

namespace RolemasterDb.App.Frontend.Curation;

public static class CurationQueueResolver
{
    public static IReadOnlyList<CriticalTableCellDetail> GetOrderedCells(CriticalTableDetail detail)
    {
        ArgumentNullException.ThrowIfNull(detail);

        var rollOrder = detail.RollBands.Select((rollBand, index) => new
        {
            rollBand.Label,
            index
        }).ToDictionary(item => item.Label, item => item.index, StringComparer.Ordinal);
        var columnOrder = detail.Columns.Select((column, index) => new
        {
            column.Key,
            index
        }).ToDictionary(item => item.Key, item => item.index, StringComparer.Ordinal);
        var groupOrder = detail.Groups.Select((group, index) => new
        {
            group.Key,
            index
        }).ToDictionary(item => item.Key, item => item.index, StringComparer.Ordinal);

        return detail.Cells.OrderBy(cell => rollOrder.GetValueOrDefault(cell.RollBand, int.MaxValue)).ThenBy(cell =>
        {
            if (string.IsNullOrWhiteSpace(cell.GroupKey))
            {
                return -1;
            }

            return groupOrder.GetValueOrDefault(cell.GroupKey, int.MaxValue);
        }).ThenBy(cell => columnOrder.GetValueOrDefault(cell.ColumnKey, int.MaxValue)).ToList();
    }

    public static CriticalTableCellDetail? FindCell(CriticalTableDetail detail, TableContextSnapshot? context) =>
        TableContextCellResolver.FindCell(detail, context);

    public static CriticalTableCellDetail? FindFirstUncurated(CriticalTableDetail detail) =>
        GetOrderedCells(detail).FirstOrDefault(cell => !cell.IsCurated);

    public static CriticalTableCellDetail? FindNextUncurated(CriticalTableDetail detail, int currentResultId)
    {
        var orderedCells = GetOrderedCells(detail);
        var currentIndex = orderedCells.Select((cell, index) => new
        {
            cell.ResultId,
            index
        }).FirstOrDefault(item => item.ResultId == currentResultId)?.index ?? -1;

        for (var index = currentIndex + 1; index < orderedCells.Count; index++)
        {
            if (!orderedCells[index].IsCurated)
            {
                return orderedCells[index];
            }
        }

        return null;
    }

    public static CurationQueueItem CreateQueueItem(CriticalTableDetail detail, CriticalTableCellDetail cell)
    {
        ArgumentNullException.ThrowIfNull(detail);
        ArgumentNullException.ThrowIfNull(cell);

        return new CurationQueueItem(detail.Slug, detail.DisplayName, cell.ResultId, cell.RollBand, cell.ColumnKey, cell.ColumnLabel, cell.GroupKey, cell.GroupLabel);
    }
}