package service

import (
	"errors"
	usersRepository "narasi-ahli-be/app/module/users/repository"
	"narasi-ahli-be/app/module/work_history/mapper"
	"narasi-ahli-be/app/module/work_history/repository"
	"narasi-ahli-be/app/module/work_history/request"
	"narasi-ahli-be/app/module/work_history/response"
	"narasi-ahli-be/utils/paginator"

	"github.com/rs/zerolog"
)

type workHistoryService struct {
	Repo      repository.WorkHistoryRepository
	UsersRepo usersRepository.UsersRepository
	Log       zerolog.Logger
}

type WorkHistoryService interface {
	All(req request.WorkHistoryQueryRequest) (workHistories []*response.WorkHistoryResponse, paging paginator.Pagination, err error)
	Show(userId uint, id uint) (workHistory *response.WorkHistoryResponse, err error)
	Save(userId uint, req request.WorkHistoryCreateRequest) (workHistory *response.WorkHistoryResponse, err error)
	Update(userId uint, id uint, req request.WorkHistoryUpdateRequest) (err error)
	Delete(userId uint, id uint) error
}

func NewWorkHistoryService(repo repository.WorkHistoryRepository, usersRepo usersRepository.UsersRepository, log zerolog.Logger) WorkHistoryService {
	return &workHistoryService{
		Repo:      repo,
		UsersRepo: usersRepo,
		Log:       log,
	}
}

func (_i *workHistoryService) All(req request.WorkHistoryQueryRequest) (workHistories []*response.WorkHistoryResponse, paging paginator.Pagination, err error) {
	results, paging, err := _i.Repo.GetAll(req.UserID, req)
	if err != nil {
		return
	}

	for _, result := range results {
		workHistories = append(workHistories, mapper.WorkHistoryResponseMapper(result))
	}

	return
}

func (_i *workHistoryService) Show(userId uint, id uint) (workHistory *response.WorkHistoryResponse, err error) {
	result, err := _i.Repo.FindOneByUserAndId(userId, id)
	if err != nil {
		return nil, err
	}

	return mapper.WorkHistoryResponseMapper(result), nil
}

func (_i *workHistoryService) Save(userId uint, req request.WorkHistoryCreateRequest) (workHistory *response.WorkHistoryResponse, err error) {
	_i.Log.Info().Interface("data", req).Msg("Creating work history")

	// Validate business rules
	if req.EndDate != nil && req.EndDate.Before(req.StartDate) {
		return nil, errors.New("end date cannot be before start date")
	}

	entity := req.ToEntity(userId)

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

	return mapper.WorkHistoryResponseMapper(result), nil
}

func (_i *workHistoryService) Update(userId uint, id uint, req request.WorkHistoryUpdateRequest) (err error) {
	_i.Log.Info().Interface("data", req).Msg("Updating work history")

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

	// Validate business rules
	if req.EndDate != nil && req.EndDate.Before(req.StartDate) {
		return errors.New("end date cannot be before start date")
	}

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

func (_i *workHistoryService) Delete(userId uint, id uint) error {
	_i.Log.Info().Uint("userId", userId).Uint("id", id).Msg("Deleting work history")

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

	return _i.Repo.Delete(userId, id)
}
