package example_test

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"strings"

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

type ExampleUser struct {
	ID       int64  `rest:"default"`
	Name     string `rest:"default"`
	password string
	Group    *ExampleGroup
	Avatar   []byte `rest:"ignore"`
}

func (s *ExampleUser) RestFields(result json.Map, files map[string]io.ReadCloser, names rest.FieldList) {
	if _, check := names.Field("avatar"); check {
		if len(s.Avatar) == 0 {
			result["avatar"] = nil
		} else {
			fName := fmt.Sprintf("user%v.avatar.jpg", s.ID)
			result["avatar"] = fName
			log.Println("--------------------------->", s.Avatar)
			files[fName] = io.NopCloser(bytes.NewReader(s.Avatar))
		}
	}
}

// Register ////////////////////////////////////////////

type ExampleRequestRegister struct {
	ID       int64
	Name     string `rest:"required"`
	Password string `rest:"required"`
	GroupID  int64  `rest:"required"`
	// Объект группы, который определяется в валидации.
	// В боевых условиях это поле должно быть приватное.
	group *ExampleGroup
}

func (s *ExampleRequestRegister) Validate(req rest.IRequest) rest.IResponse {
	// пользователь не должен быть авторизован
	if req.Auth() != nil {
		return req.ResponseError(
			500,
			rest.ErrorMessage("AlreadyAuthorized", "User is already authorized"),
		)
	}
	// проверяем имя
	if s.Name = strings.TrimSpace(s.Name); len(s.Name) == 0 {
		return req.ResponseError(500, rest.ErrorFiled("name", "expected not empty string"))
	}
	// проверяем пароль
	if len(s.Password) < 3 {
		return req.ResponseError(500, rest.ErrorFiled("password", "expected minimum 3 symbols"))
	}
	// вилидируем группу
	group, check := App.groups.Load(s.GroupID)
	if !check {
		return req.ResponseError(500, rest.ErrorMessage("GroupNotFound", "Group is not found"))
	}
	// Устанавливаем группу для использования в методе выполняния,
	// чтобы не выбирать её снова
	s.group = group.(*ExampleGroup)
	return nil
}

func (s *ExampleRequestRegister) Execute(req rest.IRequest) rest.IResponse {
	// создаем нового юзера
	userID := App.GenerateID()
	user := &ExampleUser{
		ID:       userID,
		Name:     s.Name,
		password: s.Password,
		Group:    s.group,
	}

	// генерируем токен авторизацции
	token, err := req.GenerateToken(
		json.Map{
			"id": userID,
		},
		0,
	)
	if err != nil {
		return req.ResponseError(500, rest.ErrorMessage("TokenGenerateError", err.Error()))
	}

	files := make(map[string]rest.IReadCloserLen)
	// сохраняем пользлвателя в хранилище
	App.users.Store(userID, user)
	fields, err := rest.Fields(user, files, req.Data().Slice("fields", nil)...)
	if err != nil {
		return req.ResponseError(500, rest.ErrorMessage("FieldsError", err.Error()))
	}

	// возвращаем успешный ответ
	return req.ResponseSuccess(
		json.Map{
			"user":  fields,
			"token": token,
		},
		nil,
	)
}

// user info ////////////////////////////////////////////

type ExampleRequestUserInfo struct {
	user *ExampleUser
}

func (s *ExampleRequestUserInfo) Validate(req rest.IRequest) rest.IResponse {
	if !req.IsAuth() {
		return req.ResponseError(500, rest.ErrorMessage("NotAuth", "Not authorized"))
	}
	auth := req.Auth()
	user, check := App.users.Load(auth.Int("id", 0))
	if !check {
		return req.ResponseError(500, rest.ErrorMessage("UserNotFound", "User not found"))
	}
	s.user = user.(*ExampleUser)
	return nil
}

func (s *ExampleRequestUserInfo) Execute(req rest.IRequest) rest.IResponse {
	files := make(map[string]rest.IReadCloserLen)
	log.Println(s.user.Group)
	fields := req.Data().Slice("fields", nil)
	rFields, err := rest.Fields(s.user, files, fields...)
	log.Println(err)
	if err != nil {
		return req.ResponseError(500, err)
	}
	return req.ResponseSuccess(rFields, files)
}

// set avatar

type ExampleRequestSetAvatar struct {
	user   *ExampleUser
	avatar io.Reader
}

func (s *ExampleRequestSetAvatar) Validate(req rest.IRequest) rest.IResponse {
	// проверяем авторизацию
	if !req.IsAuth() {
		return req.ResponseError(500, rest.ErrorMessage("NotAuth", "Not authorized"))
	}
	// проверяем файл аватара
	var check bool
	if s.avatar, check = req.File("avatar.jpg"); !check {
		return req.ResponseError(500, rest.ErrorMessage("FileNotFound", "avatar.jpg"))
	}
	// поиск юзера
	auth := req.Auth()
	user, check := App.users.Load(auth.Int("id", 0))
	if !check {
		//return rest.ResponseErrorMessage("UserNotFound", "User not found", 500)
		return req.ResponseError(500, rest.ErrorMessage("UserNotFound", "User not found"))
	}
	s.user = user.(*ExampleUser)
	return nil
}

func (s *ExampleRequestSetAvatar) Execute(req rest.IRequest) rest.IResponse {
	// сохраняем аватар
	f, _ := req.File("avatar.jpg")
	s.user.Avatar, _ = io.ReadAll(f)
	log.Println("U_Ava", s.user.Avatar)
	// возвращаем пустой ответ
	return req.ResponseSuccess(json.Map{}, nil)
}
