package usecase

import (
	"context"
	"testing"
	"time"

	"haixun-backend/internal/model/publish_guard/domain/entity"
	domusecase "haixun-backend/internal/model/publish_guard/domain/usecase"
)

type guardRepoStub struct {
	policy *entity.Policy
}

func (r *guardRepoStub) EnsureIndexes(ctx context.Context) error { return nil }
func (r *guardRepoStub) Get(ctx context.Context, tenantID, ownerUID, accountID string) (*entity.Policy, error) {
	if r.policy == nil {
		r.policy = defaultPolicy(tenantID, ownerUID, accountID)
	}
	return r.policy, nil
}
func (r *guardRepoStub) Upsert(ctx context.Context, policy *entity.Policy) (*entity.Policy, error) {
	r.policy = policy
	return policy, nil
}
func (r *guardRepoStub) DeleteByAccount(ctx context.Context, tenantID, ownerUID, accountID string) error {
	r.policy = nil
	return nil
}

func TestGuardCheckBlocksPausedPolicy(t *testing.T) {
	repo := &guardRepoStub{policy: defaultPolicy("t", "u", "a")}
	repo.policy.Paused = true
	repo.policy.PausedReason = "token error"
	uc := NewUseCase(repo, nil)

	result, err := uc.Check(context.Background(), checkReq())
	if err != nil {
		t.Fatal(err)
	}
	if result.Allowed || result.Reason != "token error" {
		t.Fatalf("expected paused block, got %#v", result)
	}
}

func TestGuardCheckDelaysWhenDailyLimitReached(t *testing.T) {
	repo := &guardRepoStub{policy: defaultPolicy("t", "u", "a")}
	repo.policy.MaxDailyPosts = 1
	uc := NewUseCase(repo, nil)

	result, err := uc.Check(context.Background(), checkReqWith(func(req *CheckRequestBuilder) {
		req.publishedToday = 1
	}))
	if err != nil {
		t.Fatal(err)
	}
	if result.Allowed || result.DelayUntil == 0 {
		t.Fatalf("expected delayed daily limit, got %#v", result)
	}
}

func TestGuardCheckDelaysWhenIntervalNotReached(t *testing.T) {
	repo := &guardRepoStub{policy: defaultPolicy("t", "u", "a")}
	repo.policy.MinIntervalMinutes = 90
	uc := NewUseCase(repo, nil)

	now := time.Date(2026, 6, 30, 8, 0, 0, 0, time.UTC).UnixNano()
	result, err := uc.Check(context.Background(), checkReqWith(func(req *CheckRequestBuilder) {
		req.now = now
		req.lastPublishedAt = now - int64(30*time.Minute)
	}))
	if err != nil {
		t.Fatal(err)
	}
	if result.Allowed || result.DelayUntil <= now {
		t.Fatalf("expected interval delay, got %#v", result)
	}
}

type CheckRequestBuilder struct {
	now             int64
	publishedToday  int64
	lastPublishedAt int64
}

func checkReq() domusecase.CheckRequest {
	return checkReqWith(nil)
}

func checkReqWith(update func(*CheckRequestBuilder)) domusecase.CheckRequest {
	builder := &CheckRequestBuilder{now: time.Date(2026, 6, 30, 8, 0, 0, 0, time.UTC).UnixNano()}
	if update != nil {
		update(builder)
	}
	return domusecase.CheckRequest{
		TenantID: "t", OwnerUID: "u", AccountID: "a",
		Now: builder.now, PublishedToday: builder.publishedToday, LastPublishedAt: builder.lastPublishedAt,
	}
}
