package grok

import (
	"context"
	"crypto/sha1"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
	"time"

	http "github.com/bogdanfinn/fhttp"
)

var innerChunkRe = regexp.MustCompile(`static/chunks/[a-zA-Z0-9_.~\-/]+\.js`)

func hnew(ctx context.Context, url, token string) (*http.Request, error) {
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return nil, err
	}
	req = req.WithContext(ctx)
	req.Header = http.Header{
		"accept":          {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
		"accept-language": {"en-US,en;q=0.9"},
		"user-agent":      {userAgent},
		"cookie":          {"sso=" + token + "; sso-rw=" + token},
		http.HeaderOrderKey: {"accept", "accept-language", "user-agent", "cookie"},
	}
	return req, nil
}

func TestGrokCacheChunks(t *testing.T) {
	token := os.Getenv("DIAG_SSO")
	if token == "" {
		t.Skip("no DIAG_SSO")
	}
	dir := os.Getenv("DIAG_CACHE")
	if dir == "" {
		dir = `f:\ai-gateway\vivid-ai\backend\_chunks`
	}
	os.MkdirAll(dir, 0o755)
	logf, _ := os.Create(filepath.Join(dir, "_log.txt"))
	defer logf.Close()
	lg := func(f string, a ...any) {
		fmt.Fprintf(logf, f+"\n", a...)
		logf.Sync()
	}

	c := NewClient(os.Getenv("DIAG_PROXY"))
	ctx, cancel := context.WithTimeout(context.Background(), 3000*time.Second)
	defer cancel()
	client, err := c.newTLSClient()
	if err != nil {
		t.Fatal(err)
	}

	hreq, _ := hnew(ctx, apiBase+"/", token)
	hresp, err := client.Do(hreq)
	if err != nil {
		t.Fatal(err)
	}
	body, _ := io.ReadAll(hresp.Body)
	hresp.Body.Close()
	html := string(body)
	os.WriteFile(filepath.Join(dir, "_home.html"), body, 0o644)

	seen := map[string]bool{}
	queue := dedupe(chunkPathRe.FindAllString(html, -1))
	lg("home chunk refs: %d", len(queue))

	saved := 0
	for len(queue) > 0 && saved < 3000 {
		p := queue[0]
		queue = queue[1:]
		norm := p
		if !strings.HasPrefix(norm, "/_next/") {
			norm = "/_next/" + strings.TrimPrefix(norm, "/")
		}
		if seen[norm] {
			continue
		}
		seen[norm] = true
		src, err := fetchChunk(ctx, client, norm)
		if err != nil {
			continue
		}
		saved++
		base := norm[strings.LastIndex(norm, "/")+1:]
		fn := fmt.Sprintf("%x_%s", sha1.Sum([]byte(norm)), base)
		if len(fn) > 120 {
			fn = fn[:120]
		}
		os.WriteFile(filepath.Join(dir, fn), []byte(src), 0o644)
		for _, m := range innerChunkRe.FindAllString(src, -1) {
			nn := "/_next/" + m
			if !seen[nn] {
				queue = append(queue, nn)
			}
		}
		if saved%50 == 0 {
			lg("saved=%d queue=%d", saved, len(queue))
		}
	}
	lg("CRAWL DONE saved=%d queue_left=%d", saved, len(queue))
	fmt.Printf("CRAWL DONE saved=%d\n", saved)
}
