using Books.Api.Authorization;
using Books.Api.Domain.Companies;
using Books.Api.Domain.UserAccess;
using Books.Api.EventFlow.Repositories;
using Books.Api.GraphQL.Types;
using GraphQL;
using GraphQL.Types;

namespace Books.Api.GraphQL.Queries;

public class BooksQuery : ObjectGraphType
{
    public BooksQuery()
    {
        Name = "Query";
        Description = "Root query for the Books API";

        // companies: [CompanyType]
        Field<ListGraphType<CompanyType>>("companies")
            .Description("Get all companies accessible to the current user")
            .ResolveAsync(async ctx =>
            {
                var accessService = ctx.RequestServices!.GetRequiredService<ICompanyAccessService>();
                var repository = ctx.RequestServices!.GetRequiredService<ICompanyRepository>();
                var userAccesses = await accessService.GetUserCompaniesAsync(ctx.CancellationToken);
                var companyIds = userAccesses.Select(a => CompanyId.With(a.CompanyId)).ToList();
                if (companyIds.Count == 0) return Enumerable.Empty<object>();
                return await repository.GetByIds(companyIds, ctx.CancellationToken);
            });

        // company(id: ID!): CompanyType
        Field<CompanyType>("company")
            .Description("Get a company by ID")
            .Argument<NonNullGraphType<IdGraphType>>("id", "The company ID")
            .ResolveAsync(async ctx =>
            {
                var id = ctx.GetArgument<string>("id");
                var accessService = ctx.RequestServices!.GetRequiredService<ICompanyAccessService>();
                await accessService.RequireAccessAsync(id, CompanyRole.Viewer, ctx.CancellationToken);
                var repository = ctx.RequestServices!.GetRequiredService<ICompanyRepository>();
                var companies = await repository.GetByIds([CompanyId.With(id)], ctx.CancellationToken);
                return companies.FirstOrDefault();
            });
    }
}
