package soql

import (
	"strings"
	"testing"
)

func TestParseSOQL_AggregateParentRelationshipGroupBy(t *testing.T) {
	req, err := ParseSOQL(`SELECT Account.Industry, COUNT(Id) total FROM Opportunity WHERE Account.Industry = 'Technology' GROUP BY Account.Industry HAVING Account.Industry != null ORDER BY Account.Industry ASC`)
	if err != nil {
		t.Fatalf("ParseSOQL error = %v, want accepted parent aggregate query", err)
	}
	if req.GroupBy != "Account.Industry" {
		t.Fatalf("GroupBy = %q, want Account.Industry", req.GroupBy)
	}
	if got := predicateExpression(t, req.Filter); got != "Account.Industry == 'Technology'" {
		t.Fatalf("Filter = %q, want parent relationship predicate", got)
	}
	if got := predicateExpression(t, req.HavingPredicate); got != "Account.Industry != null" {
		t.Fatalf("Having = %q, want parent relationship predicate", got)
	}
	if req.SortField != "Account.Industry" || req.SortDirection != "ASC" {
		t.Fatalf("SortField/Direction = %q/%q, want Account.Industry/ASC", req.SortField, req.SortDirection)
	}
	if len(req.OrderBy) != 1 || req.OrderBy[0].Field != "Account.Industry" || req.OrderBy[0].Direction != "ASC" {
		t.Fatalf("OrderBy = %#v, want parent relationship sort", req.OrderBy)
	}
}

func TestParseSOQL_ParentRelationshipOrderByList(t *testing.T) {
	req, err := ParseSOQL(`SELECT Id FROM Opportunity ORDER BY Account.Industry DESC, CreatedDate ASC`)
	if err != nil {
		t.Fatalf("ParseSOQL error = %v, want accepted parent ORDER BY", err)
	}
	want := []struct {
		field string
		dir   string
	}{
		{"Account.Industry", "DESC"},
		{"CreatedDate", "ASC"},
	}
	if len(req.OrderBy) != len(want) {
		t.Fatalf("OrderBy len = %d, want %d: %#v", len(req.OrderBy), len(want), req.OrderBy)
	}
	for i, w := range want {
		if req.OrderBy[i].Field != w.field || req.OrderBy[i].Direction != w.dir {
			t.Fatalf("OrderBy[%d] = %#v, want %s/%s", i, req.OrderBy[i], w.field, w.dir)
		}
	}
	if req.SortField != "Account.Industry" || req.SortDirection != "DESC" {
		t.Fatalf("SortField/Direction = %q/%q, want first parent sort", req.SortField, req.SortDirection)
	}
}

func TestParseSOQL_DottedFieldSegmentErrorNamesUnexpectedToken(t *testing.T) {
	_, err := ParseSOQL(`SELECT Account..Industry FROM Opportunity`)
	if err == nil {
		t.Fatal("ParseSOQL error = nil, want malformed dotted field error")
	}
	msg := err.Error()
	for _, want := range []string{"expected field segment", "SELECT", `"."`} {
		if !strings.Contains(msg, want) {
			t.Fatalf("ParseSOQL error = %q, want substring %q", msg, want)
		}
	}
}
