package sfcrmappservice

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"testing"

	querycodec "github.com/pingcap-inc/nexuscrm-app-packs/sfcrm/querycodec"
	catalog "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
	query "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
)

// Exercise the production gRPC client and its error decoding before HTTP
// projection, with a failure in either calendar preparation or record execution.
func TestDateDependencyFailuresThroughRuntimeTransport(t *testing.T) {
	for _, phase := range []string{"calendar", "records"} {
		for _, tc := range []struct {
			name   string
			err    error
			status int
			code   string
		}{
			{"unknown", errors.New("private diagnostic"), 500, "INTERNAL_ERROR"},
			{"forbidden", fmt.Errorf("private diagnostic: %w", &query.Failure{Category: query.FailureForbidden}), 403, "FORBIDDEN"},
			{"unavailable", fmt.Errorf("private diagnostic: %w", &query.Failure{Category: query.FailureUnavailable}), 503, "UNKNOWN_EXCEPTION"},
			{"deadline", fmt.Errorf("private diagnostic: %w", &query.Failure{Category: query.FailureDeadlineExceeded}), 504, "UNKNOWN_EXCEPTION"},
			{"canceled", fmt.Errorf("private diagnostic: %w", &query.Failure{Category: query.FailureCanceled}), 499, "UNKNOWN_EXCEPTION"},
		} {
			for _, route := range []querycodec.RouteKind{querycodec.RouteQuery, querycodec.RouteQueryAll, querycodec.RouteMore} {
				if phase == "calendar" && route == querycodec.RouteMore {
					continue
				}
				t.Run(fmt.Sprintf("%s/%s/%v", phase, tc.name, route), func(t *testing.T) {
					view := searchTestView(t, []searchObjectSpec{{APIName: "Item", Label: "Item", Fields: []searchFieldSpec{{APIName: "Due", Label: "Due", Type: "date"}}}})
					calls := 0
					producer := &queryResponseServer{query: func(_ context.Context, req query.Request) (query.Response, error) {
						calls++
						if (phase == "calendar" && req.ObjectID == "User") || (phase == "records" && req.ObjectID == "Item") {
							return query.Response{}, tc.err
						}
						if req.ObjectID != "User" {
							t.Fatalf("unexpected object %s", req.ObjectID)
						}
						zone := "UTC"
						receipts := view.Receipts
						receipts.CapabilityVersion = query.CapabilityName
						return query.Response{Done: true, TotalSize: 1, Receipts: receipts, Records: []query.Record{{ObjectID: "User", Fields: []query.Field{{Name: "TimeZoneSidKey", Value: query.Value{Kind: query.ValueString, String: &zone}}}}}}, nil
					}}
					client := queryResponseTransportProducer(t, producer)
					execute := func(ctx context.Context, _ string, req query.Request) (query.Response, error) {
						return client.QueryRecords(ctx, req)
					}
					dates := &runtimeQueryDates{query: execute, metadata: func(context.Context, catalog.GetRequest) (catalog.AppMetadataViewV3, error) { return view, nil }}
					h, err := NewRuntimeQueryHandler(execute, func(context.Context, string, query.HistoryRequest) (query.HistoryResponse, error) {
						t.Fatal("unexpected history")
						return query.HistoryResponse{}, nil
					}, dates)
					if err != nil {
						t.Fatal(err)
					}
					raw := "SELECT Id FROM Item WHERE Due = TODAY"
					request := querycodec.Request{Route: querycodec.Route{Kind: route, Version: "v63.0"}, Query: url.Values{"q": {raw}}}
					if route == querycodec.RouteMore {
						data, err := json.Marshal(map[string]any{"q": url.QueryEscape(raw), "limit": 200, "offset": 200, "dateAnchor": map[string]string{"instant": "2026-09-08T00:30:00Z", "timeZone": "UTC"}})
						if err != nil {
							t.Fatal(err)
						}
						request.Route.Locator = base64.URLEncoding.EncodeToString(data)
						request.Query = nil
					}
					result := h.Handle(queryDateTestContext(t), request)
					body, err := json.Marshal(result.Body)
					if err != nil {
						t.Fatal(err)
					}
					wantCalls := 2
					if phase == "calendar" || route == querycodec.RouteMore {
						wantCalls = 1
					}
					if result.Status != tc.status || calls != wantCalls || !strings.Contains(string(body), `"errorCode":"`+tc.code+`"`) || strings.Contains(string(body), "private diagnostic") {
						t.Fatalf("calls=%d status=%d want=%d body=%s", calls, result.Status, tc.status, body)
					}
				})
			}
		}
	}
}
