// Copyright 2012 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.

package quotedprintable

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"os/exec"
	"regexp"
	"slices"
	"strings"
	"testing"
	"time"
)

func TestReader(t *testing.T) {
	tests := []struct {
		in, want string
		err      any
	}{
		{in: "", want: ""},
		{in: "foo bar", want: "foo bar"},
		{in: "foo bar=3D", want: "foo bar="},
		{in: "foo bar=3d", want: "foo bar="}, // lax.
		{in: "foo bar=\n", want: "foo bar"},
		{in: "foo bar\n", want: "foo bar\n"}, // somewhat lax.
		{in: "foo bar=0", want: "foo bar=0"}, // lax
		{in: "foo bar=0D=0A", want: "foo bar\r\n"},
		{in: " A B        \r\n C ", want: " A B\r\n C"},
		{in: " A B =\r\n C ", want: " A B  C"},
		{in: " A B =\n C ", want: " A B  C"}, // lax. treating LF as CRLF
		{in: "foo=\nbar", want: "foobar"},
		{in: "foo\x00bar", want: "foo", err: "quotedprintable: invalid unescaped byte 0x00 in body"},
		{in: "foo bar\xff", want: "foo bar\xff"},

		// Equal sign.
		{in: "=3D30\n", want: "=30\n"},
		{in: "=00=FF0=\n", want: "\x00\xff0"},

		// Trailing whitespace
		{in: "foo  \n", want: "foo\n"},
		{in: "foo  \n\nfoo =\n\nfoo=20\n\n", want: "foo\n\nfoo \nfoo \n\n"},

		// Tests that we allow bare \n and \r through, despite it being strictly
		// not permitted per RFC 2045, Section 6.7 Page 22 bullet (4).
		{in: "foo\nbar", want: "foo\nbar"},
		{in: "foo\rbar", want: "foo\rbar"},
		{in: "foo\r\nbar", want: "foo\r\nbar"},

		// Different types of soft line-breaks.
		{in: "foo=\r\nbar", want: "foobar"},
		{in: "foo=\nbar", want: "foobar"},
		{in: "foo=\rbar", want: "foo", err: "quotedprintable: invalid hex byte 0x0d"},
		{in: "foo=\r\r\r \nbar", want: "foo", err: `quotedprintable: invalid bytes after =: "\r\r\r \n"`},
		// Issue 15486, accept trailing soft line-break at end of input.
		{in: "foo=", want: "foo"},
		{in: "=", want: "", err: `quotedprintable: invalid bytes after =: ""`},

		// Example from RFC 2045:
		{in: "Now's the time =\n" + "for all folk to come=\n" + " to the aid of their country.",
			want: "Now's the time for all folk to come to the aid of their country."},
		{in: "accept UTF-8 right quotation mark: ’",
			want: "accept UTF-8 right quotation mark: ’"},

		// Transport padding
		{in: "foo= \r\nbar", want: "foobar"},
		{in: "foo=\t \r\nbar", want: "foobar"},
	}
	for _, tt := range tests {
		var buf strings.Builder
		_, err := io.Copy(&buf, NewReader(strings.NewReader(tt.in)))
		if got := buf.String(); got != tt.want {
			t.Errorf("for %q, got %q; want %q", tt.in, got, tt.want)
		}
		switch verr := tt.err.(type) {
		case nil:
			if err != nil {
				t.Errorf("for %q, got unexpected error: %v", tt.in, err)
			}
		case string:
			if got := fmt.Sprint(err); got != verr {
				t.Errorf("for %q, got error %q; want %q", tt.in, got, verr)
			}
		case error:
			if err != verr {
				t.Errorf("for %q, got error %q; want %q", tt.in, err, verr)
			}
		}
	}

}

func everySequence(base, alpha string, length int, fn func(string)) {
	if len(base) == length {
		fn(base)
		return
	}
	for i := 0; i < len(alpha); i++ {
		everySequence(base+alpha[i:i+1], alpha, length, fn)
	}
}

var useQprint = flag.Bool("qprint", false, "Compare against the 'qprint' program.")

var badSoftRx = regexp.MustCompile(`=([^\r\n]+?\n)|([^\r\n]+$)|(\r$)|(\r[^\n]+\n)|( \r\n)`)

func TestExhaustive(t *testing.T) {
	if *useQprint {
		_, err := exec.LookPath("qprint")
		if err != nil {
			t.Fatalf("Error looking for qprint: %v", err)
		}
	}

	var buf strings.Builder
	res := make(map[string]int)
	n := 6
	if testing.Short() {
		n = 4
	}
	everySequence("", "0A \r\n=", n, func(s string) {
		if strings.HasSuffix(s, "=") || strings.Contains(s, "==") {
			return
		}
		buf.Reset()
		_, err := io.Copy(&buf, NewReader(strings.NewReader(s)))
		if err != nil {
			errStr := err.Error()
			if strings.Contains(errStr, "invalid bytes after =:") {
				errStr = "invalid bytes after ="
			}
			res[errStr]++
			if strings.Contains(errStr, "invalid hex byte ") {
				if strings.HasSuffix(errStr, "0x20") && (strings.Contains(s, "=0 ") || strings.Contains(s, "=A ") || strings.Contains(s, "= ")) {
					return
				}
				if strings.HasSuffix(errStr, "0x3d") && (strings.Contains(s, "=0=") || strings.Contains(s, "=A=")) {
					return
				}
				if strings.HasSuffix(errStr, "0x0a") || strings.HasSuffix(errStr, "0x0d") {
					// bunch of cases; since whitespace at the end of a line before \n is removed.
					return
				}
			}
			if strings.Contains(errStr, "unexpected EOF") {
				return
			}
			if errStr == "invalid bytes after =" && badSoftRx.MatchString(s) {
				return
			}
			t.Errorf("decode(%q) = %v", s, err)
			return
		}
		if *useQprint {
			cmd := exec.Command("qprint", "-d")
			cmd.Stdin = strings.NewReader(s)
			stderr, err := cmd.StderrPipe()
			if err != nil {
				panic(err)
			}
			qpres := make(chan any, 2)
			go func() {
				br := bufio.NewReader(stderr)
				s, _ := br.ReadString('\n')
				if s != "" {
					qpres <- errors.New(s)
					if cmd.Process != nil {
						// It can get stuck on invalid input, like:
						// echo -n "0000= " | qprint -d
						cmd.Process.Kill()
					}
				}
			}()
			go func() {
				want, err := cmd.Output()
				if err == nil {
					qpres <- want
				}
			}()
			select {
			case got := <-qpres:
				if want, ok := got.([]byte); ok {
					if string(want) != buf.String() {
						t.Errorf("go decode(%q) = %q; qprint = %q", s, want, buf.String())
					}
				} else {
					t.Logf("qprint -d(%q) = %v", s, got)
				}
			case <-time.After(5 * time.Second):
				t.Logf("qprint timeout on %q", s)
			}
		}
		res["OK"]++
	})
	var outcomes []string
	for k, v := range res {
		outcomes = append(outcomes, fmt.Sprintf("%v: %d", k, v))
	}
	slices.Sort(outcomes)
	got := strings.Join(outcomes, "\n")
	want := `OK: 30638
invalid bytes after =: 2243
quotedprintable: invalid hex byte 0x0d: 2050
unexpected EOF: 194`
	if testing.Short() {
		want = `OK: 935
invalid bytes after =: 61
quotedprintable: invalid hex byte 0x0d: 26
unexpected EOF: 3`
	}

	if got != want {
		t.Errorf("Got:\n%s\nWant:\n%s", got, want)
	}
}
