package service

import (
	"errors"
	"log"
	"narasi-ahli-be/app/module/research_journals/mapper"
	"narasi-ahli-be/app/module/research_journals/repository"
	"narasi-ahli-be/app/module/research_journals/request"
	"narasi-ahli-be/app/module/research_journals/response"
	usersRepository "narasi-ahli-be/app/module/users/repository"
	"narasi-ahli-be/utils/paginator"
	utilSvc "narasi-ahli-be/utils/service"

	"github.com/rs/zerolog"
)

type researchJournalsService struct {
	Repo      repository.ResearchJournalsRepository
	UsersRepo usersRepository.UsersRepository
	Log       zerolog.Logger
}

type ResearchJournalsService interface {
	All(req request.ResearchJournalsQueryRequest) (researchJournals []*response.ResearchJournalsResponse, paging paginator.Pagination, err error)
	Show(authToken string, id uint) (researchJournal *response.ResearchJournalsResponse, err error)
	Save(authToken string, req request.ResearchJournalsCreateRequest) (researchJournal *response.ResearchJournalsResponse, err error)
	Update(authToken string, id uint, req request.ResearchJournalsUpdateRequest) (err error)
	Delete(authToken string, id uint) error
}

func NewResearchJournalsService(repo repository.ResearchJournalsRepository, usersRepo usersRepository.UsersRepository, log zerolog.Logger) ResearchJournalsService {
	return &researchJournalsService{
		Repo:      repo,
		UsersRepo: usersRepo,
		Log:       log,
	}
}

// func (_i *researchJournalsService) All(authToken string, req request.ResearchJournalsQueryRequest) (researchJournals []*response.ResearchJournalsResponse, paging paginator.Pagination, err error) {
// 	userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
// 	if userInfo == nil {
// 		return nil, paginator.Pagination{}, errors.New("unauthorized")
// 	}

// 	results, paging, err := _i.Repo.GetAll(userInfo.ID, req)
// 	if err != nil {
// 		return
// 	}

// 	for _, result := range results {
// 		researchJournals = append(researchJournals, mapper.ResearchJournalsResponseMapper(result))
// 	}

// 	return
// }

func (_i *researchJournalsService) All(req request.ResearchJournalsQueryRequest) (educationHistories []*response.ResearchJournalsResponse, paging paginator.Pagination, err error) {
	log.Println("USER ID:", req.UserID)

	results, paging, err := _i.Repo.GetAll(req.UserID, req)
	if err != nil {
		return
	}

	for _, result := range results {
		educationHistories = append(educationHistories, mapper.ResearchJournalsResponseMapper(result))
	}

	return
}

func (_i *researchJournalsService) Show(authToken string, id uint) (researchJournal *response.ResearchJournalsResponse, err error) {
	userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
	if userInfo == nil {
		return nil, errors.New("unauthorized")
	}

	result, err := _i.Repo.FindOneByUserAndId(userInfo.ID, id)
	if err != nil {
		return nil, err
	}

	return mapper.ResearchJournalsResponseMapper(result), nil
}

func (_i *researchJournalsService) Save(authToken string, req request.ResearchJournalsCreateRequest) (researchJournal *response.ResearchJournalsResponse, err error) {
	_i.Log.Info().Interface("data", req).Msg("Creating research journal")

	userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
	if userInfo == nil {
		return nil, errors.New("unauthorized")
	}

	entity := req.ToEntity()
	entity.UserID = userInfo.ID

	result, err := _i.Repo.Create(entity)
	if err != nil {
		return nil, err
	}

	return mapper.ResearchJournalsResponseMapper(result), nil
}

func (_i *researchJournalsService) Update(authToken string, id uint, req request.ResearchJournalsUpdateRequest) (err error) {
	_i.Log.Info().Interface("data", req).Msg("Updating research journal")

	userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
	if userInfo == nil {
		return errors.New("unauthorized")
	}

	// Check if record exists and belongs to user
	existing, err := _i.Repo.FindOneByUserAndId(userInfo.ID, id)
	if err != nil {
		return err
	}
	if existing == nil {
		return errors.New("research journal not found")
	}

	entity := req.ToEntity()
	return _i.Repo.Update(userInfo.ID, id, entity)
}

func (_i *researchJournalsService) Delete(authToken string, id uint) error {
	_i.Log.Info().Str("authToken", authToken).Uint("id", id).Msg("Deleting research journal")

	userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
	if userInfo == nil {
		return errors.New("unauthorized")
	}

	// Check if record exists and belongs to user
	existing, err := _i.Repo.FindOneByUserAndId(userInfo.ID, id)
	if err != nil {
		return err
	}
	if existing == nil {
		return errors.New("research journal not found")
	}

	return _i.Repo.Delete(userInfo.ID, id)
}
