package pinterest

import (
	"strings"
	"testing"
)

// goldenData holds reference values generated by the Python implementation
// (pinscrape/v2.py payload encoding) for the same inputs. The Go encoder must
// be byte-identical or Pinterest may reject the request.
type golden struct {
	query  string
	source string
	data   string
}

var goldens = []golden{
	{
		query:  "iphone case",
		source: "/search/pins/?q=iphone%20case&rs=typed",
		data:   "%7B%22options%22%3A%7B%22applied_unified_filters%22%3Anull%2C%22appliedProductFilters%22%3A%22---%22%2C%22article%22%3Anull%2C%22auto_correction_disabled%22%3Afalse%2C%22corpus%22%3Anull%2C%22customized_rerank_type%22%3Anull%2C%22domains%22%3Anull%2C%22filters%22%3Anull%2C%22journey_depth%22%3Anull%2C%22page_size%22%3A%2226%22%2C%22price_max%22%3Anull%2C%22price_min%22%3Anull%2C%22query_pin_sigs%22%3Anull%2C%22query%22%3A%22iphone%20case%22%2C%22redux_normalize_feed%22%3Atrue%2C%22request_params%22%3Anull%2C%22rs%22%3A%22typed%22%2C%22scope%22%3A%22pins%22%2C%22selected_one_bar_modules%22%3Anull%2C%22source_id%22%3Anull%2C%22source_module_id%22%3Anull%2C%22seoDrawerEnabled%22%3Afalse%2C%22source_url%22%3A%22%2Fsearch%2Fpins%2F%3Fq%3Diphone%2520case%26rs%3Dtyped%22%2C%22top_pin_id%22%3Anull%2C%22top_pin_ids%22%3Anull%7D%2C%22context%22%3A%7B%7D%7D",
	},
	{
		query:  "hello world",
		source: "/search/pins/?q=hello%20world&rs=typed",
		data:   "%7B%22options%22%3A%7B%22applied_unified_filters%22%3Anull%2C%22appliedProductFilters%22%3A%22---%22%2C%22article%22%3Anull%2C%22auto_correction_disabled%22%3Afalse%2C%22corpus%22%3Anull%2C%22customized_rerank_type%22%3Anull%2C%22domains%22%3Anull%2C%22filters%22%3Anull%2C%22journey_depth%22%3Anull%2C%22page_size%22%3A%2226%22%2C%22price_max%22%3Anull%2C%22price_min%22%3Anull%2C%22query_pin_sigs%22%3Anull%2C%22query%22%3A%22hello%20world%22%2C%22redux_normalize_feed%22%3Atrue%2C%22request_params%22%3Anull%2C%22rs%22%3A%22typed%22%2C%22scope%22%3A%22pins%22%2C%22selected_one_bar_modules%22%3Anull%2C%22source_id%22%3Anull%2C%22source_module_id%22%3Anull%2C%22seoDrawerEnabled%22%3Afalse%2C%22source_url%22%3A%22%2Fsearch%2Fpins%2F%3Fq%3Dhello%2520world%26rs%3Dtyped%22%2C%22top_pin_id%22%3Anull%2C%22top_pin_ids%22%3Anull%7D%2C%22context%22%3A%7B%7D%7D",
	},
	{
		query:  "100% tips",
		source: "/search/pins/?q=100%25%20tips&rs=typed",
		data:   "%7B%22options%22%3A%7B%22applied_unified_filters%22%3Anull%2C%22appliedProductFilters%22%3A%22---%22%2C%22article%22%3Anull%2C%22auto_correction_disabled%22%3Afalse%2C%22corpus%22%3Anull%2C%22customized_rerank_type%22%3Anull%2C%22domains%22%3Anull%2C%22filters%22%3Anull%2C%22journey_depth%22%3Anull%2C%22page_size%22%3A%2226%22%2C%22price_max%22%3Anull%2C%22price_min%22%3Anull%2C%22query_pin_sigs%22%3Anull%2C%22query%22%3A%22100%2525%20tips%22%2C%22redux_normalize_feed%22%3Atrue%2C%22request_params%22%3Anull%2C%22rs%22%3A%22typed%22%2C%22scope%22%3A%22pins%22%2C%22selected_one_bar_modules%22%3Anull%2C%22source_id%22%3Anull%2C%22source_module_id%22%3Anull%2C%22seoDrawerEnabled%22%3Afalse%2C%22source_url%22%3A%22%2Fsearch%2Fpins%2F%3Fq%3D100%252525%2520tips%26rs%3Dtyped%22%2C%22top_pin_id%22%3Anull%2C%22top_pin_ids%22%3Anull%7D%2C%22context%22%3A%7B%7D%7D",
	},
	{
		query:  "a b/c?d=e&f",
		source: "/search/pins/?q=a%20b/c%3Fd%3De%26f&rs=typed",
		data:   "%7B%22options%22%3A%7B%22applied_unified_filters%22%3Anull%2C%22appliedProductFilters%22%3A%22---%22%2C%22article%22%3Anull%2C%22auto_correction_disabled%22%3Afalse%2C%22corpus%22%3Anull%2C%22customized_rerank_type%22%3Anull%2C%22domains%22%3Anull%2C%22filters%22%3Anull%2C%22journey_depth%22%3Anull%2C%22page_size%22%3A%2226%22%2C%22price_max%22%3Anull%2C%22price_min%22%3Anull%2C%22query_pin_sigs%22%3Anull%2C%22query%22%3A%22a%20b%2Fc%3Fd%3De%26f%22%2C%22redux_normalize_feed%22%3Atrue%2C%22request_params%22%3Anull%2C%22rs%22%3A%22typed%22%2C%22scope%22%3A%22pins%22%2C%22selected_one_bar_modules%22%3Anull%2C%22source_id%22%3Anull%2C%22source_module_id%22%3Anull%2C%22seoDrawerEnabled%22%3Afalse%2C%22source_url%22%3A%22%2Fsearch%2Fpins%2F%3Fq%3Da%2520b%2Fc%25253Fd%25253De%252526f%26rs%3Dtyped%22%2C%22top_pin_id%22%3Anull%2C%22top_pin_ids%22%3Anull%7D%2C%22context%22%3A%7B%7D%7D",
	},
}

func TestBuildSearchURLMatchesPython(t *testing.T) {
	for _, g := range goldens {
		url, source := BuildSearchURL("https://in.pinterest.com", g.query, 26)

		if source != g.source {
			t.Errorf("query %q: sourceURL mismatch\n got: %s\nwant: %s", g.query, source, g.source)
		}

		i := strings.Index(url, "&data=")
		if i < 0 {
			t.Fatalf("query %q: no data param in %s", g.query, url)
		}
		rest := url[i+len("&data="):]
		j := strings.Index(rest, "&_=")
		if j < 0 {
			t.Fatalf("query %q: no epoch param in %s", g.query, url)
		}
		data := rest[:j]
		if data != g.data {
			t.Errorf("query %q: data param mismatch\n got: %s\nwant: %s", g.query, data, g.data)
		}

		if !strings.Contains(url, "resource/BaseSearchResource/get/?source_url=") {
			t.Errorf("query %q: endpoint mismatch: %s", g.query, url)
		}
	}
}

func TestExtractMerged(t *testing.T) {
	body := []byte(`{"resource_response":{"data":{"results":[
		{"id":"1","title":"Hello","description":"Desc one","images":{"orig":{"url":"http://x/1.jpg"}}},
		{"id":"2","grid_title":"Grid title","description":"","images":{"orig":{"url":"http://x/2.jpg"}}},
		{"id":"3","seo_alt_text":"Alt","description":"Desc three","images":{"orig":{"url":"http://x/3.jpg"}}}
	]}}}`)
	resp, err := ParseSearchResponse(body)
	if err != nil {
		t.Fatal(err)
	}
	out := Extract(resp, "fallback")
	if len(out.Images) != 3 {
		t.Fatalf("want 3 images, got %d", len(out.Images))
	}
	if out.Images[0].Title != "Hello" {
		t.Fatalf("title parse: %s", out.Images[0].Title)
	}
	if out.Images[1].Title != "Grid title" {
		t.Fatalf("grid_title fallback: %s", out.Images[1].Title)
	}
	if out.Images[2].Title != "Alt" {
		t.Fatalf("seo_alt_text fallback: %s", out.Images[2].Title)
	}
	if len(out.Descriptions) != 2 {
		t.Fatalf("want 2 non-empty descriptions, got %d", len(out.Descriptions))
	}
}

func TestExtractTitleDictForm(t *testing.T) {
	body := []byte(`{"resource_response":{"data":{"results":[
		{"id":"1","title":{"text":"Dict Title"},"description":"d","images":{"orig":{"url":"http://x/1.jpg"}}}
	]}}}`)
	resp, _ := ParseSearchResponse(body)
	out := Extract(resp, "fallback")
	if out.Images[0].Title != "Dict Title" {
		t.Fatalf("dict title parse: %s", out.Images[0].Title)
	}
}
