package service

import (
	"github.com/google/uuid"
	"github.com/rs/zerolog"
	"netidhub-saas-be/app/database/entity"
	"netidhub-saas-be/app/module/article_approvals/mapper"
	"netidhub-saas-be/app/module/article_approvals/repository"
	"netidhub-saas-be/app/module/article_approvals/request"
	"netidhub-saas-be/app/module/article_approvals/response"
	articlesService "netidhub-saas-be/app/module/articles/service"
	usersRepository "netidhub-saas-be/app/module/users/repository"
	"netidhub-saas-be/utils/paginator"

	utilSvc "netidhub-saas-be/utils/service"
)

// ArticleApprovalsService
type articleApprovalsService struct {
	Repo            repository.ArticleApprovalsRepository
	UsersRepo       usersRepository.UsersRepository
	ArticlesService articlesService.ArticlesService
	Log             zerolog.Logger
}

// ArticleApprovalsService define interface of IArticleApprovalsService
type ArticleApprovalsService interface {
	All(req request.ArticleApprovalsQueryRequest) (articleApprovals []*response.ArticleApprovalsResponse, paging paginator.Pagination, err error)
	Show(id uint) (articleApprovals *response.ArticleApprovalsResponse, err error)
	Save(clientId *uuid.UUID, req request.ArticleApprovalsCreateRequest, authToken string) (articleApprovals *entity.ArticleApprovals, err error)
	Update(id uint, req request.ArticleApprovalsUpdateRequest) (err error)
	Delete(id uint) error
}

// NewArticleApprovalsService init ArticleApprovalsService
func NewArticleApprovalsService(repo repository.ArticleApprovalsRepository, log zerolog.Logger, usersRepo usersRepository.UsersRepository, articlesSvc articlesService.ArticlesService) ArticleApprovalsService {

	return &articleApprovalsService{
		Repo:            repo,
		Log:             log,
		UsersRepo:       usersRepo,
		ArticlesService: articlesSvc,
	}
}

// All implement interface of ArticleApprovalsService
func (_i *articleApprovalsService) All(req request.ArticleApprovalsQueryRequest) (articleApprovalss []*response.ArticleApprovalsResponse, paging paginator.Pagination, err error) {
	results, paging, err := _i.Repo.GetAll(req)
	if err != nil {
		return
	}

	for _, result := range results {
		articleApprovalss = append(articleApprovalss, mapper.ArticleApprovalsResponseMapper(result))
	}

	return
}

func (_i *articleApprovalsService) Show(id uint) (articleApprovals *response.ArticleApprovalsResponse, err error) {
	result, err := _i.Repo.FindOne(id)
	if err != nil {
		return nil, err
	}

	return mapper.ArticleApprovalsResponseMapper(result), nil
}

func (_i *articleApprovalsService) Save(clientId *uuid.UUID, req request.ArticleApprovalsCreateRequest, authToken string) (articleApprovals *entity.ArticleApprovals, err error) {
	_i.Log.Info().Interface("data", req).Msg("")

	newReq := req.ToEntity()

	createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
	newReq.ApprovalBy = createdBy.ID
	newReq.ApprovalAtLevel = &createdBy.UserLevel.LevelNumber

	approvalByUserLevelId := createdBy.UserLevelId
	approvalParentLevelId := createdBy.UserLevel.ParentLevelId

	err = _i.ArticlesService.UpdateApproval(authToken, newReq.ArticleId, newReq.StatusId, int(approvalByUserLevelId), *newReq.ApprovalAtLevel, *approvalParentLevelId)
	if err != nil {
		return nil, err
	}

	return _i.Repo.Create(newReq)
}

func (_i *articleApprovalsService) Update(id uint, req request.ArticleApprovalsUpdateRequest) (err error) {
	_i.Log.Info().Interface("data", req).Msg("")
	return _i.Repo.Update(id, req.ToEntity())
}

func (_i *articleApprovalsService) Delete(id uint) error {
	return _i.Repo.Delete(id)
}
