using InABox.API;
using InABox.Core;
using InABox.Database;

namespace InABox.Rpc;

public class RpcQueryHandler : RpcCommandHandler<IRpcServer, RpcQueryCommand, RpcQueryParameters, RpcQueryResult> 
{
    protected override RpcQueryResult Execute(IRpcSession session, RpcQueryParameters parameters, Logger logger)
    {
        var user = CredentialsCache.ValidateAndRefresh(session.ID)
            ?? throw new RpcException("User not found in Credentials Cache!", RpcError.UNAUTHENTICATED);

        var response = new RpcQueryResult();

        var tasks = new List<Task<RpcQueryTable>>();
        foreach (var query in parameters.Queries)
        {
            var task = Task.Run(() =>
            {
                var table = new RpcQueryTable() { Key = query.Key };
                try
                {
                    var store = DbFactory.FindStore(query.Type, user.ID, user.UserID, session.Platform, session.Version ?? "", logger);
                    table.Table = store.Query(query.Filter, query.Columns, query.Sort, query.Range);
                }
                catch (Exception e)
                {
                    logger.Send(
                        LogType.Error, 
                        user.UserID,
                        string.Format(
                            "[{0} {1}] Error: {2}\n{3}", 
                            PlatformUtils.PlatformToString(session.Platform), 
                            session.Version,
                            e.Message,
                            e.StackTrace
                        )
                    );                       
                }
                return table;
            });
            tasks.Add(task);
        }
        Task.WaitAll(tasks.ToArray());

        response.Tables = tasks.Select(x => x.Result).ToArray();
        
        return response;
    }

    public RpcQueryHandler(IRpcServer sender) : base(sender)
    {
    }
}