package service

import (
	"campaign-pool-be/app/database/entity"
	"campaign-pool-be/app/module/campaign_types/mapper"
	"campaign-pool-be/app/module/campaign_types/repository"
	"campaign-pool-be/app/module/campaign_types/request"
	"campaign-pool-be/app/module/campaign_types/response"
	usersRepository "campaign-pool-be/app/module/users/repository"
	config "campaign-pool-be/config/config"
	"campaign-pool-be/utils/paginator"
	utilSvc "campaign-pool-be/utils/service"

	"github.com/rs/zerolog"
)

// CampaignTypesService
type campaignTypesService struct {
	Repo      repository.CampaignTypesRepository
	UsersRepo usersRepository.UsersRepository
	Log       zerolog.Logger
	Cfg       *config.Config
}

// CampaignTypesService define interface of ICampaignTypesService
type CampaignTypesService interface {
	All(req request.CampaignTypesQueryRequest, authToken string) (campaignTypes []*response.CampaignTypesResponse, paging paginator.Pagination, err error)
	Show(id uint) (campaignTypes *response.CampaignTypesResponse, err error)
	Save(req request.CampaignTypesCreateRequest, authToken string) (campaignTypes *entity.CampaignTypes, err error)
	Update(id uint, req request.CampaignTypesUpdateRequest) (err error)
	Delete(id uint) error
}

// NewCampaignTypesService init CampaignTypesService
func NewCampaignTypesService(repo repository.CampaignTypesRepository, usersRepo usersRepository.UsersRepository, log zerolog.Logger, cfg *config.Config) CampaignTypesService {
	return &campaignTypesService{
		Repo:      repo,
		UsersRepo: usersRepo,
		Log:       log,
		Cfg:       cfg,
	}
}

// All implement interface of CampaignTypesService
func (_i *campaignTypesService) All(req request.CampaignTypesQueryRequest, authToken string) (campaignTypess []*response.CampaignTypesResponse, paging paginator.Pagination, err error) {
	results, paging, err := _i.Repo.GetAll(req)
	if err != nil {
		return
	}

	for _, result := range results {
		campaignTypess = append(campaignTypess, mapper.CampaignTypesResponseMapper(result))
	}

	return
}

func (_i *campaignTypesService) Show(id uint) (campaignTypes *response.CampaignTypesResponse, err error) {
	result, err := _i.Repo.FindOne(id)
	if err != nil {
		return nil, err
	}
	return mapper.CampaignTypesResponseMapper(result), nil
}

func (_i *campaignTypesService) Save(req request.CampaignTypesCreateRequest, authToken string) (campaignTypes *entity.CampaignTypes, err error) {
	_i.Log.Info().Interface("data", req).Msg("")
	newReq := req.ToEntity()

	if req.CreatedById != nil {
		createdBy, err := _i.UsersRepo.FindOne(*req.CreatedById)
		if err != nil {
			return nil, err
		}
		newReq.CreatedAt = createdBy.CreatedAt
	} else {
		createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
		if createdBy != nil {
			// User info available if needed
		}
	}

	return _i.Repo.Create(newReq)
}

func (_i *campaignTypesService) Update(id uint, req request.CampaignTypesUpdateRequest) (err error) {
	_i.Log.Info().Interface("data", req).Msg("")

	newReq := req.ToEntity()
	return _i.Repo.Update(id, newReq)
}

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

