package main

import (
	"context"
	"fmt"
	"math/rand"
	"time"

	"github.com/jackc/pgx/v5"
)

// A distinct, deterministic synthetic workload, not a claim to reproduce Faker text.
// Same scale/skew as the assignment; both applications receive identical rows.
func seed(ctx context.Context, c *pgx.Conn) error {
	if err := guard(ctx, c); err != nil {
		return err
	}
	if _, err := c.Exec(ctx, `TRUNCATE blog_comment,blog_post_tags,blog_post,blog_tag,blog_user RESTART IDENTITY`); err != nil {
		return err
	}
	rng := rand.New(rand.NewSource(42))
	base := time.Date(2024, 12, 31, 0, 0, 0, 0, time.UTC)
	copyRows := func(table string, cols []string, rows [][]any) error {
		_, err := c.CopyFrom(ctx, pgx.Identifier{table}, cols, pgx.CopyFromRows(rows))
		return err
	}
	users := make([][]any, 1000)
	for i := range users {
		users[i] = []any{int64(i + 1), fmt.Sprintf("user%05d", i), fmt.Sprintf("user%05d@example.com", i), fmt.Sprintf("User %d", i), "", base}
	}
	if err := copyRows("blog_user", []string{"id", "username", "email", "display_name", "bio", "created_at"}, users); err != nil {
		return err
	}
	tags := make([][]any, 50)
	for i := range tags {
		s := fmt.Sprintf("tag-%02d", i)
		if i < 5 {
			s = []string{"python", "django", "postgres", "devops", "sre"}[i]
		}
		tags[i] = []any{int64(i + 1), s, s, base}
	}
	if err := copyRows("blog_tag", []string{"id", "name", "slug", "created_at"}, tags); err != nil {
		return err
	}
	author := func() int64 {
		if rng.Float64() < 0.3 {
			return int64(rng.Intn(10) + 1)
		}
		return int64(rng.Intn(1000) + 1)
	}
	for start := 0; start < 100000; start += 1000 {
		posts := make([][]any, 1000)
		relations := [][]any{}
		for j := range posts {
			i := start + j
			days := 1095
			if rng.Float64() < 0.5 {
				days = 180
			}
			ts := base.Add(-time.Duration(rng.Intn(days*86400)) * time.Second)
			title := fmt.Sprintf("Article %d about %s", i, []string{"python", "django", "postgres", "devops", "sre"}[i%5])
			body := fmt.Sprintf("Deterministic article body %d. ", i) + repeatText(20)
			posts[j] = []any{int64(i + 1), title, body, rng.Float64() < 0.9, rng.Intn(5000), ts, ts, author()}
			chosen := map[int]bool{}
			count := max(1, int(rng.NormFloat64()+3))
			for k := 0; k < count; k++ {
				tag := rng.Intn(45) + 6
				if rng.Float64() < 0.4 {
					tag = rng.Intn(5) + 1
				}
				chosen[tag] = true
			}
			// Fixed tag traversal makes generated link IDs reproducible too.
			for tag := 1; tag <= 50; tag++ {
				if chosen[tag] {
					relations = append(relations, []any{int64(i + 1), int64(tag)})
				}
			}
		}
		if err := copyRows("blog_post", []string{"id", "title", "body", "is_published", "view_count", "created_at", "updated_at", "author_id"}, posts); err != nil {
			return err
		}
		if err := copyRows("blog_post_tags", []string{"post_id", "tag_id"}, relations); err != nil {
			return err
		}
	}
	for start := 0; start < 500000; start += 1000 {
		rows := make([][]any, 1000)
		for j := range rows {
			post := rng.Intn(100000) + 1
			if rng.Float64() < 0.5 {
				post = rng.Intn(1000) + 1
			}
			rows[j] = []any{int64(start + j + 1), fmt.Sprintf("Comment %d with café", start+j), base.Add(-time.Duration(rng.Intn(1095*86400)) * time.Second), int64(post), author()}
		}
		if err := copyRows("blog_comment", []string{"id", "body", "created_at", "post_id", "author_id"}, rows); err != nil {
			return err
		}
	}
	for _, table := range []string{"blog_user", "blog_tag", "blog_post", "blog_comment"} {
		if _, err := c.Exec(ctx, "SELECT setval(pg_get_serial_sequence('"+table+"','id'),(SELECT max(id) FROM "+table+"))"); err != nil {
			return err
		}
	}
	_, err := c.Exec(ctx, `CREATE TABLE IF NOT EXISTS harness_seed_state (id bigint PRIMARY KEY, view_count integer NOT NULL, updated_at timestamptz NOT NULL);
 TRUNCATE harness_seed_state;
 INSERT INTO harness_seed_state SELECT id,view_count,updated_at FROM blog_post WHERE id=1;
 ANALYZE`)
	return err
}
func repeatText(n int) string {
	s := ""
	for range n {
		s += "Text for search and serialization. "
	}
	return s
}
