package dialectsfcrm

import (
	"context"
	"testing"

	"github.com/nexuscrm/shared/pkg/contract"
	"github.com/nexuscrm/shared/pkg/dialect"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/nexuscrm/shared/pkg/queryspec"
	querycodec "github.com/pingcap-inc/nexuscrm-app-packs/sfcrm/querycodec"
)

type calendarMetadata struct{ contract.Metadata }

func (calendarMetadata) Describe(context.Context, string) (*models.ObjectMetadata, error) {
	return &models.ObjectMetadata{APIName: "Item", Fields: []models.FieldMetadata{{APIName: "Due", Type: models.FieldType("Date")}}}, nil
}

type calendarQuery struct {
	queryFailureStub
	t     *testing.T
	calls int
}

func (q *calendarQuery) Query(_ context.Context, spec queryspec.QuerySpec, user *models.UserSession) (*contract.QueryResult, error) {
	q.calls++
	if user == nil || user.ID != "reader" {
		q.t.Fatal("acting user lost")
	}
	if spec.ObjectAPIName == "User" {
		if spec.Filter.Field != "Id" || spec.Filter.Value != "reader" || spec.Limit != 1 {
			q.t.Fatalf("unbound calendar read: %#v", spec)
		}
		return &contract.QueryResult{Done: true, TotalSize: 1, Records: []contract.Record{{"TimeZoneSidKey": "America/Los_Angeles"}}}, nil
	}
	if spec.ObjectAPIName != "Item" || len(spec.Filter.Children) != 2 {
		q.t.Fatalf("date not resolved: %#v", spec)
	}
	for _, p := range spec.Filter.Children {
		if _, ok := p.Right.Value.(string); !ok {
			q.t.Fatalf("calendar literal escaped to queryspec: %#v", p)
		}
	}
	return &contract.QueryResult{Done: true}, nil
}
func TestLegacyQueryUsesSharedDateResolution(t *testing.T) {
	q := &calendarQuery{t: t}
	response, err := QueryNeutralHandler(context.Background(), &dialect.Request{Version: "v63.0", User: &models.UserSession{ID: "reader"}, Query: map[string][]string{"q": {"SELECT Id FROM Item WHERE Due = TODAY"}}}, dialect.Deps{Contracts: contract.Deps{Query: q, Metadata: calendarMetadata{}}})
	if err != nil || response.Status != 200 || q.calls != 2 {
		t.Fatalf("calls=%d response=%#v err=%v", q.calls, response, err)
	}
}

type selectionValidationFailure struct{}

func (selectionValidationFailure) Error() string             { return "private diagnostic" }
func (selectionValidationFailure) ValidationField() string   { return "SelectFields" }
func (selectionValidationFailure) ValidationMessage() string { return "private diagnostic" }
func TestLegacySelectionErrorUsesNeutralClassifier(t *testing.T) {
	failure := legacyQueryFailure("v63.0", selectionValidationFailure{}).(*querycodec.Failure)
	if failure.Category != querycodec.FailureInvalidField || failure.Message == "private diagnostic" {
		t.Fatalf("failure=%#v", failure)
	}
}
