//go:build integration

package inttest

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

	"github.com/google/uuid"

	"scrabble/backend/internal/payments"
)

// benefitFor returns the account's benefit on the given origin from its statement.
func benefitFor(t *testing.T, pay *payments.Service, id uuid.UUID, origin payments.Source) payments.OriginBenefit {
	t.Helper()
	stmt, err := pay.AccountStatement(context.Background(), id)
	if err != nil {
		t.Fatalf("statement: %v", err)
	}
	for _, b := range stmt.Benefits {
		if b.Origin == origin {
			return b
		}
	}
	return payments.OriginBenefit{}
}

// TestConsoleAdminGrant drives the admin grant: a raw benefit grant, a by-product grant of a reward
// bundle, and a refusal to grant a chips pack; the create is CSRF-guarded.
func TestConsoleAdminGrant(t *testing.T) {
	ctx := context.Background()
	srv, _, pay := bannerServer(t)
	h := srv.Handler()
	id := provisionAccount(t)
	const origin = "http://admin.test"
	base := "http://admin.test/_gm/users/" + id.String()

	// CSRF: a grant without the origin header is refused.
	if code, _ := consoleDo(h, http.MethodPost, base+"/grant", "origin=direct&hints=1", ""); code != http.StatusForbidden {
		t.Fatalf("grant without origin = %d, want 403", code)
	}

	// Raw grant: 5 hints + 30 no-ads days to the direct origin.
	if code, body := consoleDo(h, http.MethodPost, base+"/grant", "origin=direct&hints=5&noads=30", origin); code != http.StatusOK || !strings.Contains(body, "Granted") {
		t.Fatalf("raw grant = %d, has 'Granted' = %v", code, strings.Contains(body, "Granted"))
	}
	if b := benefitFor(t, pay, id, payments.SourceDirect); b.Hints != 5 || b.AdsPaidUntil.IsZero() {
		t.Fatalf("after raw grant: hints=%d adsUntil-zero=%v, want 5 hints + a no-ads term", b.Hints, b.AdsPaidUntil.IsZero())
	}

	// By-product grant: an archived reward bundle (3 hints) to vk.
	reward, err := pay.CreateProduct(ctx, payments.ProductInput{
		Title: "reward-3-hints", Atoms: []payments.AtomLine{{Atom: "hints", Quantity: 3}},
	}, false)
	if err != nil {
		t.Fatalf("create reward: %v", err)
	}
	if code, body := consoleDo(h, http.MethodPost, base+"/grant-product", "origin=vk&product_id="+reward.String(), origin); code != http.StatusOK || !strings.Contains(body, "Granted") {
		t.Fatalf("product grant = %d, has 'Granted' = %v", code, strings.Contains(body, "Granted"))
	}
	if b := benefitFor(t, pay, id, payments.SourceVK); b.Hints != 3 {
		t.Fatalf("after product grant: vk hints=%d, want 3", b.Hints)
	}

	// A chips pack cannot be granted.
	pack, err := pay.CreateProduct(ctx, payments.ProductInput{
		Title: "grant-pack", Atoms: []payments.AtomLine{{Atom: "chips", Quantity: 100}},
		Prices: []payments.PriceLine{{Method: "direct", Currency: payments.CurrencyRUB, Amount: 14900}},
	}, true)
	if err != nil {
		t.Fatalf("create pack: %v", err)
	}
	if code, body := consoleDo(h, http.MethodPost, base+"/grant-product", "origin=direct&product_id="+pack.String(), origin); code != http.StatusOK || !strings.Contains(body, "cannot grant chips") {
		t.Fatalf("chips grant = %d, has 'cannot grant chips' = %v", code, strings.Contains(body, "cannot grant chips"))
	}
}
