package example_test

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"mime"
	"mime/multipart"
	"net/http"
	"strings"
	"testing"

	"git.ali33.ru/fcg-xvii/go-tools/json"
)

func SendRequest(uri string, data json.Map, files map[string]io.Reader, auth string) (rData json.Map, rFiles map[string]io.Reader) {
	var (
		buf         io.Reader
		contentType string
	)
	if files == nil {
		// json
		contentType = "application/json"
		buf = bytes.NewBuffer(data.JSON())
	} else {
		// multipart form
		rBuf := bytes.NewBuffer(nil)
		form := multipart.NewWriter(rBuf)
		// setup content type
		contentType = form.FormDataContentType()
		// json (data)
		field, _ := form.CreateFormField("data")
		field.Write(data.JSON())
		// files
		for name, file := range files {
			part, _ := form.CreateFormFile(name, name)
			io.Copy(part, file)
		}
		form.Close()
		buf = rBuf
	}
	req, _ := http.NewRequest(
		"POST",
		fmt.Sprintf("http://localhost:8080%s", uri),
		buf,
	)
	req.Header.Set("Content-Type", contentType)
	if len(auth) > 0 {
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", auth))
	}
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	if resp.StatusCode != http.StatusOK {
		bData, _ := io.ReadAll(resp.Body)
		log.Println(string(bData))
		json.Unmarshal(bData, &rData)
		log.Fatal("bad status code: ", resp.StatusCode, rData.JSONPrettyString())
	}
	rContentType := resp.Header.Get("Content-Type")
	log.Println("---------------------", rContentType)
	if rContentType == "application/json" {
		bData, _ := io.ReadAll(resp.Body)
		log.Println(string(bData))
		json.Unmarshal(bData, &rData)
	} else if strings.Contains(rContentType, "multipart/form-data") {
		rFiles = make(map[string]io.Reader)
		_, params, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
		mReader := multipart.NewReader(resp.Body, params["boundary"])
		for {
			part, err := mReader.NextPart()
			if err == io.EOF {
				break // Закончить на конце потока
			}
			if err != nil {
				log.Fatal(err)
			}
			if part.FormName() == "data" {
				bData, _ := io.ReadAll(part)
				json.Unmarshal(bData, &rData)
			} else {
				if fName := part.FileName(); len(fName) > 0 {
					// Создаем новый Buffer для хранения данных файла
					buf := new(bytes.Buffer)
					// Копируем данные из part в Buffer
					_, err := io.Copy(buf, part)
					if err != nil {
						log.Fatal(err) // Или обработайте ошибку по-другому
					}
					// Сохраняем Buffer в rFiles
					rFiles[fName] = buf
				}
			}
			part.Close()
		}
	}
	resp.Body.Close()
	return
}

func TestExample(t *testing.T) {
	var data json.Map
	var files map[string]io.Reader
	ExampleNew()

	t.Log("--- register user ---")
	data, _ = SendRequest(
		"/user/register",
		json.Map{
			"name":     "First User",
			"password": "my-strong-pass",
			"group_id": 1,
		},
		nil,
		"",
	)
	t.Log(data)
	t.Log("------------------------------------------")
	token := data.String("token", "")
	t.Log("token", token)

	t.Log("--- set avatar ---")
	sFiles := map[string]io.Reader{
		"avatar.jpg": bytes.NewBuffer([]byte{1, 2, 3, 4, 5}),
	}

	data, files = SendRequest(
		"/user/set_avatar",
		json.Map{},
		sFiles,
		token,
	)

	data.LogPretty()

	t.Log("------------------------------------------")

	t.Log("--- user info ---")
	data, files = SendRequest(
		"/user/info",
		json.Map{
			"fields": []string{
				"id", "name", "group", "avatar",
			},
		},
		nil,
		token,
	)
	data.LogPretty()
	log.Println(files)
	if data["avatar"] != nil {
		avData, err := io.ReadAll(files[data.String("avatar", "")])
		log.Println("avData", avData, err)
	}
	t.Log("------------------------------------------")
	//ch := make(chan struct{})
	//<-ch
}
