package recordsv1

import (
	"context"
	"errors"
	"strings"
	"testing"
	"time"
)

func TestApprovedExecutionFacts(t *testing.T) {
	if MaxAttemptDuration != 2*time.Second {
		t.Fatalf("MaxAttemptDuration = %s", MaxAttemptDuration)
	}
	if !FailFastAdmissionRequired {
		t.Fatal("selected-root v1 must require fail-fast admission")
	}
}

func TestValidateRequestApprovedBoundaries(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	fields := make([]string, MaxSelectedFields)
	for i := range fields {
		fields[i] = fieldName(i, MaxFieldIdentifierBytes)
	}
	request := Request{
		ObjectID:           strings.Repeat("O", MaxObjectIdentifierBytes),
		RecordID:           strings.Repeat("é", 127) + "a",
		SelectedRootFields: fields,
	}
	revision := ^uint64(0)
	request.MinCatalogRevision = &revision
	if err := ValidateRequest(ctx, request); err != nil {
		t.Fatalf("ValidateRequest(maximum) = %v", err)
	}
	if got, _ := SemanticRequestSize(request); got != 34720 {
		t.Fatalf("maximum structurally valid request semantic bytes = %d, want 34720", got)
	}

	tests := []struct {
		name   string
		mutate func(*Request)
		kind   LimitKind
	}{
		{name: "object", mutate: func(r *Request) { r.ObjectID += "X" }, kind: LimitObjectID},
		{name: "record", mutate: func(r *Request) { r.RecordID += "b" }, kind: LimitRecordID},
		{name: "field", mutate: func(r *Request) { r.SelectedRootFields[0] += "X" }, kind: LimitFieldID},
		{name: "field count", mutate: func(r *Request) { r.SelectedRootFields = append(r.SelectedRootFields, "OneOver") }, kind: LimitSelectedFields},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			copyRequest := request
			copyRequest.SelectedRootFields = append([]string(nil), request.SelectedRootFields...)
			tc.mutate(&copyRequest)
			var failure *Failure
			if err := ValidateRequest(ctx, copyRequest); !errors.As(err, &failure) || failure.LimitKind != tc.kind {
				t.Fatalf("ValidateRequest(one over) = %#v, want %s", err, tc.kind)
			}
		})
	}
}

func TestValidateRequestRequiresDeadline(t *testing.T) {
	err := ValidateRequest(context.Background(), Request{ObjectID: "Issue", RecordID: "I-1", SelectedRootFields: []string{"Subject"}})
	var failure *Failure
	if !errors.As(err, &failure) || failure.Category != FailureInvalidRequest || failure.InvalidComponent != InvalidComponentDeadline {
		t.Fatalf("ValidateRequest(no deadline) = %#v", err)
	}
}

func TestValidateResponseTypedValuesNullAndAbsence(t *testing.T) {
	empty := ""
	falseValue := false
	zero := int64(0)
	date := "2026-07-12"
	datetime := "2026-07-12T10:11:12.123Z"
	reference := "P-1"
	response := Response{
		RecordID: "I-1",
		Fields: []Field{
			{Name: "Archived", Kind: ValueKindBoolean, Boolean: &falseValue},
			{Name: "DueDate", Kind: ValueKindDate, Date: &date},
			{Name: "Empty", Kind: ValueKindString, String: &empty},
			{Name: "Estimate", Kind: ValueKindDecimal, Decimal: &Decimal{Coefficient: "0", Scale: 2}},
			{Name: "Optional", Kind: ValueKindString, Null: true},
			{Name: "ProjectId", Kind: ValueKindReference, Reference: &reference},
			{Name: "RetryCount", Kind: ValueKindInteger, Integer: &zero},
			{Name: "UpdatedAt", Kind: ValueKindDateTime, DateTime: &datetime},
		},
		Receipts: Receipts{ProtocolVersion: "1.0", CapabilityVersion: CapabilityName},
	}
	if err := ValidateResponse(response); err != nil {
		t.Fatalf("ValidateResponse() = %v", err)
	}
	// A declared-but-absent/FLS-hidden field is intentionally not represented.
	for _, field := range response.Fields {
		if field.Name == "Secret" || field.Name == "DeclaredAbsent" {
			t.Fatalf("omitted field leaked: %#v", field)
		}
	}
}

func fieldName(index, width int) string {
	prefix := "F" + leftPadDecimal(index, 6)
	return prefix + strings.Repeat("X", width-len(prefix))
}

func leftPadDecimal(value, width int) string {
	digits := ""
	if value == 0 {
		digits = "0"
	}
	for value > 0 {
		digits = string(rune('0'+value%10)) + digits
		value /= 10
	}
	return strings.Repeat("0", width-len(digits)) + digits
}
