package dialectsfcrm

import (
	"context"
	"encoding/json"
	"errors"
	"reflect"
	"testing"
	"time"

	"github.com/nexuscrm/shared/pkg/constants"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordsv1"
)

func TestRuntimeSelectedRootClientProjectsOnlyAuthorizedRootValues(t *testing.T) {
	empty, falseValue, zero := "", false, int64(0)
	date, dateTime, reference := "2026-07-12", "2026-07-12T09:10:11.123456Z", "001-root"
	var calls int
	client, err := NewRuntimeSelectedRootClient(func(_ context.Context, request semantic.Request) (semantic.Response, error) {
		calls++
		if request.ObjectID != "Account" || request.RecordID != "001-record" ||
			!reflect.DeepEqual(request.SelectedRootFields, []string{"Zero", "Hidden", "Empty", "Optional", "Amount", "Closed", "DueDate", "UpdatedAt", "ParentId"}) ||
			request.MinCatalogRevision == nil || *request.MinCatalogRevision != 7 {
			t.Fatalf("request = %#v", request)
		}
		return semantic.Response{
			RecordID: "001-record",
			Fields: []semantic.Field{
				{Name: "Amount", Kind: semantic.ValueKindDecimal, Decimal: &semantic.Decimal{Coefficient: "-1200", Scale: 2}},
				{Name: "Closed", Kind: semantic.ValueKindBoolean, Boolean: &falseValue},
				{Name: "DueDate", Kind: semantic.ValueKindDate, Date: &date},
				{Name: "Empty", Kind: semantic.ValueKindString, String: &empty},
				{Name: "Optional", Kind: semantic.ValueKindString, Null: true},
				{Name: "ParentId", Kind: semantic.ValueKindReference, Reference: &reference},
				{Name: "UpdatedAt", Kind: semantic.ValueKindDateTime, DateTime: &dateTime},
				{Name: "Zero", Kind: semantic.ValueKindInteger, Integer: &zero},
			},
			Receipts: semantic.Receipts{
				ProtocolVersion: "1.0", CatalogRevision: 7,
				CapabilityVersion: semantic.CapabilityName,
			},
		}, nil
	})
	if err != nil {
		t.Fatal(err)
	}
	revision := uint64(7)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	record, receipts, err := client.Read(ctx, "v63.0", "Account", "001-record",
		[]string{"Zero", "Hidden", "Empty", "Optional", "Amount", "Closed", "DueDate", "UpdatedAt", "ParentId"}, &revision)
	if err != nil {
		t.Fatal(err)
	}
	if calls != 1 || receipts.CatalogRevision != 7 {
		t.Fatalf("calls=%d receipts=%#v", calls, receipts)
	}
	if record[constants.FieldID] != "001-record" || record["Closed"] != false || record["Zero"] != int64(0) || record["Empty"] != "" || record["Optional"] != nil ||
		record["Amount"] != json.Number("-12.00") || record["DueDate"] != date || record["UpdatedAt"] != dateTime || record["ParentId"] != reference {
		t.Fatalf("record = %#v", record)
	}
	if _, exists := record["Hidden"]; exists {
		t.Fatal("FLS-hidden field was invented by the L1 projection")
	}
	if len(record) != 10 {
		t.Fatalf("record fields = %#v", record)
	}
	attributes, ok := record["attributes"].(map[string]any)
	if !ok || attributes["type"] != "Account" || attributes["url"] != "/services/data/v63.0/sobjects/Account/001-record" {
		t.Fatalf("attributes = %#v", record["attributes"])
	}
}

func TestRuntimeSelectedRootClientPreservesSemanticFailure(t *testing.T) {
	want := &semantic.Failure{Category: semantic.FailureMissing}
	client, err := NewRuntimeSelectedRootClient(func(context.Context, semantic.Request) (semantic.Response, error) {
		return semantic.Response{}, want
	})
	if err != nil {
		t.Fatal(err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	record, receipts, err := client.Read(ctx, "v63.0", "Account", "missing", []string{"Name"}, nil)
	var failure *semantic.Failure
	if record != nil || receipts != (semantic.Receipts{}) || !errors.As(err, &failure) || failure.Category != semantic.FailureMissing {
		t.Fatalf("record=%#v receipts=%#v error=%#v", record, receipts, err)
	}
}

func TestRuntimeSelectedRootClientRejectsMissingReader(t *testing.T) {
	if client, err := NewRuntimeSelectedRootClient(nil); client != nil || err == nil {
		t.Fatalf("NewRuntimeSelectedRootClient(nil) = %#v, %v", client, err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	var client *RuntimeSelectedRootClient
	_, _, err := client.Read(ctx, "v63.0", "Account", "001", []string{"Name"}, nil)
	var failure *semantic.Failure
	if !errors.As(err, &failure) || failure.Category != semantic.FailureUnavailable {
		t.Fatalf("zero client error = %#v", err)
	}
}

func TestFormatSelectedRootDecimal(t *testing.T) {
	for _, tc := range []struct {
		value semantic.Decimal
		want  string
	}{
		{value: semantic.Decimal{Coefficient: "0", Scale: 0}, want: "0"},
		{value: semantic.Decimal{Coefficient: "0", Scale: 2}, want: "0.00"},
		{value: semantic.Decimal{Coefficient: "1", Scale: 3}, want: "0.001"},
		{value: semantic.Decimal{Coefficient: "12345", Scale: 2}, want: "123.45"},
		{value: semantic.Decimal{Coefficient: "-1", Scale: 3}, want: "-0.001"},
		{value: semantic.Decimal{Coefficient: "1", Scale: ^uint32(0)}, want: "1e-4294967295"},
	} {
		if got, err := formatSelectedRootDecimal(tc.value); err != nil || got != tc.want {
			t.Fatalf("formatSelectedRootDecimal(%#v) = %q, %v; want %q", tc.value, got, err, tc.want)
		}
	}
}
