package api import ( "context" "io" "log/slog" "net/http/httptest" "strings" "testing" "git.amiirkhl.ir/starcoach-hackathon/zarinpal-analytics-backend/internal/identity" "git.amiirkhl.ir/starcoach-hackathon/zarinpal-analytics-backend/internal/insight" ) type fakeInsightService struct { refreshSection func(int64, string, insight.Module, insight.Section, string) (insight.Job, bool, error) } func (fakeInsightService) Latest(context.Context, int64, string, insight.Module) (insight.Snapshot, error) { return insight.Snapshot{}, insight.ErrNotFound } func (fakeInsightService) Refresh(context.Context, int64, string, insight.Module, string) (insight.Job, bool, error) { return insight.Job{}, false, nil } func (fakeInsightService) Enqueue(context.Context, int64, string, insight.Module, string) (insight.Job, bool, error) { return insight.Job{}, false, nil } func (f fakeInsightService) RefreshSection(_ context.Context, merchantID int64, terminalID string, module insight.Module, section insight.Section, key string) (insight.Job, bool, error) { return f.refreshSection(merchantID, terminalID, module, section, key) } func (fakeInsightService) GetJob(context.Context, int64, string) (insight.Job, error) { return insight.Job{}, insight.ErrNotFound } func (fakeInsightService) EventsAfter(context.Context, int64, string, int64) ([]insight.Event, error) { return nil, nil } func (fakeInsightService) LatestForPeriod(context.Context, int64, string, insight.Module, insight.PeriodScope) (insight.Snapshot, error) { return insight.Snapshot{}, insight.ErrNotFound } func (fakeInsightService) RefreshForPeriod(context.Context, int64, string, insight.Module, insight.PeriodScope, string) (insight.Job, bool, error) { return insight.Job{}, false, nil } func (fakeInsightService) RefreshSectionForPeriod(context.Context, int64, string, insight.Module, insight.Section, insight.PeriodScope, string) (insight.Job, bool, error) { return insight.Job{}, false, nil } func TestRefreshAIInsightSectionTargetsOnlyRequestedSection(t *testing.T) { service := fakeInsightService{refreshSection: func(merchantID int64, terminalID string, module insight.Module, section insight.Section, key string) (insight.Job, bool, error) { if merchantID != 7 || terminalID != "T83" || module != insight.ModulePayments || section != insight.SectionFuture7Days || key != "section-refresh-123" { t.Fatalf("unexpected request: %d %s %s %s %s", merchantID, terminalID, module, section, key) } return insight.Job{JobID: "insightjob_0123456789abcdef01234567", SnapshotID: "snapshot", Module: module, Section: section, State: "QUEUED"}, false, nil }} server := &Server{logger: slog.New(slog.NewTextHandler(io.Discard, nil)), insights: service} request := httptest.NewRequest("POST", "/", strings.NewReader(`{"terminalId":"T83"}`)) request.SetPathValue("module", "payments") request.SetPathValue("sectionId", "future-7-days") request.Header.Set("Idempotency-Key", "section-refresh-123") request = request.WithContext(context.WithValue(request.Context(), sessionKey{}, identity.Session{MerchantID: 7, UserID: 3})) response := httptest.NewRecorder() server.refreshAIInsightSection(response, request) if response.Code != 202 || !strings.Contains(response.Body.String(), `"sectionId":"future-7-days"`) { t.Fatalf("status=%d body=%s", response.Code, response.Body.String()) } } func TestRefreshAIInsightSectionRejectsUnsupportedNinetyDaySection(t *testing.T) { server := &Server{logger: slog.New(slog.NewTextHandler(io.Discard, nil)), insights: fakeInsightService{}} request := httptest.NewRequest("POST", "/", strings.NewReader(`{}`)) request.SetPathValue("module", "payments") request.SetPathValue("sectionId", "future-90-days") request.Header.Set("Idempotency-Key", "section-refresh-123") response := httptest.NewRecorder() server.refreshAIInsightSection(response, request) if response.Code != 422 { t.Fatalf("status=%d body=%s", response.Code, response.Body.String()) } }