package sample

import (
	"bytes"
	"compress/gzip"
	"encoding/csv"
	"encoding/hex"
	"encoding/json"
	"encoding/xml"
	"html/template"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"slices"
	"sort"
	"strconv"
	"strings"
	"time"

	proto "google.golang.org/protobuf/proto"
	yaml "gopkg.in/yaml.v3"
)

type xmlPayload struct {
	Name string `xml:"name"`
}

type protoPayload struct{}

func RenderList(w http.ResponseWriter, r *http.Request) {
	_, _ = template.ParseFiles("list.tmpl")
	_, _ = w.Write([]byte("ok"))
	_ = r
}

func CompileRows(rows []string, w http.ResponseWriter) {
	for _, row := range rows {
		compiled, _ := regexp.Compile("^" + row + "$")
		_ = compiled
		encoder := json.NewEncoder(w)
		_ = encoder.Encode(map[string]string{"row": row})
		zipWriter := gzip.NewWriter(w)
		_, _ = zipWriter.Write([]byte(row))
	}
}

func ExportRows(w http.ResponseWriter, rows [][]string) {
	writer := csv.NewWriter(w)
	for _, row := range rows {
		_ = writer.Write(row)
		writer.Flush()
	}
}

func DecodeTwice(body []byte) {
	var first map[string]string
	var second map[string]string
	_ = json.Unmarshal(body, &first)
	_ = json.Unmarshal(body, &second)
}

func DecodeMore(rows []string, body []byte) {
	var xmlFirst xmlPayload
	var xmlSecond xmlPayload
	_ = xml.Unmarshal(body, &xmlFirst)
	_ = xml.Unmarshal(body, &xmlSecond)

	var yamlFirst map[string]any
	var yamlSecond map[string]any
	_ = yaml.Unmarshal(body, &yamlFirst)
	_ = yaml.Unmarshal(body, &yamlSecond)

	var protoFirst protoPayload
	var protoSecond protoPayload
	_ = proto.Unmarshal(body, &protoFirst)
	_ = proto.Unmarshal(body, &protoSecond)

	for _, row := range rows {
		decoder := json.NewDecoder(strings.NewReader(row))
		_ = decoder
	}
}

func SplitSameInput(value string, payload []byte, raw string) {
	left := strings.Split(value, ",")
	right := strings.Fields(value)
	first := bytes.Split(payload, []byte(","))
	second := bytes.Fields(payload)
	id, _ := strconv.Atoi(raw)
	count, _ := strconv.ParseInt(raw, 10, 64)
	_ = left
	_ = right
	_ = first
	_ = second
	_ = id
	_ = count
}

func ParseLoop(rows []string, baseURL string, raw string) {
	for _, row := range rows {
		parsed, _ := url.Parse(baseURL)
		_ = parsed
		when, _ := time.Parse(time.RFC3339, raw)
		_ = when

		var builder strings.Builder
		_, _ = builder.WriteString(row)

		var buffer bytes.Buffer
		_, _ = buffer.WriteString(row)
	}
}

func ReadAllThenDecode(reader io.Reader) {
	body, _ := io.ReadAll(reader)
	var payload map[string]any
	_ = json.Unmarshal(body, &payload)
}

func CloneAndScratch(rows []string, payload []byte) {
	lookup := map[string]int{"alpha": 1}
	for _, row := range rows {
		scratch := make([]byte, 0, 16)
		tags := make(map[string]int)
		clone := slices.Clone(payload)
		_ = scratch
		_ = clone
		tags[row] = len(row)
		_, _ = lookup[string([]byte(row))]
		_ = slices.Contains(rows, row)
	}
}

func AppendWithoutPrealloc(items []string) []int {
	var result []int
	for _, item := range items {
		result = append(result, len(item))
	}
	return result
}

func NestedAppend(rows [][]string) []string {
	var all []string
	for _, row := range rows {
		for _, cell := range row {
			all = append(all, cell)
		}
	}
	return all
}

func MapNoHint(items []string) {
	counts := map[string]int{}
	for _, item := range items {
		counts[item] += 1
	}
	_ = counts
}

func BuilderNoGrow(items []string) string {
	var builder strings.Builder
	for _, item := range items {
		builder.WriteString(item)
	}
	return builder.String()
}

func BufferNoGrow(items []string) []byte {
	var buffer bytes.Buffer
	for _, item := range items {
		buffer.WriteString(item)
	}
	return buffer.Bytes()
}

func CloneMapInLoop(base map[string]int, items []string) {
	for _, item := range items {
		copy := make(map[string]int)
		for k, v := range base {
			copy[k] = v
		}
		copy[item] = 1
		_ = copy
	}
}

func AppendThenTrim(items []string) {
	var buf []byte
	for _, item := range items {
		buf = append(buf, item...)
		buf = buf[:0]
	}
	_ = buf
}

func NormalizeInLoop(rows []string, prefix string) {
	for _, row := range rows {
		lower := strings.ToLower(prefix)
		_ = lower + row
	}
}

func WriteWithoutBufio(items []string) {
	f, _ := os.Create("output.txt")
	defer f.Close()
	for _, item := range items {
		f.Write([]byte(item))
	}
}

func ReadWithoutBufio(f *os.File) {
	buf := make([]byte, 1)
	for {
		f.Read(buf)
	}
}

func NestedJoinSearch(users []string, allowed []string) {
	for _, user := range users {
		for _, a := range allowed {
			if a == user || slices.Contains(allowed, user) {
				_ = a
			}
		}
	}
}

func SortEachIteration(items []string, batches [][]int) {
	for _, batch := range batches {
		sort.Ints(batch)
		_ = items
	}
}

func SortForFirst(items []int) int {
	sort.Ints(items)
	return items[0]
}

func FilterCountIterate(rows []string) {
	var filtered []string
	for _, row := range rows {
		if len(row) > 3 {
			filtered = append(filtered, row)
		}
	}
	count := 0
	for _, row := range filtered {
		count += len(row)
		_ = row
	}
	for _, row := range filtered {
		_ = row
	}
	_ = count
}

func FormatForLogs(ids []string) {
	for _, id := range ids {
		formatted := hex.EncodeToString([]byte(id))
		log.Debug("processing id: " + formatted)
	}
}
}