package server

import (
	"context"
	"errors"
	"net/http"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/api/admin"
	"github.com/tidbcloud/AgentTeam/internal/api/billing"
)

type fakeAdminBillingClient struct {
	params billing.HostedCreditGrantParams
	grant  billing.HostedCreditGrant
	err    error
}

func (fake *fakeAdminBillingClient) GrantHostedCredit(_ context.Context, params billing.HostedCreditGrantParams) (billing.HostedCreditGrant, error) {
	fake.params = params
	if fake.err != nil {
		return billing.HostedCreditGrant{}, fake.err
	}
	return fake.grant, nil
}

func TestAdminHostedCreditGrantClientConvertsParamsAndResponse(t *testing.T) {
	t.Parallel()

	expiresAt := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)
	createdAt := time.Date(2026, 6, 10, 8, 0, 0, 0, time.UTC)
	next := &fakeAdminBillingClient{
		grant: billing.HostedCreditGrant{
			GrantID:           "hcg_1",
			OperationID:       "hgo_1",
			Created:           true,
			OrganizationID:    "org_1",
			CreditUnit:        "agentteam_credit",
			CreditAmount:      3000,
			CreditAmountAtoms: 3_000_000_000,
			GrantSourceType:   "operator_gift",
			GrantReasonRef:    "support-ticket-1",
			Refundable:        false,
			ExpiresAt:         &expiresAt,
			OperatorIdentity:  "usr_admin",
			SourceRef:         "ticket-1",
			CreatedAt:         createdAt,
			UpdatedAt:         createdAt,
		},
	}

	grant, err := adminHostedCreditGrantClient{next: next}.GrantHostedCredit(context.Background(), admin.HostedCreditGrantParams{
		OrganizationID:   "org_1",
		IdempotencyKey:   "grant-idem",
		CreditUnit:       "agentteam_credit",
		CreditAmount:     3000,
		GrantSourceType:  "operator_gift",
		GrantReasonRef:   "support-ticket-1",
		ExpiresAt:        &expiresAt,
		OperatorIdentity: "usr_admin",
		SourceRef:        "ticket-1",
	})

	require.NoError(t, err)
	require.Equal(t, "org_1", next.params.OrganizationID)
	require.Equal(t, "grant-idem", next.params.IdempotencyKey)
	require.Equal(t, int64(3000), next.params.CreditAmount)
	require.Equal(t, "usr_admin", next.params.OperatorIdentity)
	require.Equal(t, "hcg_1", grant.GrantID)
	require.Equal(t, int64(3_000_000_000), grant.CreditAmountAtoms)
	require.Equal(t, createdAt, grant.CreatedAt)
}

func TestAdminHostedCreditGrantClientWrapsMaaSStatusErrors(t *testing.T) {
	t.Parallel()

	next := &fakeAdminBillingClient{err: billing.MaaSClientError{StatusCode: http.StatusConflict, Body: "conflict"}}
	_, err := adminHostedCreditGrantClient{next: next}.GrantHostedCredit(context.Background(), admin.HostedCreditGrantParams{})

	var serviceErr admin.HostedCreditGrantServiceError
	require.True(t, errors.As(err, &serviceErr))
	require.Equal(t, http.StatusConflict, serviceErr.StatusCode)
}
