// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build goexperiment.jsonv2

package jsontext

import (
	"bytes"
	"errors"
	"io"
	"math/rand"
	"slices"
	"testing"

	"encoding/json/internal/jsontest"
)

func FuzzCoder(f *testing.F) {
	// Add a number of inputs to the corpus including valid and invalid data.
	for _, td := range coderTestdata {
		f.Add(int64(0), []byte(td.in))
	}
	for _, td := range decoderErrorTestdata {
		f.Add(int64(0), []byte(td.in))
	}
	for _, td := range encoderErrorTestdata {
		f.Add(int64(0), []byte(td.wantOut))
	}
	for _, td := range jsontest.Data {
		f.Add(int64(0), td.Data())
	}

	f.Fuzz(func(t *testing.T, seed int64, b []byte) {
		var tokVals []tokOrVal
		rn := rand.NewSource(seed)

		// Read a sequence of tokens or values. Skip the test for any errors
		// since we expect this with randomly generated fuzz inputs.
		src := bytes.NewReader(b)
		dec := NewDecoder(src)
		for {
			if rn.Int63()%8 > 0 {
				tok, err := dec.ReadToken()
				if err != nil {
					if err == io.EOF {
						break
					}
					t.Skipf("Decoder.ReadToken error: %v", err)
				}
				tokVals = append(tokVals, tok.Clone())
			} else {
				val, err := dec.ReadValue()
				if err != nil {
					expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']'
					if expectError && errors.As(err, new(*SyntacticError)) {
						continue
					}
					if err == io.EOF {
						break
					}
					t.Skipf("Decoder.ReadValue error: %v", err)
				}
				tokVals = append(tokVals, append(zeroValue, val...))
			}
		}

		// Write a sequence of tokens or values. Fail the test for any errors
		// since the previous stage guarantees that the input is valid.
		dst := new(bytes.Buffer)
		enc := NewEncoder(dst)
		for _, tokVal := range tokVals {
			switch tokVal := tokVal.(type) {
			case Token:
				if err := enc.WriteToken(tokVal); err != nil {
					t.Fatalf("Encoder.WriteToken error: %v", err)
				}
			case Value:
				if err := enc.WriteValue(tokVal); err != nil {
					t.Fatalf("Encoder.WriteValue error: %v", err)
				}
			}
		}

		// Encoded output and original input must decode to the same thing.
		var got, want []Token
		for dec := NewDecoder(bytes.NewReader(b)); dec.PeekKind() > 0; {
			tok, err := dec.ReadToken()
			if err != nil {
				t.Fatalf("Decoder.ReadToken error: %v", err)
			}
			got = append(got, tok.Clone())
		}
		for dec := NewDecoder(dst); dec.PeekKind() > 0; {
			tok, err := dec.ReadToken()
			if err != nil {
				t.Fatalf("Decoder.ReadToken error: %v", err)
			}
			want = append(want, tok.Clone())
		}
		if !equalTokens(got, want) {
			t.Fatalf("mismatching output:\ngot  %v\nwant %v", got, want)
		}
	})
}

func FuzzResumableDecoder(f *testing.F) {
	for _, td := range resumableDecoderTestdata {
		f.Add(int64(0), []byte(td))
	}

	f.Fuzz(func(t *testing.T, seed int64, b []byte) {
		rn := rand.NewSource(seed)

		// Regardless of how many bytes the underlying io.Reader produces,
		// the provided tokens, values, and errors should always be identical.
		t.Run("ReadToken", func(t *testing.T) {
			decGot := NewDecoder(&FaultyBuffer{B: b, MaxBytes: 8, Rand: rn})
			decWant := NewDecoder(bytes.NewReader(b))
			gotTok, gotErr := decGot.ReadToken()
			wantTok, wantErr := decWant.ReadToken()
			if gotTok.String() != wantTok.String() || !equalError(gotErr, wantErr) {
				t.Errorf("Decoder.ReadToken = (%v, %v), want (%v, %v)", gotTok, gotErr, wantTok, wantErr)
			}
		})
		t.Run("ReadValue", func(t *testing.T) {
			decGot := NewDecoder(&FaultyBuffer{B: b, MaxBytes: 8, Rand: rn})
			decWant := NewDecoder(bytes.NewReader(b))
			gotVal, gotErr := decGot.ReadValue()
			wantVal, wantErr := decWant.ReadValue()
			if !slices.Equal(gotVal, wantVal) || !equalError(gotErr, wantErr) {
				t.Errorf("Decoder.ReadValue = (%s, %v), want (%s, %v)", gotVal, gotErr, wantVal, wantErr)
			}
		})
	})
}

func FuzzValueFormat(f *testing.F) {
	for _, td := range valueTestdata {
		f.Add(int64(0), []byte(td.in))
	}

	// isValid reports whether b is valid according to the specified options.
	isValid := func(b []byte, opts ...Options) bool {
		d := NewDecoder(bytes.NewReader(b), opts...)
		_, errVal := d.ReadValue()
		_, errEOF := d.ReadToken()
		return errVal == nil && errEOF == io.EOF
	}

	// stripWhitespace removes all JSON whitespace characters from the input.
	stripWhitespace := func(in []byte) (out []byte) {
		out = make([]byte, 0, len(in))
		for _, c := range in {
			switch c {
			case ' ', '\n', '\r', '\t':
			default:
				out = append(out, c)
			}
		}
		return out
	}

	allOptions := []Options{
		AllowDuplicateNames(true),
		AllowInvalidUTF8(true),
		EscapeForHTML(true),
		EscapeForJS(true),
		PreserveRawStrings(true),
		CanonicalizeRawInts(true),
		CanonicalizeRawFloats(true),
		ReorderRawObjects(true),
		SpaceAfterColon(true),
		SpaceAfterComma(true),
		Multiline(true),
		WithIndent("\t"),
		WithIndentPrefix("    "),
	}

	f.Fuzz(func(t *testing.T, seed int64, b []byte) {
		validRFC7159 := isValid(b, AllowInvalidUTF8(true), AllowDuplicateNames(true))
		validRFC8259 := isValid(b, AllowInvalidUTF8(false), AllowDuplicateNames(true))
		validRFC7493 := isValid(b, AllowInvalidUTF8(false), AllowDuplicateNames(false))
		switch {
		case !validRFC7159 && validRFC8259:
			t.Errorf("invalid input per RFC 7159 implies invalid per RFC 8259")
		case !validRFC8259 && validRFC7493:
			t.Errorf("invalid input per RFC 8259 implies invalid per RFC 7493")
		}

		gotValid := Value(b).IsValid()
		wantValid := validRFC7493
		if gotValid != wantValid {
			t.Errorf("Value.IsValid = %v, want %v", gotValid, wantValid)
		}

		gotCompacted := Value(string(b))
		gotCompactOk := gotCompacted.Compact() == nil
		wantCompactOk := validRFC7159
		if !bytes.Equal(stripWhitespace(gotCompacted), stripWhitespace(b)) {
			t.Errorf("stripWhitespace(Value.Compact) = %s, want %s", stripWhitespace(gotCompacted), stripWhitespace(b))
		}
		if gotCompactOk != wantCompactOk {
			t.Errorf("Value.Compact success mismatch: got %v, want %v", gotCompactOk, wantCompactOk)
		}

		gotIndented := Value(string(b))
		gotIndentOk := gotIndented.Indent() == nil
		wantIndentOk := validRFC7159
		if !bytes.Equal(stripWhitespace(gotIndented), stripWhitespace(b)) {
			t.Errorf("stripWhitespace(Value.Indent) = %s, want %s", stripWhitespace(gotIndented), stripWhitespace(b))
		}
		if gotIndentOk != wantIndentOk {
			t.Errorf("Value.Indent success mismatch: got %v, want %v", gotIndentOk, wantIndentOk)
		}

		gotCanonicalized := Value(string(b))
		gotCanonicalizeOk := gotCanonicalized.Canonicalize() == nil
		wantCanonicalizeOk := validRFC7493
		if gotCanonicalizeOk != wantCanonicalizeOk {
			t.Errorf("Value.Canonicalize success mismatch: got %v, want %v", gotCanonicalizeOk, wantCanonicalizeOk)
		}

		// Random options should not result in a panic.
		var opts []Options
		rn := rand.New(rand.NewSource(seed))
		for _, opt := range allOptions {
			if rn.Intn(len(allOptions)/4) == 0 {
				opts = append(opts, opt)
			}
		}
		v := Value(b)
		v.Format(opts...) // should not panic
	})
}
