package store

import (
	"context"
	"testing"
	"time"
)

func TestHostRepoStatsHistory_PartialUpsertPreservesPriorValues(t *testing.T) {
	t.Parallel()
	s := openTestStore(t)
	ctx := context.Background()

	const hostID = "h-history-1"
	seedHost(t, s, hostID)

	day := "2026-05-07"
	now := time.Now().UTC()

	// 1. First write of the day: total_size only.
	if err := s.UpsertHostRepoStatsHistory(ctx, hostID, day,
		HostRepoStats{TotalSizeBytes: int64ptr(100)}, now); err != nil {
		t.Fatalf("upsert 1: %v", err)
	}

	// 2. Second write: snapshot_count only — total_size MUST survive.
	if err := s.UpsertHostRepoStatsHistory(ctx, hostID, day,
		HostRepoStats{SnapshotCount: int64ptr(7)}, now.Add(time.Minute)); err != nil {
		t.Fatalf("upsert 2: %v", err)
	}

	// 3. Third write: a prune-only patch (no size, no count). Both
	//    prior values must survive.
	if err := s.UpsertHostRepoStatsHistory(ctx, hostID, day,
		HostRepoStats{}, now.Add(2*time.Minute)); err != nil {
		t.Fatalf("upsert 3: %v", err)
	}

	pts, err := s.ListHostRepoStatsHistory(ctx, hostID, time.Time{})
	if err != nil {
		t.Fatalf("list: %v", err)
	}
	if len(pts) != 1 {
		t.Fatalf("want 1 point, got %d", len(pts))
	}
	p := pts[0]
	if p.TotalSizeBytes == nil || *p.TotalSizeBytes != 100 {
		t.Errorf("TotalSizeBytes: want 100, got %v", p.TotalSizeBytes)
	}
	if p.SnapshotCount == nil || *p.SnapshotCount != 7 {
		t.Errorf("SnapshotCount: want 7, got %v", p.SnapshotCount)
	}
}

func TestHostRepoStatsHistory_OrderingAndSinceFilter(t *testing.T) {
	t.Parallel()
	s := openTestStore(t)
	ctx := context.Background()

	const hostID = "h-history-2"
	seedHost(t, s, hostID)

	now := time.Now().UTC()
	for i, day := range []string{"2026-05-01", "2026-05-02", "2026-05-04", "2026-05-07"} {
		v := int64(100 + i*10)
		if err := s.UpsertHostRepoStatsHistory(ctx, hostID, day,
			HostRepoStats{TotalSizeBytes: &v}, now); err != nil {
			t.Fatalf("upsert %s: %v", day, err)
		}
	}

	all, err := s.ListHostRepoStatsHistory(ctx, hostID, time.Time{})
	if err != nil {
		t.Fatalf("list all: %v", err)
	}
	if len(all) != 4 {
		t.Fatalf("want 4 points, got %d", len(all))
	}
	wantDays := []string{"2026-05-01", "2026-05-02", "2026-05-04", "2026-05-07"}
	for i, p := range all {
		got := p.Day.Format("2006-01-02")
		if got != wantDays[i] {
			t.Errorf("point %d: want day %s, got %s", i, wantDays[i], got)
		}
	}

	since, _ := time.Parse("2006-01-02", "2026-05-03")
	recent, err := s.ListHostRepoStatsHistory(ctx, hostID, since)
	if err != nil {
		t.Fatalf("list since: %v", err)
	}
	if len(recent) != 2 {
		t.Fatalf("since 2026-05-03: want 2 points, got %d", len(recent))
	}
}

func TestHostRepoStatsHistory_CascadeOnHostDelete(t *testing.T) {
	t.Parallel()
	s := openTestStore(t)
	ctx := context.Background()

	const hostID = "h-history-3"
	seedHost(t, s, hostID)
	if err := s.UpsertHostRepoStatsHistory(ctx, hostID, "2026-05-07",
		HostRepoStats{TotalSizeBytes: int64ptr(42)}, time.Now().UTC()); err != nil {
		t.Fatalf("upsert: %v", err)
	}

	if err := s.DeleteHost(ctx, hostID); err != nil {
		t.Fatalf("delete host: %v", err)
	}

	pts, err := s.ListHostRepoStatsHistory(ctx, hostID, time.Time{})
	if err != nil {
		t.Fatalf("list after delete: %v", err)
	}
	if len(pts) != 0 {
		t.Fatalf("want 0 points after host delete, got %d", len(pts))
	}
}
