#
tokens: 34722/50000 1/59 files (page 4/4)
lines: off (toggle) GitHub
raw markdown copy
This is page 4 of 4. Use http://codebase.md/razorpay/razorpay-mcp-server?page={x} to view the full context.

# Directory Structure

```
├── .cursor
│   └── rules
│       └── new-tool-from-docs.mdc
├── .cursorignore
├── .dockerignore
├── .github
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── pull_request_template.md
│   └── workflows
│       ├── assign.yml
│       ├── build.yml
│       ├── ci.yml
│       ├── docker-publish.yml
│       ├── lint.yml
│       └── release.yml
├── .gitignore
├── .golangci.yaml
├── .goreleaser.yaml
├── cmd
│   └── razorpay-mcp-server
│       ├── main.go
│       └── stdio.go
├── codecov.yml
├── CONTRIBUTING.md
├── Dockerfile
├── go.mod
├── go.sum
├── LICENSE
├── Makefile
├── pkg
│   ├── contextkey
│   │   └── context_key.go
│   ├── log
│   │   ├── config.go
│   │   ├── log.go
│   │   ├── slog_test.go
│   │   └── slog.go
│   ├── mcpgo
│   │   ├── README.md
│   │   ├── server.go
│   │   ├── stdio.go
│   │   ├── tool.go
│   │   └── transport.go
│   ├── observability
│   │   └── observability.go
│   ├── razorpay
│   │   ├── mock
│   │   │   ├── server_test.go
│   │   │   └── server.go
│   │   ├── orders_test.go
│   │   ├── orders.go
│   │   ├── payment_links_test.go
│   │   ├── payment_links.go
│   │   ├── payments_test.go
│   │   ├── payments.go
│   │   ├── payouts_test.go
│   │   ├── payouts.go
│   │   ├── qr_codes_test.go
│   │   ├── qr_codes.go
│   │   ├── README.md
│   │   ├── refunds_test.go
│   │   ├── refunds.go
│   │   ├── server.go
│   │   ├── settlements_test.go
│   │   ├── settlements.go
│   │   ├── test_helpers.go
│   │   ├── tokens_test.go
│   │   ├── tokens.go
│   │   ├── tools_params_test.go
│   │   ├── tools_params.go
│   │   ├── tools_test.go
│   │   └── tools.go
│   └── toolsets
│       └── toolsets.go
├── README.md
└── SECURITY.md
```

# Files

--------------------------------------------------------------------------------
/pkg/razorpay/payments_test.go:
--------------------------------------------------------------------------------

```go
package razorpay

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/razorpay/razorpay-go/constants"

	"github.com/razorpay/razorpay-mcp-server/pkg/mcpgo"
	"github.com/razorpay/razorpay-mcp-server/pkg/razorpay/mock"
)

func Test_FetchPayment(t *testing.T) {
	fetchPaymentPathFmt := fmt.Sprintf(
		"/%s%s/%%s",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	paymentResp := map[string]interface{}{
		"id":     "pay_MT48CvBhIC98MQ",
		"amount": float64(1000),
		"status": "captured",
	}

	paymentNotFoundResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "payment not found",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful payment fetch",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(fetchPaymentPathFmt, "pay_MT48CvBhIC98MQ"),
						Method:   "GET",
						Response: paymentResp,
					},
				)
			},
			ExpectError:    false,
			ExpectedResult: paymentResp,
		},
		{
			Name: "payment not found",
			Request: map[string]interface{}{
				"payment_id": "pay_invalid",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(fetchPaymentPathFmt, "pay_invalid"),
						Method:   "GET",
						Response: paymentNotFoundResp,
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "fetching payment failed: payment not found",
		},
		{
			Name:           "missing payment_id parameter",
			Request:        map[string]interface{}{},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: payment_id",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, FetchPayment, "Payment")
		})
	}
}

func Test_FetchPaymentCardDetails(t *testing.T) {
	fetchCardDetailsPathFmt := fmt.Sprintf(
		"/%s%s/%%s/card",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	cardDetailsResp := map[string]interface{}{
		"id":            "card_JXPULjlKqC5j0i",
		"entity":        "card",
		"name":          "Gaurav Kumar",
		"last4":         "4366",
		"network":       "Visa",
		"type":          "credit",
		"issuer":        "UTIB",
		"international": false,
		"emi":           false,
		"sub_type":      "consumer",
		"token_iin":     nil,
	}

	paymentNotFoundResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "The id provided does not exist",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful card details fetch",
			Request: map[string]interface{}{
				"payment_id": "pay_DtFYPi3IfUTgsL",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(fetchCardDetailsPathFmt, "pay_DtFYPi3IfUTgsL"),
						Method:   "GET",
						Response: cardDetailsResp,
					},
				)
			},
			ExpectError:    false,
			ExpectedResult: cardDetailsResp,
		},
		{
			Name: "payment not found",
			Request: map[string]interface{}{
				"payment_id": "pay_invalid",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(fetchCardDetailsPathFmt, "pay_invalid"),
						Method:   "GET",
						Response: paymentNotFoundResp,
					},
				)
			},
			ExpectError: true,
			ExpectedErrMsg: "fetching card details failed: " +
				"The id provided does not exist",
		},
		{
			Name:           "missing payment_id parameter",
			Request:        map[string]interface{}{},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: payment_id",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, FetchPaymentCardDetails, "Card Details")
		})
	}
}

func Test_CapturePayment(t *testing.T) {
	capturePaymentPathFmt := fmt.Sprintf(
		"/%s%s/%%s/capture",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	successfulCaptureResp := map[string]interface{}{
		"id":                "pay_G3P9vcIhRs3NV4",
		"entity":            "payment",
		"amount":            float64(1000),
		"currency":          "INR",
		"status":            "captured",
		"order_id":          "order_GjCr5oKh4AVC51",
		"invoice_id":        nil,
		"international":     false,
		"method":            "card",
		"amount_refunded":   float64(0),
		"refund_status":     nil,
		"captured":          true,
		"description":       "Payment for Adidas shoes",
		"card_id":           "card_KOdY30ajbuyOYN",
		"bank":              nil,
		"wallet":            nil,
		"vpa":               nil,
		"email":             "[email protected]",
		"contact":           "9000090000",
		"customer_id":       "cust_K6fNE0WJZWGqtN",
		"token_id":          "token_KOdY$DBYQOv08n",
		"notes":             []interface{}{},
		"fee":               float64(1),
		"tax":               float64(0),
		"error_code":        nil,
		"error_description": nil,
		"error_source":      nil,
		"error_step":        nil,
		"error_reason":      nil,
		"acquirer_data": map[string]interface{}{
			"authentication_reference_number": "100222021120200000000742753928",
		},
		"created_at": float64(1605871409),
	}

	alreadyCapturedResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "This payment has already been captured",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful payment capture",
			Request: map[string]interface{}{
				"payment_id": "pay_G3P9vcIhRs3NV4",
				"amount":     float64(1000),
				"currency":   "INR",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(capturePaymentPathFmt, "pay_G3P9vcIhRs3NV4"),
						Method:   "POST",
						Response: successfulCaptureResp,
					},
				)
			},
			ExpectError:    false,
			ExpectedResult: successfulCaptureResp,
		},
		{
			Name: "payment already captured",
			Request: map[string]interface{}{
				"payment_id": "pay_G3P9vcIhRs3NV4",
				"amount":     float64(1000),
				"currency":   "INR",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(capturePaymentPathFmt, "pay_G3P9vcIhRs3NV4"),
						Method:   "POST",
						Response: alreadyCapturedResp,
					},
				)
			},
			ExpectError: true,
			ExpectedErrMsg: "capturing payment failed: This payment has already been " +
				"captured",
		},
		{
			Name: "missing payment_id parameter",
			Request: map[string]interface{}{
				"amount":   float64(1000),
				"currency": "INR",
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: payment_id",
		},
		{
			Name: "missing amount parameter",
			Request: map[string]interface{}{
				"payment_id": "pay_G3P9vcIhRs3NV4",
				"currency":   "INR",
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: amount",
		},
		{
			Name: "missing currency parameter",
			Request: map[string]interface{}{
				"payment_id": "pay_G3P9vcIhRs3NV4",
				"amount":     float64(1000),
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: currency",
		},
		{
			Name:    "multiple validation errors",
			Request: map[string]interface{}{
				// All required parameters missing
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "Validation errors:\n- " +
				"missing required parameter: payment_id\n- " +
				"missing required parameter: amount\n- " +
				"missing required parameter: currency",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, CapturePayment, "Payment")
		})
	}
}

func Test_UpdatePayment(t *testing.T) {
	updatePaymentPathFmt := fmt.Sprintf(
		"/%s%s/%%s",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	successfulUpdateResp := map[string]interface{}{
		"id":              "pay_KbCVlLqUbb3VhA",
		"entity":          "payment",
		"amount":          float64(400000),
		"currency":        "INR",
		"status":          "authorized",
		"order_id":        nil,
		"invoice_id":      nil,
		"international":   false,
		"method":          "emi",
		"amount_refunded": float64(0),
		"refund_status":   nil,
		"captured":        false,
		"description":     "Test Transaction",
		"card_id":         "card_KbCVlPnxWRlOpH",
		"bank":            "HDFC",
		"wallet":          nil,
		"vpa":             nil,
		"email":           "[email protected]",
		"contact":         "+919000090000",
		"notes": map[string]interface{}{
			"key1": "value1",
			"key2": "value2",
		},
		"fee":               nil,
		"tax":               nil,
		"error_code":        nil,
		"error_description": nil,
		"error_source":      nil,
		"error_step":        nil,
		"error_reason":      nil,
		"acquirer_data": map[string]interface{}{
			"auth_code": "205480",
		},
		"emi_plan": map[string]interface{}{
			"issuer":   "HDFC",
			"type":     "credit",
			"rate":     float64(1500),
			"duration": float64(24),
		},
		"created_at": float64(1667398779),
	}

	paymentNotFoundResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "The id provided does not exist",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful payment notes update",
			Request: map[string]interface{}{
				"payment_id": "pay_KbCVlLqUbb3VhA",
				"notes": map[string]interface{}{
					"key1": "value1",
					"key2": "value2",
				},
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(updatePaymentPathFmt, "pay_KbCVlLqUbb3VhA"),
						Method:   "PATCH",
						Response: successfulUpdateResp,
					},
				)
			},
			ExpectError:    false,
			ExpectedResult: successfulUpdateResp,
		},
		{
			Name: "payment not found",
			Request: map[string]interface{}{
				"payment_id": "pay_invalid",
				"notes": map[string]interface{}{
					"key1": "value1",
				},
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(updatePaymentPathFmt, "pay_invalid"),
						Method:   "PATCH",
						Response: paymentNotFoundResp,
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "updating payment failed: The id provided does not exist",
		},
		{
			Name: "missing payment_id parameter",
			Request: map[string]interface{}{
				"notes": map[string]interface{}{
					"key1": "value1",
				},
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: payment_id",
		},
		{
			Name: "missing notes parameter",
			Request: map[string]interface{}{
				"payment_id": "pay_KbCVlLqUbb3VhA",
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: notes",
		},
		{
			Name:    "multiple validation errors",
			Request: map[string]interface{}{
				// All required parameters missing
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "Validation errors:\n- " +
				"missing required parameter: payment_id\n- " +
				"missing required parameter: notes",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, UpdatePayment, "Payment")
		})
	}
}

func Test_FetchAllPayments(t *testing.T) {
	fetchAllPaymentsPath := fmt.Sprintf(
		"/%s%s",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	// Sample response for successful fetch
	paymentsListResp := map[string]interface{}{
		"entity": "collection",
		"count":  float64(2),
		"items": []interface{}{
			map[string]interface{}{
				"id":              "pay_KbCFyQ0t9Lmi1n",
				"entity":          "payment",
				"amount":          float64(1000),
				"currency":        "INR",
				"status":          "authorized",
				"order_id":        nil,
				"invoice_id":      nil,
				"international":   false,
				"method":          "netbanking",
				"amount_refunded": float64(0),
				"refund_status":   nil,
				"captured":        false,
				"description":     "Test Transaction",
				"card_id":         nil,
				"bank":            "IBKL",
				"wallet":          nil,
				"vpa":             nil,
				"email":           "[email protected]",
				"contact":         "+919000090000",
				"notes": map[string]interface{}{
					"address": "Razorpay Corporate Office",
				},
				"fee":               nil,
				"tax":               nil,
				"error_code":        nil,
				"error_description": nil,
				"error_source":      nil,
				"error_step":        nil,
				"error_reason":      nil,
				"acquirer_data": map[string]interface{}{
					"bank_transaction_id": "5733649",
				},
				"created_at": float64(1667397881),
			},
			map[string]interface{}{
				"id":              "pay_KbCEDHh1IrU4RJ",
				"entity":          "payment",
				"amount":          float64(1000),
				"currency":        "INR",
				"status":          "authorized",
				"order_id":        nil,
				"invoice_id":      nil,
				"international":   false,
				"method":          "upi",
				"amount_refunded": float64(0),
				"refund_status":   nil,
				"captured":        false,
				"description":     "Test Transaction",
				"card_id":         nil,
				"bank":            nil,
				"wallet":          nil,
				"vpa":             "gaurav.kumar@okhdfcbank",
				"email":           "[email protected]",
				"contact":         "+919000090000",
				"notes": map[string]interface{}{
					"address": "Razorpay Corporate Office",
				},
				"fee":               nil,
				"tax":               nil,
				"error_code":        nil,
				"error_description": nil,
				"error_source":      nil,
				"error_step":        nil,
				"error_reason":      nil,
				"acquirer_data": map[string]interface{}{
					"rrn":                "230901495295",
					"upi_transaction_id": "6935B87A72C2A7BC83FA927AA264AD53",
				},
				"created_at": float64(1667397781),
			},
		},
	}

	// Error response when parameters are invalid
	invalidParamsResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "from must be between 946684800 and 4765046400",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful payments fetch with all parameters",
			Request: map[string]interface{}{
				"from":  float64(1593320020),
				"to":    float64(1624856020),
				"count": float64(2),
				"skip":  float64(1),
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fetchAllPaymentsPath,
						Method:   "GET",
						Response: paymentsListResp,
					},
				)
			},
			ExpectError:    false,
			ExpectedResult: paymentsListResp,
		},
		{
			Name: "payments fetch with invalid timestamp",
			Request: map[string]interface{}{
				"from": float64(900000000), // Invalid timestamp (too early)
				"to":   float64(1624856020),
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fetchAllPaymentsPath,
						Method:   "GET",
						Response: invalidParamsResp,
					},
				)
			},
			ExpectError: true,
			ExpectedErrMsg: "fetching payments failed: from must be between " +
				"946684800 and 4765046400",
		},
		{
			Name: "multiple validation errors with wrong types",
			Request: map[string]interface{}{
				"count": "not_a_number",
				"skip":  "not_a_number",
				"from":  "not_a_number",
				"to":    "not_a_number",
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "Validation errors:\n- " +
				"invalid parameter type: count\n- " +
				"invalid parameter type: skip\n- " +
				"invalid parameter type: from\n- " +
				"invalid parameter type: to",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, FetchAllPayments, "Payments List")
		})
	}
}

func Test_InitiatePayment(t *testing.T) {
	initiatePaymentPath := fmt.Sprintf(
		"/%s%s/create/json",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	createCustomerPath := fmt.Sprintf(
		"/%s%s",
		constants.VERSION_V1,
		constants.CUSTOMER_URL,
	)

	customerResp := map[string]interface{}{
		"id":         "cust_1Aa00000000003",
		"entity":     "customer",
		"name":       "",
		"email":      "",
		"contact":    "9876543210",
		"gstin":      nil,
		"notes":      map[string]interface{}{},
		"created_at": float64(1234567890),
	}

	successPaymentWithRedirectResp := map[string]interface{}{
		"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
		"status":              "created",
		"amount":              float64(10000),
		"currency":            "INR",
		"order_id":            "order_129837127313912",
		"next": []interface{}{
			map[string]interface{}{
				"action": "redirect",
				"url": "https://api.razorpay.com/v1/payments/" +
					"pay_MT48CvBhIC98MQ/authenticate",
			},
		},
	}

	successPaymentWithoutNextResp := map[string]interface{}{
		"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
		"status":              "captured",
		"amount":              float64(10000),
		"currency":            "INR",
		"order_id":            "order_129837127313912",
	}

	paymentErrorResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "Invalid token",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful payment initiation without next actions",
			Request: map[string]interface{}{
				"amount":   10000,
				"currency": "INR",
				"token":    "token_MT48CvBhIC98MQ",
				"order_id": "order_129837127313912",
				"email":    "[email protected]",
				"contact":  "9876543210",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successPaymentWithoutNextResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details":     successPaymentWithoutNextResp,
				"status":              "payment_initiated",
				"message": "Payment initiated successfully using " +
					"S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
				},
			},
		},
		{
			Name: "successful payment initiation with redirect",
			Request: map[string]interface{}{
				"amount":   10000,
				"token":    "token_MT48CvBhIC98MQ",
				"order_id": "order_129837127313912",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successPaymentWithRedirectResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details":     successPaymentWithRedirectResp,
				"status":              "payment_initiated",
				"message": "Payment initiated. Redirect authentication is available. " +
					"Use the redirect URL provided in available_actions.",
				"available_actions": []interface{}{
					map[string]interface{}{
						"action": "redirect",
						"url": "https://api.razorpay.com/v1/payments/" +
							"pay_MT48CvBhIC98MQ/authenticate",
					},
				},
			},
		},
		{
			Name: "successful payment initiation with contact only",
			Request: map[string]interface{}{
				"amount":   10000,
				"token":    "token_MT48CvBhIC98MQ",
				"order_id": "order_129837127313912",
				"contact":  "9876543210",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successPaymentWithoutNextResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details":     successPaymentWithoutNextResp,
				"status":              "payment_initiated",
				"message": "Payment initiated successfully using " +
					"S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
				},
			},
		},
		{
			Name: "payment initiation with API error",
			Request: map[string]interface{}{
				"amount":   10000,
				"token":    "token_invalid",
				"order_id": "order_129837127313912",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: paymentErrorResp,
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "initiating payment failed:",
		},
		{
			Name: "missing required amount parameter",
			Request: map[string]interface{}{
				"token":    "token_MT48CvBhIC98MQ",
				"order_id": "order_129837127313912",
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: amount",
		},
		{
			Name: "missing required order_id parameter",
			Request: map[string]interface{}{
				"amount": 10000,
				"token":  "token_MT48CvBhIC98MQ",
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: order_id",
		},
		{
			Name: "invalid amount parameter type",
			Request: map[string]interface{}{
				"amount":   "not_a_number",
				"token":    "token_MT48CvBhIC98MQ",
				"order_id": "order_129837127313912",
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "invalid parameter type: amount",
		},
		{
			Name: "multiple validation errors",
			Request: map[string]interface{}{
				"amount": "not_a_number",
				"token":  123,
				"email":  456,
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "Validation errors:\n- invalid parameter type: amount\n- " +
				"invalid parameter type: token\n- " +
				"missing required parameter: order_id\n- " +
				"invalid parameter type: email",
		},
		{
			Name: "successful UPI collect flow payment initiation",
			Request: map[string]interface{}{
				"amount":      10000,
				"currency":    "INR",
				"order_id":    "order_129837127313912",
				"email":       "[email protected]",
				"contact":     "9876543210",
				"customer_id": "cust_RGCgP2osfPKFq2",
				"save":        true,
				"vpa":         "9876543210@ptsbi",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiCollectResp := map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_collect",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_MT48CvBhIC98MQ/authenticate",
						},
					},
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiCollectResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_collect",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_MT48CvBhIC98MQ/authenticate",
						},
					},
				},
				"status":  "payment_initiated",
				"message": "Payment initiated. Available actions: [upi_collect]",
				"available_actions": []interface{}{
					map[string]interface{}{
						"action": "upi_collect",
						"url": "https://api.razorpay.com/v1/payments/" +
							"pay_MT48CvBhIC98MQ/authenticate",
					},
				},
			},
		},
		{
			Name: "successful UPI collect flow without token",
			Request: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_129837127313912",
				"contact":  "9876543210",
				"vpa":      "9876543210@ptsbi",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiCollectResp := map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiCollectResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
				},
				"status": "payment_initiated",
				"message": "Payment initiated successfully using " +
					"S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
				},
			},
		},
		{
			Name: "UPI collect flow with all optional parameters",
			Request: map[string]interface{}{
				"amount":      10000,
				"currency":    "INR",
				"order_id":    "order_129837127313912",
				"email":       "[email protected]",
				"contact":     "9876543210",
				"customer_id": "cust_RGCgP2osfPKFq2",
				"save":        false,
				"vpa":         "test@paytm",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiCollectResp := map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiCollectResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
				},
				"status": "payment_initiated",
				"message": "Payment initiated successfully using " +
					"S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
				},
			},
		},
		{
			Name: "invalid save parameter type",
			Request: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_129837127313912",
				"save":     "invalid_string_instead_of_bool",
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "invalid parameter type: save",
		},
		{
			Name: "invalid customer_id parameter type",
			Request: map[string]interface{}{
				"amount":      10000,
				"order_id":    "order_129837127313912",
				"customer_id": 123,
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "invalid parameter type: customer_id",
		},
		{
			Name: "successful UPI intent flow payment initiation",
			Request: map[string]interface{}{
				"amount":     12000,
				"currency":   "INR",
				"order_id":   "order_INTENT123",
				"email":      "[email protected]",
				"contact":    "9876543210",
				"upi_intent": true,
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiIntentResp := map[string]interface{}{
					"razorpay_payment_id": "pay_INTENT123",
					"status":              "created",
					"amount":              float64(12000),
					"currency":            "INR",
					"order_id":            "order_INTENT123",
					"method":              "upi",
					"upi": map[string]interface{}{
						"flow": "intent",
					},
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_intent",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_INTENT123/upi_intent",
						},
					},
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiIntentResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_INTENT123",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_INTENT123",
					"status":              "created",
					"amount":              float64(12000),
					"currency":            "INR",
					"order_id":            "order_INTENT123",
					"method":              "upi",
					"upi": map[string]interface{}{
						"flow": "intent",
					},
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_intent",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_INTENT123/upi_intent",
						},
					},
				},
				"status":  "payment_initiated",
				"message": "Payment initiated. Available actions: [upi_intent]",
				"available_actions": []interface{}{
					map[string]interface{}{
						"action": "upi_intent",
						"url": "https://api.razorpay.com/v1/payments/" +
							"pay_INTENT123/upi_intent",
					},
				},
			},
		},
		{
			Name: "invalid upi_intent parameter type",
			Request: map[string]interface{}{
				"amount":     10000,
				"order_id":   "order_129837127313912",
				"upi_intent": "invalid_string",
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "invalid parameter type: upi_intent",
		},
		{
			Name: "successful payment initiation with force_terminal_id " +
				"for single block multiple debit",
			Request: map[string]interface{}{
				"amount":            10000,
				"currency":          "INR",
				"order_id":          "order_129837127313912",
				"email":             "[email protected]",
				"contact":           "9876543210",
				"customer_id":       "cust_RGCgP2osfPKFq2",
				"recurring":         true,
				"force_terminal_id": "term_ABCD1234256732",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successPaymentWithTerminalResp := map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
					"force_terminal_id":   "term_ABCD1234256732",
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successPaymentWithTerminalResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
					"force_terminal_id":   "term_ABCD1234256732",
				},
				"status":  "payment_initiated",
				"message": "Payment initiated successfully using S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
				},
			},
		},
		{
			Name: "invalid force_terminal_id parameter type",
			Request: map[string]interface{}{
				"amount":            10000,
				"order_id":          "order_129837127313912",
				"force_terminal_id": 123,
			},
			MockHttpClient: nil,
			ExpectError:    true,
			ExpectedErrMsg: "invalid parameter type: force_terminal_id",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, InitiatePayment, "Payment Initiation")
		})
	}
}

func Test_SubmitOtp(t *testing.T) {
	submitOtpPathFmt := fmt.Sprintf(
		"/%s%s/%%s/otp/submit",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	successOtpSubmitResp := map[string]interface{}{
		"id":                "pay_MT48CvBhIC98MQ",
		"entity":            "payment",
		"amount":            float64(10000),
		"currency":          "INR",
		"status":            "authorized",
		"order_id":          "order_129837127313912",
		"description":       "Test payment",
		"method":            "card",
		"amount_refunded":   float64(0),
		"refund_status":     nil,
		"captured":          false,
		"email":             "[email protected]",
		"contact":           "9876543210",
		"fee":               float64(236),
		"tax":               float64(36),
		"error_code":        nil,
		"error_description": nil,
		"created_at":        float64(1234567890),
	}

	otpVerificationFailedResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "Invalid OTP provided",
			"field":       "otp",
		},
	}

	paymentNotFoundResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "Payment not found",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful OTP submission",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
				"otp_string": "123456",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(submitOtpPathFmt, "pay_MT48CvBhIC98MQ"),
						Method:   "POST",
						Response: successOtpSubmitResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"payment_id":    "pay_MT48CvBhIC98MQ",
				"status":        "success",
				"message":       "OTP verified successfully.",
				"response_data": successOtpSubmitResp,
			},
		},
		{
			Name: "OTP verification failed - invalid OTP",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
				"otp_string": "000000",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(submitOtpPathFmt, "pay_MT48CvBhIC98MQ"),
						Method:   "POST",
						Response: otpVerificationFailedResp,
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP verification failed: Invalid OTP provided",
		},
		{
			Name: "payment not found",
			Request: map[string]interface{}{
				"payment_id": "pay_invalid",
				"otp_string": "123456",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(submitOtpPathFmt, "pay_invalid"),
						Method:   "POST",
						Response: paymentNotFoundResp,
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP verification failed: Payment not found",
		},
		{
			Name: "missing payment_id parameter",
			Request: map[string]interface{}{
				"otp_string": "123456",
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: payment_id",
		},
		{
			Name: "missing otp_string parameter",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: otp_string",
		},
		{
			Name:           "missing both required parameters",
			Request:        map[string]interface{}{},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: otp_string",
		},
		{
			Name: "empty otp_string",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
				"otp_string": "",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   fmt.Sprintf(submitOtpPathFmt, "pay_MT48CvBhIC98MQ"),
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Authentication failed",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP verification failed: Authentication failed",
		},
		{
			Name: "empty payment_id",
			Request: map[string]interface{}{
				"payment_id": "",
				"otp_string": "123456",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   fmt.Sprintf(submitOtpPathFmt, ""),
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP verification failed:",
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, SubmitOtp, "OTP Submission")
		})
	}
}

func Test_InitiatePaymentWithVPA(t *testing.T) {
	initiatePaymentPath := fmt.Sprintf(
		"/%s%s/create/json",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	createCustomerPath := fmt.Sprintf(
		"/%s%s",
		constants.VERSION_V1,
		constants.CUSTOMER_URL,
	)

	customerResp := map[string]interface{}{
		"id":         "cust_1Aa00000000003",
		"entity":     "customer",
		"name":       "",
		"email":      "",
		"contact":    "9876543210",
		"gstin":      nil,
		"notes":      map[string]interface{}{},
		"created_at": float64(1234567890),
	}

	testCases := []RazorpayToolTestCase{
		{
			Name: "successful UPI payment with VPA parameter",
			Request: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_129837127313912",
				"vpa":      "9876543210@ptsbi",
				"email":    "[email protected]",
				"contact":  "9876543210",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiVpaResp := map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
					"email":               "[email protected]",
					"contact":             "9876543210",
					"upi_transaction_id":  nil,
					"upi": map[string]interface{}{
						"flow":        "collect",
						"expiry_time": "6",
						"vpa":         "9876543210@ptsbi",
					},
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_collect",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_MT48CvBhIC98MQ/otp_generate",
						},
					},
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     createCustomerPath,
						Method:   "POST",
						Response: customerResp,
					},
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiVpaResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
					"method":              "upi",
					"email":               "[email protected]",
					"contact":             "9876543210",
					"upi_transaction_id":  nil,
					"upi": map[string]interface{}{
						"flow":        "collect",
						"expiry_time": "6",
						"vpa":         "9876543210@ptsbi",
					},
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_collect",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_MT48CvBhIC98MQ/otp_generate",
						},
					},
				},
				"status":  "payment_initiated",
				"message": "Payment initiated. Available actions: [upi_collect]",
				"available_actions": []interface{}{
					map[string]interface{}{
						"action": "upi_collect",
						"url": "https://api.razorpay.com/v1/payments/" +
							"pay_MT48CvBhIC98MQ/otp_generate",
					},
				},
			},
		},
		{
			Name: "UPI payment with VPA and custom currency",
			Request: map[string]interface{}{
				"amount":   20000,
				"currency": "INR",
				"order_id": "order_ABC123XYZ456",
				"vpa":      "test@upi",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiVpaResp := map[string]interface{}{
					"razorpay_payment_id": "pay_ABC123XYZ456",
					"status":              "created",
					"amount":              float64(20000),
					"currency":            "INR",
					"order_id":            "order_ABC123XYZ456",
					"method":              "upi",
					"upi": map[string]interface{}{
						"flow":        "collect",
						"expiry_time": "6",
						"vpa":         "test@upi",
					},
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiVpaResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_ABC123XYZ456",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_ABC123XYZ456",
					"status":              "created",
					"amount":              float64(20000),
					"currency":            "INR",
					"order_id":            "order_ABC123XYZ456",
					"method":              "upi",
					"upi": map[string]interface{}{
						"flow":        "collect",
						"expiry_time": "6",
						"vpa":         "test@upi",
					},
				},
				"status": "payment_initiated",
				"message": "Payment initiated successfully using " +
					"S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_ABC123XYZ456",
				},
			},
		},
		{
			Name: "missing VPA parameter value",
			Request: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_129837127313912",
				"vpa":      "",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successRegularResp := map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successRegularResp,
					},
				)
			},
			ExpectError: false, // Empty VPA should not trigger UPI logic
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
					"amount":              float64(10000),
					"currency":            "INR",
					"order_id":            "order_129837127313912",
				},
				"status": "payment_initiated",
				"message": "Payment initiated successfully using " +
					"S2S JSON v1 flow",
				"next_step": "Use 'resend_otp' to regenerate OTP or " +
					"'submit_otp' to proceed to enter OTP if " +
					"OTP authentication is required.",
				"next_tool": "resend_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
				},
			},
		},
		{
			Name: "VPA parameter automatically sets UPI method",
			Request: map[string]interface{}{
				"amount":   15000,
				"order_id": "order_OVERRIDE123",
				"vpa":      "new@upi",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				successUpiOverrideResp := map[string]interface{}{
					"razorpay_payment_id": "pay_OVERRIDE123",
					"status":              "created",
					"amount":              float64(15000),
					"currency":            "INR",
					"order_id":            "order_OVERRIDE123",
					"method":              "upi", // Should be set to UPI by VPA
					"upi": map[string]interface{}{
						"flow":        "collect", // Default flow
						"expiry_time": "6",       // Default expiry
						"vpa":         "new@upi", // VPA from parameter
					},
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_collect",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_OVERRIDE123/otp_generate",
						},
					},
				}
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     initiatePaymentPath,
						Method:   "POST",
						Response: successUpiOverrideResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"razorpay_payment_id": "pay_OVERRIDE123",
				"payment_details": map[string]interface{}{
					"razorpay_payment_id": "pay_OVERRIDE123",
					"status":              "created",
					"amount":              float64(15000),
					"currency":            "INR",
					"order_id":            "order_OVERRIDE123",
					"method":              "upi",
					"upi": map[string]interface{}{
						"flow":        "collect",
						"expiry_time": "6",
						"vpa":         "new@upi",
					},
					"next": []interface{}{
						map[string]interface{}{
							"action": "upi_collect",
							"url": "https://api.razorpay.com/v1/payments/" +
								"pay_OVERRIDE123/otp_generate",
						},
					},
				},
				"status":  "payment_initiated",
				"message": "Payment initiated. Available actions: [upi_collect]",
				"available_actions": []interface{}{
					map[string]interface{}{
						"action": "upi_collect",
						"url": "https://api.razorpay.com/v1/payments/" +
							"pay_OVERRIDE123/otp_generate",
					},
				},
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, InitiatePayment, "Payment")
		})
	}
}

// Test helper functions for better coverage
func Test_extractPaymentID(t *testing.T) {
	tests := []struct {
		name     string
		payment  map[string]interface{}
		expected string
	}{
		{
			name: "valid payment ID",
			payment: map[string]interface{}{
				"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
				"status":              "created",
			},
			expected: "pay_MT48CvBhIC98MQ",
		},
		{
			name: "missing payment ID",
			payment: map[string]interface{}{
				"status": "created",
			},
			expected: "",
		},
		{
			name: "nil payment ID",
			payment: map[string]interface{}{
				"razorpay_payment_id": nil,
				"status":              "created",
			},
			expected: "",
		},
		{
			name:     "empty payment map",
			payment:  map[string]interface{}{},
			expected: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := extractPaymentID(tt.payment)
			if result != tt.expected {
				t.Errorf("extractPaymentID() = %v, want %v", result, tt.expected)
			}
		})
	}
}

func Test_buildInitiatePaymentResponse(t *testing.T) {
	tests := []struct {
		name           string
		payment        map[string]interface{}
		paymentID      string
		actions        []map[string]interface{}
		expectedMsg    string
		expectedOtpURL string
	}{
		{
			name: "payment with OTP action",
			payment: map[string]interface{}{
				"id":     "pay_MT48CvBhIC98MQ",
				"status": "created",
			},
			paymentID: "pay_MT48CvBhIC98MQ",
			actions: []map[string]interface{}{
				{
					"action": "otp_generate",
					"url": "https://api.razorpay.com/v1/payments/" +
						"pay_MT48CvBhIC98MQ/otp_generate",
				},
			},
			expectedMsg: "Payment initiated. OTP authentication is available. " +
				"Use the 'submit_otp' tool to submit OTP received by the customer " +
				"for authentication.",
			expectedOtpURL: "https://api.razorpay.com/v1/payments/" +
				"pay_MT48CvBhIC98MQ/otp_generate",
		},
		{
			name: "payment with redirect action",
			payment: map[string]interface{}{
				"id":     "pay_MT48CvBhIC98MQ",
				"status": "created",
			},
			paymentID: "pay_MT48CvBhIC98MQ",
			actions: []map[string]interface{}{
				{
					"action": "redirect",
					"url": "https://api.razorpay.com/v1/payments/" +
						"pay_MT48CvBhIC98MQ/authenticate",
				},
			},
			expectedMsg: "Payment initiated. Redirect authentication is available. " +
				"Use the redirect URL provided in available_actions.",
			expectedOtpURL: "",
		},
		{
			name: "payment with UPI collect action",
			payment: map[string]interface{}{
				"id":     "pay_MT48CvBhIC98MQ",
				"status": "created",
			},
			paymentID: "pay_MT48CvBhIC98MQ",
			actions: []map[string]interface{}{
				{
					"action": "upi_collect",
					"url": "https://api.razorpay.com/v1/payments/" +
						"pay_MT48CvBhIC98MQ/authenticate",
				},
			},
			expectedMsg:    "Payment initiated. Available actions: [upi_collect]",
			expectedOtpURL: "",
		},
		{
			name: "payment with multiple actions including OTP",
			payment: map[string]interface{}{
				"id":     "pay_MT48CvBhIC98MQ",
				"status": "created",
			},
			paymentID: "pay_MT48CvBhIC98MQ",
			actions: []map[string]interface{}{
				{
					"action": "otp_generate",
					"url": "https://api.razorpay.com/v1/payments/" +
						"pay_MT48CvBhIC98MQ/otp_generate",
				},
				{
					"action": "redirect",
					"url": "https://api.razorpay.com/v1/payments/" +
						"pay_MT48CvBhIC98MQ/authenticate",
				},
			},
			expectedMsg: "Payment initiated. OTP authentication is available. " +
				"Use the 'submit_otp' tool to submit OTP received by the customer " +
				"for authentication.",
			expectedOtpURL: "https://api.razorpay.com/v1/payments/" +
				"pay_MT48CvBhIC98MQ/otp_generate",
		},
		{
			name: "payment with no actions",
			payment: map[string]interface{}{
				"id":     "pay_MT48CvBhIC98MQ",
				"status": "captured",
			},
			paymentID:      "pay_MT48CvBhIC98MQ",
			actions:        []map[string]interface{}{},
			expectedMsg:    "Payment initiated successfully using S2S JSON v1 flow",
			expectedOtpURL: "",
		},
		{
			name: "payment with unknown action",
			payment: map[string]interface{}{
				"id":     "pay_MT48CvBhIC98MQ",
				"status": "created",
			},
			paymentID: "pay_MT48CvBhIC98MQ",
			actions: []map[string]interface{}{
				{
					"action": "unknown_action",
					"url": "https://api.razorpay.com/v1/payments/" +
						"pay_MT48CvBhIC98MQ/unknown",
				},
			},
			expectedMsg:    "Payment initiated. Available actions: [unknown_action]",
			expectedOtpURL: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			response, otpURL := buildInitiatePaymentResponse(
				tt.payment, tt.paymentID, tt.actions)

			// Check basic response structure
			if response["razorpay_payment_id"] != tt.paymentID {
				t.Errorf("Expected payment ID %s, got %v", tt.paymentID,
					response["razorpay_payment_id"])
			}

			if response["status"] != "payment_initiated" {
				t.Errorf("Expected status 'payment_initiated', got %v", response["status"])
			}

			// Check message
			if response["message"] != tt.expectedMsg {
				t.Errorf("Expected message %s, got %v", tt.expectedMsg, response["message"])
			}

			// Check OTP URL
			if otpURL != tt.expectedOtpURL {
				t.Errorf("Expected OTP URL %s, got %s", tt.expectedOtpURL, otpURL)
			}

			// Check actions are included when present
			if len(tt.actions) > 0 {
				if _, exists := response["available_actions"]; !exists {
					t.Error("Expected available_actions to be present in response")
				}
			}

			// Check next step instructions for OTP case
			if tt.paymentID != "" && len(tt.actions) == 0 {
				if _, exists := response["next_step"]; !exists {
					t.Error("Expected next_step to be present for fallback case")
				}
			}
		})
	}
}

func Test_addNextStepInstructions(t *testing.T) {
	tests := []struct {
		name      string
		paymentID string
		expected  bool // whether next_step should be added
	}{
		{
			name:      "valid payment ID",
			paymentID: "pay_MT48CvBhIC98MQ",
			expected:  true,
		},
		{
			name:      "empty payment ID",
			paymentID: "",
			expected:  false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			response := make(map[string]interface{})
			addNextStepInstructions(response, tt.paymentID)

			if tt.expected {
				if _, exists := response["next_step"]; !exists {
					t.Error("Expected next_step to be added")
				}
				if _, exists := response["next_tool"]; !exists {
					t.Error("Expected next_tool to be added")
				}
				if _, exists := response["next_tool_params"]; !exists {
					t.Error("Expected next_tool_params to be added")
				}

				// Check specific values
				if response["next_tool"] != "resend_otp" {
					t.Errorf("Expected next_tool to be 'resend_otp', got %v",
						response["next_tool"])
				}

				params, ok := response["next_tool_params"].(map[string]interface{})
				if !ok || params["payment_id"] != tt.paymentID {
					t.Errorf("Expected next_tool_params to contain payment_id %s",
						tt.paymentID)
				}
			} else {
				if _, exists := response["next_step"]; exists {
					t.Error("Expected next_step NOT to be added for empty payment ID")
				}
			}
		})
	}
}

func Test_sendOtp_validation(t *testing.T) {
	tests := []struct {
		name        string
		otpURL      string
		expectedErr string
	}{
		{
			name:        "empty URL",
			otpURL:      "",
			expectedErr: "OTP URL is empty",
		},
		{
			name:        "invalid URL",
			otpURL:      "not-a-valid-url",
			expectedErr: "OTP URL must use HTTPS",
		},
		{
			name:        "non-HTTPS URL",
			otpURL:      "http://api.razorpay.com/v1/payments/pay_123/otp_generate",
			expectedErr: "OTP URL must use HTTPS",
		},
		{
			name:        "non-Razorpay domain",
			otpURL:      "https://malicious.com/v1/payments/pay_123/otp_generate",
			expectedErr: "OTP URL must be from Razorpay domain",
		},
		{
			name:        "valid Razorpay URL - should fail at HTTP call",
			otpURL:      "https://api.razorpay.com/v1/payments/pay_123/otp_generate",
			expectedErr: "OTP generation failed",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := sendOtp(tt.otpURL)
			if err == nil {
				t.Error("Expected error but got nil")
				return
			}

			if tt.expectedErr != "" && !strings.Contains(err.Error(), tt.expectedErr) {
				t.Errorf("Expected error to contain '%s', got '%s'",
					tt.expectedErr, err.Error())
			}
		})
	}
}

func Test_extractOtpSubmitURL(t *testing.T) {
	tests := []struct {
		name     string
		payment  map[string]interface{}
		expected string
	}{
		{
			name: "payment with next actions containing otp_submit",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						"action": "otp_submit",
						"url":    "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
					},
				},
			},
			expected: "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
		},
		{
			name: "payment with multiple next actions",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						"action": "redirect",
						"url":    "https://api.razorpay.com/v1/payments/pay_123/authenticate",
					},
					map[string]interface{}{
						"action": "otp_submit",
						"url":    "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
					},
				},
			},
			expected: "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
		},
		{
			name: "payment with no next actions",
			payment: map[string]interface{}{
				"status": "captured",
			},
			expected: "",
		},
		{
			name: "payment with next actions but no otp_submit",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						"action": "redirect",
						"url":    "https://api.razorpay.com/v1/payments/pay_123/authenticate",
					},
				},
			},
			expected: "",
		},
		{
			name: "payment with empty next array",
			payment: map[string]interface{}{
				"next": []interface{}{},
			},
			expected: "",
		},
		{
			name: "payment with invalid next structure",
			payment: map[string]interface{}{
				"next": "invalid_structure",
			},
			expected: "",
		},
		{
			name: "payment with otp_submit action but nil URL",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						"action": "otp_submit",
						"url":    nil, // nil URL should return empty string
					},
				},
			},
			expected: "",
		},
		{
			name: "payment with otp_submit action but non-string URL",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						"action": "otp_submit",
						"url":    123, // non-string URL should cause type assertion to fail
					},
				},
			},
			expected: "",
		},
		{
			name: "payment with otp_submit action but missing URL field",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						"action": "otp_submit",
						// no url field
					},
				},
			},
			expected: "",
		},
		{
			name: "payment with mixed valid and invalid items in next array",
			payment: map[string]interface{}{
				"next": []interface{}{
					"invalid_item", // This should be skipped
					map[string]interface{}{
						"action": "redirect",
						"url":    "https://example.com/redirect",
					},
					123, // Another invalid item that should be skipped
					map[string]interface{}{
						"action": "otp_submit",
						"url":    "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
					},
				},
			},
			expected: "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
		},
		{
			name: "payment with otp_submit action but missing action field",
			payment: map[string]interface{}{
				"next": []interface{}{
					map[string]interface{}{
						// no action field
						"url": "https://api.razorpay.com/v1/payments/pay_123/otp/submit",
					},
				},
			},
			expected: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := extractOtpSubmitURL(tt.payment)
			if result != tt.expected {
				t.Errorf("extractOtpSubmitURL() = %v, want %v", result, tt.expected)
			}
		})
	}
}

// Test_extractOtpSubmitURL_invalidInput tests the
// function with invalid input types
func Test_extractOtpSubmitURL_invalidInput(t *testing.T) {
	tests := []struct {
		name     string
		input    interface{}
		expected string
	}{
		{
			name:     "nil input",
			input:    nil,
			expected: "",
		},
		{
			name:     "string input instead of map",
			input:    "invalid_input",
			expected: "",
		},
		{
			name:     "integer input instead of map",
			input:    123,
			expected: "",
		},
		{
			name:     "slice input instead of map",
			input:    []string{"invalid"},
			expected: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := extractOtpSubmitURL(tt.input)
			if result != tt.expected {
				t.Errorf("extractOtpSubmitURL() = %v, want %v", result, tt.expected)
			}
		})
	}
}

func Test_ResendOtp(t *testing.T) {
	resendOtpPathFmt := fmt.Sprintf(
		"/%s%s/%%s/otp/resend",
		constants.VERSION_V1,
		constants.PAYMENT_URL,
	)

	successResendOtpResp := map[string]interface{}{
		"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
		"next": []interface{}{
			map[string]interface{}{
				"action": "otp_submit",
				"url": "https://api.razorpay.com/v1/payments/" +
					"pay_MT48CvBhIC98MQ/otp/submit",
			},
		},
	}

	paymentNotFoundResp := map[string]interface{}{
		"error": map[string]interface{}{
			"code":        "BAD_REQUEST_ERROR",
			"description": "Payment not found",
		},
	}

	tests := []RazorpayToolTestCase{
		{
			Name: "successful OTP resend",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(resendOtpPathFmt, "pay_MT48CvBhIC98MQ"),
						Method:   "POST",
						Response: successResendOtpResp,
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
				"status":     "success",
				"message": "OTP sent successfully. Please enter the OTP received on your " +
					"mobile number to complete the payment.",
				"next_step": "Use 'submit_otp' tool with the OTP code received " +
					"from user to complete payment authentication.",
				"next_tool": "submit_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
					"otp_string": "{OTP_CODE_FROM_USER}",
				},
				"otp_submit_url": "https://api.razorpay.com/v1/payments/" +
					"pay_MT48CvBhIC98MQ/otp/submit",
				"response_data": successResendOtpResp,
			},
		},
		{
			Name: "payment not found for OTP resend",
			Request: map[string]interface{}{
				"payment_id": "pay_invalid",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:     fmt.Sprintf(resendOtpPathFmt, "pay_invalid"),
						Method:   "POST",
						Response: paymentNotFoundResp,
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP resend failed: Payment not found",
		},
		{
			Name:    "missing payment_id parameter for resend",
			Request: map[string]interface{}{
				// No payment_id provided
			},
			MockHttpClient: nil, // No HTTP client needed for validation error
			ExpectError:    true,
			ExpectedErrMsg: "missing required parameter: payment_id",
		},
		{
			Name: "OTP resend without next actions",
			Request: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   fmt.Sprintf(resendOtpPathFmt, "pay_MT48CvBhIC98MQ"),
						Method: "POST",
						Response: map[string]interface{}{
							"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
							"status":              "created",
						},
					},
				)
			},
			ExpectError: false,
			ExpectedResult: map[string]interface{}{
				"payment_id": "pay_MT48CvBhIC98MQ",
				"status":     "success",
				"message": "OTP sent successfully. Please enter the OTP received on your " +
					"mobile number to complete the payment.",
				"next_step": "Use 'submit_otp' tool with the OTP code received " +
					"from user to complete payment authentication.",
				"next_tool": "submit_otp",
				"next_tool_params": map[string]interface{}{
					"payment_id": "pay_MT48CvBhIC98MQ",
					"otp_string": "{OTP_CODE_FROM_USER}",
				},
				"response_data": map[string]interface{}{
					"razorpay_payment_id": "pay_MT48CvBhIC98MQ",
					"status":              "created",
				},
			},
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {
			runToolTest(t, tc, ResendOtp, "OTP Resend")
		})
	}
}

// Test_sendOtp_additionalCases tests additional cases for sendOtp function
func Test_sendOtp_additionalCases(t *testing.T) {
	tests := []struct {
		name        string
		otpURL      string
		expectedErr string
	}{
		{
			name: "URL with invalid characters",
			otpURL: "https://api.razorpay.com/v1/payments/pay_123/" +
				"otp_generate?param=value with spaces",
			expectedErr: "OTP generation failed",
		},
		{
			name: "URL with special characters in domain",
			otpURL: "https://api-test.razorpay.com/v1/payments/" +
				"pay_123/otp_generate",
			expectedErr: "OTP generation failed",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := sendOtp(tt.otpURL)
			if err == nil {
				t.Error("Expected error but got nil")
				return
			}
			if tt.expectedErr != "" && !strings.Contains(err.Error(), tt.expectedErr) {
				t.Errorf(
					"Expected error to contain '%s', got '%s'", tt.expectedErr, err.Error(),
				)
			}
		})
	}
}

// Test_buildPaymentData_edgeCases tests edge cases for
// buildPaymentData function
func Test_buildPaymentData_edgeCases(t *testing.T) {
	tests := []struct {
		name          string
		params        map[string]interface{}
		currency      string
		customerID    string
		expectedError string
		shouldContain map[string]interface{}
	}{
		{
			name: "payment data with valid customer ID",
			params: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
			},
			currency:   "INR",
			customerID: "cust_123456789",
			shouldContain: map[string]interface{}{
				"amount":      10000,
				"currency":    "INR",
				"order_id":    "order_123",
				"customer_id": "cust_123456789",
			},
		},
		{
			name: "payment data with empty token",
			params: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"token":    "", // Empty token should not be added
			},
			currency:   "INR",
			customerID: "cust_123456789",
			shouldContain: map[string]interface{}{
				"amount":      10000,
				"currency":    "INR",
				"order_id":    "order_123",
				"customer_id": "cust_123456789",
			},
		},
		{
			name: "payment data with empty customer ID",
			params: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"token":    "token_123",
			},
			currency:   "INR",
			customerID: "",
			shouldContain: map[string]interface{}{
				"amount":   10000,
				"currency": "INR",
				"order_id": "order_123",
				"token":    "token_123",
			},
		},
		{
			name: "payment data with all parameters",
			params: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"token":    "token_123",
				"email":    "[email protected]",
				"contact":  "9876543210",
				"method":   "upi",
				"save":     true,
				"upi": map[string]interface{}{
					"flow":        "collect",
					"expiry_time": "6",
					"vpa":         "test@upi",
				},
			},
			currency:   "INR",
			customerID: "cust_123456789",
			shouldContain: map[string]interface{}{
				"amount":      10000,
				"currency":    "INR",
				"order_id":    "order_123",
				"customer_id": "cust_123456789",
				"token":       "token_123",
				"email":       "[email protected]",
				"contact":     "9876543210",
				"method":      "upi",
				"save":        true,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := buildPaymentData(tt.params, tt.currency, tt.customerID)

			if result == nil {
				t.Error("Expected result but got nil")
				return
			}

			// Check that all expected fields are present
			for key, expectedValue := range tt.shouldContain {
				actualValue, exists := (*result)[key]
				if !exists {
					t.Errorf("Expected key '%s' to exist in result", key)
				} else if actualValue != expectedValue {
					t.Errorf(
						"Expected '%s' to be %v, got %v", key, expectedValue, actualValue,
					)
				}
			}

			// Check that empty token is not added
			if tt.params["token"] == "" {
				if _, exists := (*result)["token"]; exists {
					t.Error("Empty token should not be added to payment data")
				}
			}

			// Check that customer_id is not added when customerID is empty
			if tt.customerID == "" {
				if _, exists := (*result)["customer_id"]; exists {
					t.Error("customer_id should not be added when customerID is empty")
				}
			}

		})
	}
}

// Test_createOrGetCustomer_scenarios tests
// createOrGetCustomer function scenarios
func Test_createOrGetCustomer_scenarios(t *testing.T) {
	tests := []struct {
		name           string
		params         map[string]interface{}
		mockSetup      func() (*http.Client, *httptest.Server)
		expectedError  string
		expectedResult map[string]interface{}
	}{
		{
			name: "successful customer creation with contact",
			params: map[string]interface{}{
				"contact": "9876543210",
			},
			mockSetup: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/customers",
						Method: "POST",
						Response: map[string]interface{}{
							"id":      "cust_123456789",
							"contact": "9876543210",
							"email":   "[email protected]",
						},
					},
				)
			},
			expectedResult: map[string]interface{}{
				"id":      "cust_123456789",
				"contact": "9876543210",
				"email":   "[email protected]",
			},
		},
		{
			name: "no contact provided - returns nil",
			params: map[string]interface{}{
				"amount": 10000,
			},
			mockSetup: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient()
			},
			expectedResult: nil,
		},
		{
			name: "empty contact provided - returns nil",
			params: map[string]interface{}{
				"contact": "",
			},
			mockSetup: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient()
			},
			expectedResult: nil,
		},
		{
			name: "customer creation API error",
			params: map[string]interface{}{
				"contact": "9876543210",
			},
			mockSetup: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/customers",
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Invalid contact number",
							},
						},
					},
				)
			},
			expectedError: "failed to create/fetch customer with contact 9876543210",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			client, server := newMockRzpClient(tt.mockSetup)
			if server != nil {
				defer server.Close()
			}

			result, err := createOrGetCustomer(client, tt.params)

			if tt.expectedError != "" {
				if err == nil {
					t.Error("Expected error but got nil")
					return
				}
				if !strings.Contains(err.Error(), tt.expectedError) {
					t.Errorf(
						"Expected error to contain '%s', got '%s'", tt.expectedError, err.Error(),
					)
				}
			} else {
				if err != nil {
					t.Errorf("Unexpected error: %v", err)
					return
				}

				switch {
				case tt.expectedResult == nil && result != nil:
					t.Errorf("Expected nil result but got %v", result)
				case tt.expectedResult != nil && result == nil:
					t.Error("Expected result but got nil")
				case tt.expectedResult != nil && result != nil:
					if result["id"] != tt.expectedResult["id"] {
						t.Errorf(
							"Expected customer ID '%s', got '%s'", tt.expectedResult["id"],
							result["id"],
						)
					}
				}
			}
		})
	}
}

// Test_processVPAParameters_scenarios tests
//
//	processUPIParameters function scenarios
func Test_processUPIParameters_scenarios(t *testing.T) {
	tests := []struct {
		name           string
		inputParams    map[string]interface{}
		expectedParams map[string]interface{}
	}{
		{
			name: "VPA parameter provided - sets UPI parameters",
			inputParams: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"vpa":      "9876543210@paytm",
			},
			expectedParams: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"vpa":      "9876543210@paytm",
				"method":   "upi",
				"upi": map[string]interface{}{
					"flow":        "collect",
					"expiry_time": "6",
					"vpa":         "9876543210@paytm",
				},
			},
		},
		{
			name: "empty VPA parameter - no changes",
			inputParams: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"vpa":      "",
			},
			expectedParams: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
				"vpa":      "",
			},
		},
		{
			name: "no VPA parameter - no changes",
			inputParams: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
			},
			expectedParams: map[string]interface{}{
				"amount":   10000,
				"order_id": "order_123",
			},
		},
		{
			name: "UPI intent parameter provided - sets UPI intent parameters",
			inputParams: map[string]interface{}{
				"amount":     15000,
				"order_id":   "order_456",
				"upi_intent": true,
			},
			expectedParams: map[string]interface{}{
				"amount":     15000,
				"order_id":   "order_456",
				"upi_intent": true,
				"method":     "upi",
				"upi": map[string]interface{}{
					"flow": "intent",
				},
			},
		},
		{
			name: "UPI intent false - no changes",
			inputParams: map[string]interface{}{
				"amount":     10000,
				"order_id":   "order_123",
				"upi_intent": false,
			},
			expectedParams: map[string]interface{}{
				"amount":     10000,
				"order_id":   "order_123",
				"upi_intent": false,
			},
		},
		{
			name: "both VPA and UPI intent provided - UPI intent takes precedence",
			inputParams: map[string]interface{}{
				"amount":     20000,
				"order_id":   "order_789",
				"vpa":        "test@upi",
				"upi_intent": true,
			},
			expectedParams: map[string]interface{}{
				"amount":     20000,
				"order_id":   "order_789",
				"vpa":        "test@upi",
				"upi_intent": true,
				"method":     "upi",
				"upi": map[string]interface{}{
					"flow": "intent",
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			params := make(map[string]interface{})
			for k, v := range tt.inputParams {
				params[k] = v
			}

			processUPIParameters(params)

			for key, expectedValue := range tt.expectedParams {
				actualValue, exists := params[key]
				if !exists {
					t.Errorf("Expected key '%s' to exist in params", key)
					continue
				}

				if key == "upi" {
					expectedUPI := expectedValue.(map[string]interface{})
					actualUPI, ok := actualValue.(map[string]interface{})
					if !ok {
						t.Errorf("Expected UPI to be map[string]interface{}, got %T", actualValue)
						continue
					}
					for upiKey, upiValue := range expectedUPI {
						if actualUPI[upiKey] != upiValue {
							t.Errorf(
								"Expected UPI[%s] to be '%v', got '%v'",
								upiKey, upiValue, actualUPI[upiKey],
							)
						}
					}
				} else if actualValue != expectedValue {
					t.Errorf(
						"Expected '%s' to be '%v', got '%v'", key, expectedValue, actualValue,
					)
				}
			}
		})
	}
}

// Test_addAdditionalPaymentParameters_scenarios
// tests addAdditionalPaymentParameters function scenarios
// Note: method parameter is set internally by VPA processing, not by user input
func Test_addAdditionalPaymentParameters_scenarios(t *testing.T) {
	tests := []struct {
		name           string
		paymentData    map[string]interface{}
		params         map[string]interface{}
		expectedResult map[string]interface{}
	}{
		{
			name: "all additional parameters provided (method set internally)",
			paymentData: map[string]interface{}{
				"amount":   10000,
				"currency": "INR",
			},
			params: map[string]interface{}{
				"method": "upi",
				"save":   true,
				"upi": map[string]interface{}{
					"flow": "collect",
					"vpa":  "test@upi",
				},
			},
			expectedResult: map[string]interface{}{
				"amount":   10000,
				"currency": "INR",
				"method":   "upi",
				"save":     true,
				"upi": map[string]interface{}{
					"flow": "collect",
					"vpa":  "test@upi",
				},
			},
		},
		{
			name: "empty method parameter - not added (internal processing)",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"method": "",
				"save":   false,
			},
			expectedResult: map[string]interface{}{
				"amount": 10000,
				"save":   false,
			},
		},
		{
			name: "nil UPI parameters - not added (method set internally)",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"method": "card",
				"upi":    nil,
			},
			expectedResult: map[string]interface{}{
				"amount": 10000,
				"method": "card",
			},
		},
		{
			name: "invalid UPI parameter type - not added (method set internally)",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"method": "upi",
				"upi":    "invalid_type",
			},
			expectedResult: map[string]interface{}{
				"amount": 10000,
				"method": "upi",
			},
		},
		{
			name: "recurring parameter provided",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"recurring": true,
			},
			expectedResult: map[string]interface{}{
				"amount":    10000,
				"recurring": true,
			},
		},
		{
			name: "recurring parameter false",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"recurring": false,
			},
			expectedResult: map[string]interface{}{
				"amount":    10000,
				"recurring": false,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			paymentData := make(map[string]interface{})
			for k, v := range tt.paymentData {
				paymentData[k] = v
			}

			addAdditionalPaymentParameters(paymentData, tt.params)

			for key, expectedValue := range tt.expectedResult {
				actualValue, exists := paymentData[key]
				if !exists {
					t.Errorf("Expected key '%s' to exist in paymentData", key)
					continue
				}

				if key == "upi" {
					expectedUPI := expectedValue.(map[string]interface{})
					actualUPI, ok := actualValue.(map[string]interface{})
					if !ok {
						t.Errorf("Expected UPI to be map[string]interface{}, got %T", actualValue)
						continue
					}
					for upiKey, upiValue := range expectedUPI {
						if actualUPI[upiKey] != upiValue {
							t.Errorf(
								"Expected UPI[%s] to be '%v', got '%v'", upiKey, upiValue,
								actualUPI[upiKey],
							)
						}
					}
				} else if actualValue != expectedValue {
					t.Errorf(
						"Expected '%s' to be '%v', got '%v'", key, expectedValue, actualValue,
					)
				}
			}

			// Check that no unexpected keys were added
			for key := range paymentData {
				if _, expected := tt.expectedResult[key]; !expected {
					t.Errorf("Unexpected key '%s' found in paymentData", key)
				}
			}
		})
	}
}

// Test_addContactAndEmailToPaymentData_scenarios
// tests addContactAndEmailToPaymentData function scenarios
func Test_addContactAndEmailToPaymentData_scenarios(t *testing.T) {
	tests := []struct {
		name           string
		paymentData    map[string]interface{}
		params         map[string]interface{}
		expectedResult map[string]interface{}
	}{
		{
			name: "both contact and email provided",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"contact": "9876543210",
				"email":   "[email protected]",
			},
			expectedResult: map[string]interface{}{
				"amount":  10000,
				"contact": "9876543210",
				"email":   "[email protected]",
			},
		},
		{
			name: "only contact provided - email generated",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"contact": "9876543210",
			},
			expectedResult: map[string]interface{}{
				"amount":  10000,
				"contact": "9876543210",
				"email":   "[email protected]",
			},
		},
		{
			name: "empty contact and email - nothing added",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"contact": "",
				"email":   "",
			},
			expectedResult: map[string]interface{}{
				"amount": 10000,
			},
		},
		{
			name: "contact provided but email is empty - email generated",
			paymentData: map[string]interface{}{
				"amount": 10000,
			},
			params: map[string]interface{}{
				"contact": "9876543210",
				"email":   "",
			},
			expectedResult: map[string]interface{}{
				"amount":  10000,
				"contact": "9876543210",
				"email":   "[email protected]",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			paymentData := make(map[string]interface{})
			for k, v := range tt.paymentData {
				paymentData[k] = v
			}

			addContactAndEmailToPaymentData(paymentData, tt.params)

			for key, expectedValue := range tt.expectedResult {
				actualValue, exists := paymentData[key]
				if !exists {
					t.Errorf("Expected key '%s' to exist in paymentData", key)
					continue
				}
				if actualValue != expectedValue {
					t.Errorf(
						"Expected '%s' to be '%v', got '%v'", key, expectedValue, actualValue,
					)
				}
			}

			// Check that no unexpected keys were added
			for key := range paymentData {
				if _, expected := tt.expectedResult[key]; !expected {
					t.Errorf("Unexpected key '%s' found in paymentData", key)
				}
			}
		})
	}
}

// Test_processPaymentResult_edgeCases
// tests edge cases for processPaymentResult function
func Test_processPaymentResult_edgeCases(t *testing.T) {
	tests := []struct {
		name          string
		payment       map[string]interface{}
		expectedError string
		shouldProcess bool
	}{
		{
			name: "payment with OTP URL that causes sendOtp to fail",
			payment: map[string]interface{}{
				"razorpay_payment_id": "pay_123456789",
				"next": []interface{}{
					map[string]interface{}{
						"action": "otp_generate",
						"url":    "http://invalid-url", // Invalid URL
					},
				},
			},
			expectedError: "OTP generation failed",
		},
		{
			name: "payment with empty OTP URL",
			payment: map[string]interface{}{
				"razorpay_payment_id": "pay_123456789",
				"next": []interface{}{
					map[string]interface{}{
						"action": "otp_generate",
						"url":    "", // Empty URL should not trigger sendOtp
					},
				},
			},
			shouldProcess: true,
		},
		{
			name: "payment without next actions",
			payment: map[string]interface{}{
				"razorpay_payment_id": "pay_123456789",
			},
			shouldProcess: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, err := processPaymentResult(tt.payment)

			if tt.expectedError != "" {
				if err == nil {
					t.Error("Expected error but got nil")
					return
				}
				if !strings.Contains(err.Error(), tt.expectedError) {
					t.Errorf(
						"Expected error to contain '%s', got '%s'", tt.expectedError, err.Error())
				}
			} else if tt.shouldProcess {
				if err != nil {
					t.Errorf("Unexpected error: %v", err)
				}
				if result == nil {
					t.Error("Expected result but got nil")
				} else {
					// Verify the response structure
					if paymentID, exists := result["razorpay_payment_id"]; !exists ||
						paymentID == "" {
						t.Error("Expected razorpay_payment_id in result")
					}
					if status, exists := result["status"]; !exists ||
						status != "payment_initiated" {
						t.Error("Expected status to be 'payment_initiated'")
					}
				}
			}
		})
	}
}

// Test for sendOtp function - comprehensive coverage
func TestSendOtp(t *testing.T) {
	t.Run("empty OTP URL", func(t *testing.T) {
		err := sendOtp("")
		if err == nil {
			t.Error("Expected error for empty OTP URL")
		}
		if err.Error() != "OTP URL is empty" {
			t.Errorf("Expected 'OTP URL is empty', got '%s'", err.Error())
		}
	})

	t.Run("invalid URL format", func(t *testing.T) {
		err := sendOtp("invalid-url")
		if err == nil {
			t.Error("Expected error for invalid URL")
		}
		// The URL parsing succeeds but fails on HTTPS check
		if !strings.Contains(err.Error(), "OTP URL must use HTTPS") {
			t.Errorf("Expected 'OTP URL must use HTTPS' error, got '%s'", err.Error())
		}
	})

	t.Run("non-HTTPS URL", func(t *testing.T) {
		err := sendOtp("http://api.razorpay.com/v1/payments/otp")
		if err == nil {
			t.Error("Expected error for non-HTTPS URL")
		}
		if err.Error() != "OTP URL must use HTTPS" {
			t.Errorf("Expected 'OTP URL must use HTTPS', got '%s'", err.Error())
		}
	})

	t.Run("non-Razorpay domain", func(t *testing.T) {
		err := sendOtp("https://example.com/otp")
		if err == nil {
			t.Error("Expected error for non-Razorpay domain")
		}
		if err.Error() != "OTP URL must be from Razorpay domain" {
			t.Errorf("Expected 'OTP URL must be from Razorpay domain', got '%s'",
				err.Error())
		}
	})

	t.Run("successful OTP request", func(t *testing.T) {
		// Since we can't actually call external APIs in tests, we'll test the
		// validation logic by testing with a URL that would fail at HTTP call stage
		err := sendOtp(
			"https://api.razorpay.com/v1/payments/invalid-endpoint-for-test")
		if err == nil {
			t.Error("Expected error for invalid endpoint")
		}
		// This should fail at the HTTP request stage, which is expected
		if !strings.Contains(err.Error(), "OTP generation failed") {
			t.Logf("Got expected error: %s", err.Error())
		}
	})

	t.Run("HTTP request creation failure", func(t *testing.T) {
		// Test with invalid characters that would cause http.NewRequest to fail
		// This is difficult to trigger in practice, so we'll test URL validation
		err := sendOtp("https://api.razorpay.com/v1/payments\x00/otp")
		if err == nil {
			t.Error("Expected error for invalid URL characters")
		}
	})
}

// Test for extractPaymentID function
func TestExtractPaymentID(t *testing.T) {
	t.Run("payment ID exists", func(t *testing.T) {
		payment := map[string]interface{}{
			"razorpay_payment_id": "pay_test123",
			"other_field":         "value",
		}
		result := extractPaymentID(payment)
		if result != "pay_test123" {
			t.Errorf("Expected 'pay_test123', got '%s'", result)
		}
	})

	t.Run("payment ID missing", func(t *testing.T) {
		payment := map[string]interface{}{
			"other_field": "value",
		}
		result := extractPaymentID(payment)
		if result != "" {
			t.Errorf("Expected empty string, got '%s'", result)
		}
	})

	t.Run("payment ID is nil", func(t *testing.T) {
		payment := map[string]interface{}{
			"razorpay_payment_id": nil,
		}
		result := extractPaymentID(payment)
		if result != "" {
			t.Errorf("Expected empty string, got '%s'", result)
		}
	})
}

// Test for extractNextActions function
func TestExtractNextActions(t *testing.T) {
	t.Run("next actions exist", func(t *testing.T) {
		payment := map[string]interface{}{
			"next": []interface{}{
				map[string]interface{}{
					"action": "redirect",
					"url":    "https://example.com",
				},
				map[string]interface{}{
					"action": "otp",
					"url":    "https://otp.example.com",
				},
			},
		}
		result := extractNextActions(payment)
		if len(result) != 2 {
			t.Errorf("Expected 2 actions, got %d", len(result))
		}
		if result[0]["action"] != "redirect" {
			t.Errorf("Expected first action to be 'redirect', got '%s'",
				result[0]["action"])
		}
	})

	t.Run("next field missing", func(t *testing.T) {
		payment := map[string]interface{}{
			"other_field": "value",
		}
		result := extractNextActions(payment)
		if len(result) != 0 {
			t.Errorf("Expected empty slice, got %d actions", len(result))
		}
	})

	t.Run("next field is nil", func(t *testing.T) {
		payment := map[string]interface{}{
			"next": nil,
		}
		result := extractNextActions(payment)
		if len(result) != 0 {
			t.Errorf("Expected empty slice, got %d actions", len(result))
		}
	})

	t.Run("next field is not a slice", func(t *testing.T) {
		payment := map[string]interface{}{
			"next": "invalid_type",
		}
		result := extractNextActions(payment)
		if len(result) != 0 {
			t.Errorf("Expected empty slice, got %d actions", len(result))
		}
	})

	t.Run("next field contains non-map items", func(t *testing.T) {
		payment := map[string]interface{}{
			"next": []interface{}{
				"invalid_item",
				map[string]interface{}{
					"action": "valid_action",
				},
			},
		}
		result := extractNextActions(payment)
		if len(result) != 1 {
			t.Errorf("Expected 1 valid action, got %d", len(result))
		}
		if result[0]["action"] != "valid_action" {
			t.Errorf("Expected action to be 'valid_action', got '%s'",
				result[0]["action"])
		}
	})
}

// Test for addNextStepInstructions function
func TestAddNextStepInstructions(t *testing.T) {
	t.Run("add next step instructions with payment ID", func(t *testing.T) {
		result := make(map[string]interface{})
		paymentID := "pay_test123"

		addNextStepInstructions(result, paymentID)

		nextStep, exists := result["next_step"]
		if !exists {
			t.Error("Expected next_step to be added")
		}

		nextStepStr, ok := nextStep.(string)
		if !ok {
			t.Error("Expected next_step to be a string")
		}

		if !strings.Contains(nextStepStr, "resend_otp") {
			t.Error("Expected instructions to contain 'resend_otp'")
		}
		if !strings.Contains(nextStepStr, "submit_otp") {
			t.Error("Expected instructions to contain 'submit_otp'")
		}

		// Check next_tool
		nextTool, exists := result["next_tool"]
		if !exists {
			t.Error("Expected next_tool to be added")
		}
		if nextTool != "resend_otp" {
			t.Errorf("Expected next_tool to be 'resend_otp', got '%s'", nextTool)
		}

		// Check next_tool_params
		params, exists := result["next_tool_params"]
		if !exists {
			t.Error("Expected next_tool_params to be added")
		}
		paramsMap, ok := params.(map[string]interface{})
		if !ok {
			t.Error("Expected next_tool_params to be a map")
		}
		if paramsMap["payment_id"] != paymentID {
			t.Errorf("Expected payment_id to be '%s', got '%s'",
				paymentID, paramsMap["payment_id"])
		}
	})

	t.Run("empty payment ID", func(t *testing.T) {
		result := make(map[string]interface{})

		addNextStepInstructions(result, "")

		// Should not add anything when payment ID is empty
		if len(result) != 0 {
			t.Error("Expected no fields to be added for empty payment ID")
		}
	})
}

// Test for processUPIParameters function
func TestProcessUPIParameters(t *testing.T) {
	t.Run("processUPIParameters", func(t *testing.T) {
		// Test with VPA
		params := map[string]interface{}{
			"vpa": "test@upi",
		}
		processUPIParameters(params)

		if params["method"] != "upi" {
			t.Errorf("Expected method to be 'upi', got '%s'", params["method"])
		}

		upi, exists := params["upi"]
		if !exists {
			t.Error("Expected upi field to be added")
		}

		upiMap, ok := upi.(map[string]interface{})
		if !ok {
			t.Error("Expected upi to be a map")
		}

		if upiMap["vpa"] != "test@upi" {
			t.Errorf("Expected vpa to be 'test@upi', got '%s'", upiMap["vpa"])
		}
		if upiMap["flow"] != "collect" {
			t.Errorf("Expected flow to be 'collect', got '%s'", upiMap["flow"])
		}
	})

	t.Run("processUPIParameters - UPI intent", func(t *testing.T) {
		// Test with UPI intent
		params := map[string]interface{}{
			"upi_intent": true,
		}
		processUPIParameters(params)

		if params["method"] != "upi" {
			t.Errorf("Expected method to be 'upi', got '%s'", params["method"])
		}

		upi, exists := params["upi"]
		if !exists {
			t.Error("Expected upi field to be added")
		}

		upiMap, ok := upi.(map[string]interface{})
		if !ok {
			t.Error("Expected upi to be a map")
		}

		if upiMap["flow"] != "intent" {
			t.Errorf("Expected flow to be 'intent', got '%s'", upiMap["flow"])
		}
	})

	t.Run("processUPIParameters - no UPI params", func(t *testing.T) {
		// Test with no UPI parameters
		params := map[string]interface{}{
			"amount": 1000,
		}
		processUPIParameters(params)

		// Should not modify params when no UPI parameters are present
		if _, exists := params["method"]; exists {
			t.Error("Expected method not to be added when no UPI params")
		}
		if _, exists := params["upi"]; exists {
			t.Error("Expected upi not to be added when no UPI params")
		}
	})

}

// Test for createOrGetCustomer function
func TestCreateOrGetCustomer(t *testing.T) {
	t.Run("createOrGetCustomer - no contact", func(t *testing.T) {
		// Test with no contact parameter
		params := map[string]interface{}{
			"amount": 1000,
		}

		// This should return nil, nil since no contact is provided
		result, err := createOrGetCustomer(nil, params)

		if result != nil {
			t.Error("Expected nil result when no contact provided")
		}
		if err != nil {
			t.Errorf("Expected no error when no contact provided, got %v", err)
		}
	})
}

// Test for buildPaymentData function
func TestBuildPaymentData(t *testing.T) {
	t.Run("buildPaymentData", func(t *testing.T) {
		params := map[string]interface{}{
			"amount":   1000,
			"order_id": "order_test123",
		}
		currency := "INR"
		customerId := "cust_test123"

		result := buildPaymentData(params, currency, customerId)

		if (*result)["amount"] != 1000 {
			t.Errorf("Expected amount to be 1000, got %v", (*result)["amount"])
		}
		if (*result)["currency"] != "INR" {
			t.Errorf("Expected currency to be 'INR', got '%s'", (*result)["currency"])
		}
		if (*result)["customer_id"] != customerId {
			t.Errorf("Expected customer_id to be '%s', got '%s'",
				customerId, (*result)["customer_id"])
		}
	})

	t.Run("buildPaymentData - no customer ID", func(t *testing.T) {
		params := map[string]interface{}{
			"amount":   1000,
			"order_id": "order_test123",
		}
		currency := "INR"
		customerId := ""

		result := buildPaymentData(params, currency, customerId)

		if (*result)["amount"] != 1000 {
			t.Errorf("Expected amount to be 1000, got %v", (*result)["amount"])
		}
		if (*result)["currency"] != "INR" {
			t.Errorf("Expected currency to be 'INR', got '%s'", (*result)["currency"])
		}
		// Should not have customer_id when empty
		if _, exists := (*result)["customer_id"]; exists {
			t.Error("Expected no customer_id when empty string provided")
		}
	})

}

// Test for processPaymentResult function
func TestProcessPaymentResult(t *testing.T) {
	t.Run("processPaymentResult", func(t *testing.T) {
		paymentResult := map[string]interface{}{
			"razorpay_payment_id": "pay_test123",
			"status":              "created",
			"next": []interface{}{
				map[string]interface{}{
					"action": "redirect",
					"url":    "https://example.com",
				},
			},
		}

		result, err := processPaymentResult(paymentResult)

		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}

		if result["razorpay_payment_id"] != "pay_test123" {
			t.Errorf("Expected payment ID, got %v", result["razorpay_payment_id"])
		}

		if result["status"] != "payment_initiated" {
			t.Errorf("Expected status to be 'payment_initiated', got '%s'",
				result["status"])
		}
	})

	t.Run("processPaymentResult - with error", func(t *testing.T) {
		// Test with payment result that might cause an error
		paymentResult := map[string]interface{}{
			"error": map[string]interface{}{
				"code":        "BAD_REQUEST_ERROR",
				"description": "Invalid payment data",
			},
		}

		result, err := processPaymentResult(paymentResult)

		// The function should handle this gracefully
		if err != nil && result == nil {
			t.Logf("Expected behavior - got error: %v", err)
		} else if result != nil {
			// If no error, result should be properly processed
			if result["status"] != "payment_initiated" {
				t.Errorf("Expected status to be 'payment_initiated', got '%s'",
					result["status"])
			}
		}
	})

}

// Test for extractOtpSubmitURL function
func TestExtractOtpSubmitURL(t *testing.T) {
	t.Run("extractOtpSubmitURL", func(t *testing.T) {
		// Test with valid response data containing OTP submit URL
		responseData := map[string]interface{}{
			"next": []interface{}{
				map[string]interface{}{
					"action": "redirect",
					"url":    "https://example.com/redirect",
				},
				map[string]interface{}{
					"action": "otp_submit",
					"url":    "https://example.com/otp/submit",
				},
			},
		}

		result := extractOtpSubmitURL(responseData)
		if result != "https://example.com/otp/submit" {
			t.Errorf("Expected OTP submit URL, got '%s'", result)
		}
	})

	t.Run("extractOtpSubmitURL - no OTP action", func(t *testing.T) {
		responseData := map[string]interface{}{
			"next": []interface{}{
				map[string]interface{}{
					"action": "redirect",
					"url":    "https://example.com/redirect",
				},
			},
		}

		result := extractOtpSubmitURL(responseData)
		if result != "" {
			t.Errorf("Expected empty string, got '%s'", result)
		}
	})

	t.Run("extractOtpSubmitURL - invalid input", func(t *testing.T) {
		// Test with invalid input type
		result := extractOtpSubmitURL("invalid_input")
		if result != "" {
			t.Errorf("Expected empty string for invalid input, got '%s'", result)
		}
	})

	t.Run("extractOtpSubmitURL - no next field", func(t *testing.T) {
		responseData := map[string]interface{}{
			"other_field": "value",
		}

		result := extractOtpSubmitURL(responseData)
		if result != "" {
			t.Errorf("Expected empty string when no next field, got '%s'", result)
		}
	})
}

// TestPayments100PercentCoverage_FetchPayment tests FetchPayment coverage
func TestPayments100PercentCoverage_FetchPayment(t *testing.T) {
	// Test FetchPayment with SDK errors
	t.Run("FetchPayment - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123",
						Method: "GET",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Invalid payment ID",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "fetching payment failed",
		}
		runToolTest(t, testCase, FetchPayment, "Payment")
	})

}

// TestPayments100PercentCoverage_FetchPaymentCardDetails tests
// FetchPaymentCardDetails coverage
func TestPayments100PercentCoverage_FetchPaymentCardDetails(t *testing.T) {
	// Test FetchPaymentCardDetails with SDK errors
	t.Run("FetchPaymentCardDetails - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123/card",
						Method: "GET",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Card details not available",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "fetching card details failed",
		}
		runToolTest(t, testCase, FetchPaymentCardDetails, "PaymentCardDetails")
	})

}

// TestPayments100PercentCoverage_UpdatePayment tests UpdatePayment coverage
func TestPayments100PercentCoverage_UpdatePayment(t *testing.T) {
	// Test UpdatePayment with SDK errors
	t.Run("UpdatePayment - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
				"notes": map[string]interface{}{
					"key": "value",
				},
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123",
						Method: "PATCH",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Invalid notes",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "updating payment failed",
		}
		runToolTest(t, testCase, UpdatePayment, "Payment")
	})

}

// TestPayments100PercentCoverage_CapturePayment tests CapturePayment coverage
func TestPayments100PercentCoverage_CapturePayment(t *testing.T) {
	// Test CapturePayment with SDK errors
	t.Run("CapturePayment - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
				"amount":     1000,
				"currency":   "INR",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123/capture",
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Payment cannot be captured",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "capturing payment failed",
		}
		runToolTest(t, testCase, CapturePayment, "Payment")
	})

}

// TestPayments100PercentCoverage_FetchAllPayments tests
// FetchAllPayments coverage
func TestPayments100PercentCoverage_FetchAllPayments(t *testing.T) {
	// Test FetchAllPayments with SDK errors
	t.Run("FetchAllPayments - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"count": 10,
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments",
						Method: "GET",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Invalid request",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "fetching payments failed",
		}
		runToolTest(t, testCase, FetchAllPayments, "Collection")
	})

}

// TestPayments100PercentCoverage_ResendOtp tests ResendOtp coverage
func TestPayments100PercentCoverage_ResendOtp(t *testing.T) {
	// Test ResendOtp with SDK errors
	t.Run("ResendOtp - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123/otp/resend",
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Cannot resend OTP",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP resend failed",
		}
		runToolTest(t, testCase, ResendOtp, "ResendOtp")
	})

}

// TestPayments100PercentCoverage_SubmitOtp tests SubmitOtp coverage
func TestPayments100PercentCoverage_SubmitOtp(t *testing.T) {
	// Test SubmitOtp with SDK errors
	t.Run("SubmitOtp - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
				"otp_string": "123456",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123/otp/submit",
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Invalid OTP",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "OTP verification failed",
		}
		runToolTest(t, testCase, SubmitOtp, "SubmitOtp")
	})

}

// TestPayments100PercentCoverage_InitiatePayment tests InitiatePayment coverage
func TestPayments100PercentCoverage_InitiatePayment(t *testing.T) {

	// Test InitiatePayment with errors
	t.Run("InitiatePayment - SDK error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "SDK error",
			Request: map[string]interface{}{
				"amount":   1000,
				"currency": "INR",
				"order_id": "order_test123",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/create/json",
						Method: "POST",
						Response: map[string]interface{}{
							"error": map[string]interface{}{
								"code":        "BAD_REQUEST_ERROR",
								"description": "Invalid payment data",
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "initiating payment failed",
		}
		runToolTest(t, testCase, InitiatePayment, "InitiatePayment")
	})

	// Test sendOtp with HTTP error status
	t.Run("sendOtp - HTTP error status", func(t *testing.T) {
		server := httptest.NewTLSServer(
			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusBadRequest)
			}))
		defer server.Close()

		// Replace domain to pass validation
		testURL := strings.Replace(
			server.URL, server.URL[8:], "api.razorpay.com/v1/payments/otp", 1)
		err := sendOtp(testURL)
		if err == nil {
			t.Error("Expected error for HTTP error status")
		}
		if !strings.Contains(err.Error(), "OTP generation failed with HTTP status") {
			t.Logf("Got expected error: %s", err.Error())
		}
	})

	// More aggressive tests - hitting every error path!
	t.Run("sendOtp - request creation error", func(t *testing.T) {
		// Test with malformed URL that passes parsing but fails request creation
		err := sendOtp("https://api.razorpay.com:99999/invalid")
		if err == nil {
			t.Error("Expected error for malformed URL")
		}
		if !strings.Contains(err.Error(), "failed to create OTP request") &&
			!strings.Contains(err.Error(), "OTP generation failed") {
			t.Logf("Got expected error: %s", err.Error())
		}
	})

	// Test with extremely long URL to trigger different error paths
	t.Run("sendOtp - extreme URL", func(t *testing.T) {
		longPath := strings.Repeat("a", 10000)
		testURL := "https://api.razorpay.com/v1/payments/" + longPath + "/otp"
		err := sendOtp(testURL)
		if err == nil {
			t.Error("Expected error for extreme URL")
		}
	})

}

// contextKey is a type for context keys to avoid collisions
type contextKey string

// TestPayments100PercentCoverage_ContextErrors tests context error paths
func TestPayments100PercentCoverage_ContextErrors(t *testing.T) {
	// Test getClientFromContextOrDefault error path
	t.Run("SubmitOtp - client context error", func(t *testing.T) {
		// Create context with invalid client
		ctx := context.WithValue(
			context.Background(), contextKey("invalid_key"), "invalid_value")

		tool := SubmitOtp(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"payment_id": "pay_test123",
				"otp_string": "123456",
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for invalid client context")
		}
	})

	// Test sendOtp with actual HTTP client failure
	t.Run("sendOtp - HTTP client failure", func(t *testing.T) {
		// Test with a URL that will fail at the HTTP client level
		err := sendOtp("https://api.razorpay.com:99999/invalid/path/that/will/fail")
		if err == nil {
			t.Error("Expected error for HTTP client failure")
		}
		if !strings.Contains(err.Error(), "OTP generation failed") {
			t.Logf("Got expected error: %s", err.Error())
		}
	})

}

// TestPayments100PercentCoverage_ContextErrors2 tests more context error paths
func TestPayments100PercentCoverage_ContextErrors2(t *testing.T) {
	// Test InitiatePayment - getClientFromContextOrDefault error
	t.Run("InitiatePayment - client context error", func(t *testing.T) {
		// Create context without client
		ctx := context.Background()

		tool := InitiatePayment(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"amount":   1000,
				"order_id": "order_test123",
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for missing client context")
		}
		if !strings.Contains(result.Text, "no client found in context") {
			t.Errorf("Expected 'no client found in context', got '%s'", result.Text)
		}
	})

	// Simple working test
	t.Run("InitiatePayment - basic test", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "basic test",
			Request: map[string]interface{}{
				"amount":   1000,
				"order_id": "order_test123",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/create/json",
						Method: "POST",
						Response: map[string]interface{}{
							"id":         "pay_test123",
							"entity":     "payment",
							"amount":     1000,
							"currency":   "INR",
							"status":     "created",
							"invalid":    make(chan int), // This causes JSON marshal to fail
							"created_at": 1234567890,
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "failed",
		}
		runToolTest(t, testCase, InitiatePayment, "Payment")
	})

}

// TestPayments100PercentCoverage_ContextErrors3 tests remaining
// context error paths
func TestPayments100PercentCoverage_ContextErrors3(t *testing.T) {
	// Test FetchPayment - getClientFromContextOrDefault error
	t.Run("FetchPayment - client context error", func(t *testing.T) {
		// Create context without client
		ctx := context.Background()

		tool := FetchPayment(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"payment_id": "pay_test123",
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for missing client context")
		}
		if !strings.Contains(result.Text, "no client found in context") {
			t.Errorf("Expected 'no client found in context', got '%s'", result.Text)
		}
	})

	// Test FetchPaymentCardDetails - getClientFromContextOrDefault error
	t.Run("FetchPaymentCardDetails - client context error", func(t *testing.T) {
		// Create context without client
		ctx := context.Background()

		tool := FetchPaymentCardDetails(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"payment_id": "pay_test123",
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for missing client context")
		}
		if !strings.Contains(result.Text, "no client found in context") {
			t.Errorf("Expected 'no client found in context', got '%s'", result.Text)
		}
	})

	// Test FetchPaymentCardDetails - JSON marshal error
	// (using channel in response)
	t.Run("FetchPaymentCardDetails - JSON marshal error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "JSON marshal error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123/card",
						Method: "GET",
						Response: map[string]interface{}{
							"id":         "card_test123",
							"entity":     "card",
							"name":       "Test User",
							"last4":      "1234",
							"network":    "Visa",
							"type":       "credit",
							"invalid":    make(chan int), // This causes JSON marshal to fail
							"created_at": 1234567890,
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "failed",
		}
		runToolTest(t, testCase, FetchPaymentCardDetails, "Card Details")
	})

}

// TestPayments100PercentCoverage_ContextErrors4 tests final context error paths
func TestPayments100PercentCoverage_ContextErrors4(t *testing.T) {
	// Test CapturePayment - getClientFromContextOrDefault error
	t.Run("CapturePayment - client context error", func(t *testing.T) {
		// Create context without client
		ctx := context.Background()

		tool := CapturePayment(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"payment_id": "pay_test123",
				"amount":     1000,
				"currency":   "INR",
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for missing client context")
		}
		if !strings.Contains(result.Text, "no client found in context") {
			t.Errorf("Expected 'no client found in context', got '%s'", result.Text)
		}
	})

	// Test CapturePayment - JSON marshal error (using channel in response)
	t.Run("CapturePayment - JSON marshal error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "JSON marshal error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
				"amount":     1000,
				"currency":   "INR",
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123/capture",
						Method: "POST",
						Response: map[string]interface{}{
							"id":         "pay_test123",
							"entity":     "payment",
							"amount":     1000,
							"currency":   "INR",
							"status":     "captured",
							"invalid":    make(chan int), // This causes JSON marshal to fail
							"created_at": 1234567890,
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "failed",
		}
		runToolTest(t, testCase, CapturePayment, "Payment")
	})

	// Test UpdatePayment - getClientFromContextOrDefault error
	t.Run("UpdatePayment - client context error", func(t *testing.T) {
		// Create context without client
		ctx := context.Background()

		tool := UpdatePayment(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"payment_id": "pay_test123",
				"notes": map[string]interface{}{
					"key": "value",
				},
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for missing client context")
		}
		if !strings.Contains(result.Text, "no client found in context") {
			t.Errorf("Expected 'no client found in context', got '%s'", result.Text)
		}
	})

	// Test UpdatePayment - JSON marshal error (using channel in response)
	t.Run("UpdatePayment - JSON marshal error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "JSON marshal error",
			Request: map[string]interface{}{
				"payment_id": "pay_test123",
				"notes": map[string]interface{}{
					"key": "value",
				},
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments/pay_test123",
						Method: "PATCH",
						Response: map[string]interface{}{
							"id":       "pay_test123",
							"entity":   "payment",
							"amount":   1000,
							"currency": "INR",
							"status":   "authorized",
							"invalid":  make(chan int), // This causes JSON marshal to fail
							"notes": map[string]interface{}{
								"key": "value",
							},
							"created_at": 1234567890,
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "failed",
		}
		runToolTest(t, testCase, UpdatePayment, "Payment")
	})

	// Test FetchAllPayments - getClientFromContextOrDefault error
	t.Run("FetchAllPayments - client context error", func(t *testing.T) {
		// Create context without client
		ctx := context.Background()

		tool := FetchAllPayments(nil, nil)
		request := mcpgo.CallToolRequest{
			Arguments: map[string]interface{}{
				"count": 10,
			},
		}

		result, err := tool.GetHandler()(ctx, request)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result == nil || !result.IsError {
			t.Error("Expected error result for missing client context")
		}
		if !strings.Contains(result.Text, "no client found in context") {
			t.Errorf("Expected 'no client found in context', got '%s'", result.Text)
		}
	})

	// Test FetchAllPayments - JSON marshal error (using channel in response)
	t.Run("FetchAllPayments - JSON marshal error", func(t *testing.T) {
		testCase := RazorpayToolTestCase{
			Name: "JSON marshal error",
			Request: map[string]interface{}{
				"count": 10,
			},
			MockHttpClient: func() (*http.Client, *httptest.Server) {
				return mock.NewHTTPClient(
					mock.Endpoint{
						Path:   "/v1/payments",
						Method: "GET",
						Response: map[string]interface{}{
							"entity": "collection",
							"count":  1,
							"items": []interface{}{
								map[string]interface{}{
									"id":         "pay_test123",
									"invalid":    make(chan int), // This causes JSON marshal to fail
									"entity":     "payment",
									"amount":     1000,
									"currency":   "INR",
									"status":     "created",
									"created_at": 1234567890,
								},
							},
						},
					},
				)
			},
			ExpectError:    true,
			ExpectedErrMsg: "failed",
		}
		runToolTest(t, testCase, FetchAllPayments, "Collection")
	})
}

```
Page 4/4FirstPrevNextLast