package service

import (
	"github.com/google/uuid"
	"github.com/rs/zerolog"
	"web-qudo-be/app/database/entity"
	"web-qudo-be/app/module/clients/mapper"
	"web-qudo-be/app/module/clients/repository"
	"web-qudo-be/app/module/clients/request"
	"web-qudo-be/app/module/clients/response"
	usersRepository "web-qudo-be/app/module/users/repository"
	"web-qudo-be/utils/paginator"

	utilSvc "web-qudo-be/utils/service"
)

// ClientsService
type clientsService struct {
	Repo      repository.ClientsRepository
	UsersRepo usersRepository.UsersRepository
	Log       zerolog.Logger
}

// ClientsService define interface of IClientsService
type ClientsService interface {
	All(req request.ClientsQueryRequest) (clients []*response.ClientsResponse, paging paginator.Pagination, err error)
	Show(id uuid.UUID) (clients *response.ClientsResponse, err error)
	Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error)
	Update(id uuid.UUID, req request.ClientsUpdateRequest) (err error)
	Delete(id uuid.UUID) error
}

// NewClientsService init ClientsService
func NewClientsService(repo repository.ClientsRepository, log zerolog.Logger, usersRepo usersRepository.UsersRepository) ClientsService {

	return &clientsService{
		Repo:      repo,
		Log:       log,
		UsersRepo: usersRepo,
	}
}

// All implement interface of ClientsService
func (_i *clientsService) All(req request.ClientsQueryRequest) (clientss []*response.ClientsResponse, paging paginator.Pagination, err error) {
	results, paging, err := _i.Repo.GetAll(req)
	if err != nil {
		return
	}

	for _, result := range results {
		clientss = append(clientss, mapper.ClientsResponseMapper(result))
	}

	return
}

func (_i *clientsService) Show(id uuid.UUID) (clients *response.ClientsResponse, err error) {
	result, err := _i.Repo.FindOne(id)
	if err != nil {
		return nil, err
	}

	return mapper.ClientsResponseMapper(result), nil
}

func (_i *clientsService) Save(req request.ClientsCreateRequest, authToken string) (clients *entity.Clients, err error) {
	_i.Log.Info().Interface("data", req).Msg("")
	newReq := req.ToEntity()
	_i.Log.Info().Interface("token", authToken).Msg("")
	createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
	_i.Log.Info().Interface("token", authToken).Msg("")
	newReq.CreatedById = &createdBy.ID

	newReq.ID = uuid.New()

	_i.Log.Info().Interface("new data", newReq).Msg("")

	return _i.Repo.Create(newReq)
}

func (_i *clientsService) Update(id uuid.UUID, req request.ClientsUpdateRequest) (err error) {
	_i.Log.Info().Interface("data", req).Msg("")
	return _i.Repo.Update(id, req.ToEntity())
}

func (_i *clientsService) Delete(id uuid.UUID) error {
	result, err := _i.Repo.FindOne(id)
	if err != nil {
		return err
	}

	isActive := false
	result.IsActive = &isActive
	return _i.Repo.Update(id, result)
}
