package luckygift

import (
	"context"
	"testing"
	"time"

	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	domain "hyapp/services/lucky-gift-service/internal/domain/luckygift"
)

type poolAdjustmentRepositoryStub struct {
	Repository
	command domain.PoolAdjustmentCommand
	nowMS   int64
	result  domain.PoolAdjustmentResult
	err     error
	calls   int
}

func (s *poolAdjustmentRepositoryStub) AdjustLuckyGiftPoolBalance(_ context.Context, command domain.PoolAdjustmentCommand, nowMS int64) (domain.PoolAdjustmentResult, error) {
	s.calls++
	s.command = command
	s.nowMS = nowMS
	return s.result, s.err
}

func TestAdjustPoolBalanceNormalizesAndForwardsOwnerCommand(t *testing.T) {
	stub := &poolAdjustmentRepositoryStub{result: domain.PoolAdjustmentResult{Pool: domain.PoolBalance{Balance: 50}}}
	service := New(stub)
	fixedNow := time.Date(2026, 7, 15, 1, 2, 3, 0, time.UTC)
	service.SetClock(func() time.Time { return fixedNow })
	ctx := appcode.WithContext(context.Background(), " AsLaN ")
	result, err := service.AdjustPoolBalance(ctx, domain.PoolAdjustmentCommand{
		PoolID: " lucky ", StrategyVersion: " DYNAMIC_V3 ", AdjustmentID: " adjustment-1 ",
		Direction: " IN ", AmountCoins: 50, Reason: " approved budget ", OperatorAdminID: 9,
		RequestID: " request-1 ",
	})
	if err != nil {
		t.Fatalf("adjust pool balance: %v", err)
	}
	if result.Pool.Balance != 50 || stub.calls != 1 {
		t.Fatalf("result=%+v calls=%d", result, stub.calls)
	}
	if stub.command.AppCode != "aslan" || stub.command.PoolID != "lucky" || stub.command.StrategyVersion != domain.StrategyDynamicV3 ||
		stub.command.Direction != domain.PoolAdjustmentIn || stub.command.Reason != "approved budget" || stub.nowMS != fixedNow.UnixMilli() {
		t.Fatalf("normalized command=%+v now=%d", stub.command, stub.nowMS)
	}
}

func TestAdjustPoolBalanceRejectsInvalidMoneyCommandBeforeRepository(t *testing.T) {
	stub := &poolAdjustmentRepositoryStub{}
	service := New(stub)
	tests := []domain.PoolAdjustmentCommand{
		{StrategyVersion: domain.StrategyDynamicV3, AdjustmentID: "a", Direction: "in", AmountCoins: 1, Reason: "r", OperatorAdminID: 1},
		{PoolID: "lucky", StrategyVersion: "v4", AdjustmentID: "a", Direction: "in", AmountCoins: 1, Reason: "r", OperatorAdminID: 1},
		{PoolID: "lucky", StrategyVersion: domain.StrategyDynamicV3, Direction: "in", AmountCoins: 1, Reason: "r", OperatorAdminID: 1},
		{PoolID: "lucky", StrategyVersion: domain.StrategyDynamicV3, AdjustmentID: "a", Direction: "sideways", AmountCoins: 1, Reason: "r", OperatorAdminID: 1},
		{PoolID: "lucky", StrategyVersion: domain.StrategyDynamicV3, AdjustmentID: "a", Direction: "out", AmountCoins: 0, Reason: "r", OperatorAdminID: 1},
		{PoolID: "lucky", StrategyVersion: domain.StrategyDynamicV3, AdjustmentID: "a", Direction: "out", AmountCoins: 1, OperatorAdminID: 1},
	}
	for index, command := range tests {
		if _, err := service.AdjustPoolBalance(context.Background(), command); !xerr.IsCode(err, xerr.InvalidArgument) {
			t.Fatalf("case %d error=%v, want invalid argument", index, err)
		}
	}
	if stub.calls != 0 {
		t.Fatalf("repository calls=%d, want 0 for invalid commands", stub.calls)
	}
}
