package selection_queries

import (
	"context"
	"fmt"
	"strings"

	"visualizador_instanciados/backend_go/queryscope"
)

func neighborsQuery(selectedNodes []NodeRef, includeBNodes bool) string {
	valuesTerms := make([]string, 0, len(selectedNodes))
	for _, n := range selectedNodes {
		t := valuesTerm(n)
		if t == "" {
			continue
		}
		valuesTerms = append(valuesTerms, t)
	}

	if len(valuesTerms) == 0 {
		return "SELECT ?s ?p ?o WHERE { FILTER(false) }"
	}

	bnodeFilter := ""
	if !includeBNodes {
		bnodeFilter = "FILTER(!isBlank(?s) && !isBlank(?o))"
	}

	values := strings.Join(valuesTerms, " ")
	pattern := queryscope.NamedGraph(fmt.Sprintf(`
{
  VALUES ?sel { %s }
  BIND(?sel AS ?s)
  VALUES ?p { rdf:type }
  ?s ?p ?o .
}
UNION
{
  VALUES ?sel { %s }
  VALUES ?p { rdf:type }
  ?s ?p ?sel .
  BIND(?sel AS ?o)
}
UNION
{
  VALUES ?sel { %s }
  BIND(?sel AS ?s)
  VALUES ?p { rdfs:subClassOf }
  ?s ?p ?o .
}
UNION
{
  VALUES ?sel { %s }
  VALUES ?p { rdfs:subClassOf }
  ?s ?p ?sel .
  BIND(?sel AS ?o)
}
`, values, values, values, values))

	return fmt.Sprintf(`
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

SELECT DISTINCT ?s ?p ?o
WHERE {
%s
  FILTER(!isLiteral(?o))
  FILTER(?s != ?o)
  %s
}
`, pattern, bnodeFilter)
}

func runNeighbors(ctx context.Context, q Querier, idx Index, selectedIDs []uint32, includeBNodes bool) (Result, error) {
	selectedNodes, selectedSet := selectedNodesFromIDs(idx, selectedIDs, includeBNodes)
	if len(selectedNodes) == 0 {
		return Result{NeighborIDs: []uint32{}, Triples: []Triple{}}, nil
	}

	query := neighborsQuery(selectedNodes, includeBNodes)
	raw, err := q.Query(ctx, query)
	if err != nil {
		logQueryExecutionFailure("neighbors", selectedIDs, includeBNodes, query, err)
		return Result{}, err
	}
	return resultFromTripleBindings(raw, idx, selectedSet, includeBNodes)
}
