using Coscine.ApiClient.Core.Api;
using Coscine.ApiClient.Core.Model;
using Microsoft.Extensions.Logging;
using VDS.RDF;
using VDS.RDF.Parsing;

namespace Coscine.GraphDeployer;

/// <summary>
/// Class responsible for converting role data into linked data graphs.
/// It retrieves role information from the API and then transforms this data into a series of RDF graphs,
/// making use of predefined URIs and RDF constructs.
/// </summary>
public class RoleStructuralData
{
    private readonly AdminApi _adminApi;
    private readonly ILogger<ResourceTypeStructuralData> _logger;
    public RoleStructuralData(AdminApi adminApi)
    {
        _adminApi = adminApi;
        _logger = logger;

    }
    public async IAsyncEnumerable<IGraph> CreateGraphAsync(IAsyncEnumerable<RoleDto> entries)
    {
        await foreach (var entry in entries)
        {
            var roleGraphName = UriHelper.TryCombineUri(RdfUris.CoscineRoles, entry.Id)
                ?? throw new Exception("Could not combine role prefix with role ID");
            var response = await _adminApi.GetMetadataGraphAsync(roleGraphName.AbsoluteUri, RdfFormat.TextTurtle);

            var graph = new Graph()
            {
                BaseUri = roleGraphName
            };

            graph.LoadFromString(response.Data.Content, new TurtleParser());

            // check if a triple with a org:role already exists in the role graph
            var getTriplesOrgRole = graph.GetTriplesWithObject(RdfUris.OrgRoleClass);

            if (!getTriplesOrgRole.Any())
            {
                GraphExtensions.AssertToGraph(graph, roleGraphName, RdfUris.A, RdfUris.OrgRoleClass);
                _logger.LogInformation($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {RdfUris.A} {RdfUris.OrgRoleClass}'. ");
            }
            else
            {
                _logger.LogInformation($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {RdfUris.A} {RdfUris.OrgRoleClass}'. ");
            }

            // check if a triple with dcterms:title '{entry.DisplayName}' already exists in the role graph
            var getTriplesDctermsTitle = graph.GetTriplesWithPredicate(RdfUris.DcTermsTitle);

            if (!getTriplesDctermsTitle.Any())
            {
                GraphExtensions.AssertToGraph(graph, roleGraphName, RdfUris.DcTermsTitle, entry.DisplayName);
               _logger.LogInformation($"For role '{entry.DisplayName}' will migrate triple '{graph.BaseUri} {RdfUris.DcTermsTitle} {entry.DisplayName}'. ");
            }
            else
            {
                _logger.LogInformation($"For role '{entry.DisplayName}' will NOT migrate triple '{graph.BaseUri} {RdfUris.DcTermsTitle} {entry.DisplayName}'. ");
            }
            if (!getTriplesOrgRole.Any() || !getTriplesDctermsTitle.Any())
            {
                yield return graph;
            }
        }
    }
}