package episodeofcare

import (
	"context"
	"net/url"
	"service/internal/interfaces/satusehat"
	"service/pkg/errors"
)

// Service mendefinisikan kontrak untuk logika bisnis EpisodeOfCare.
type Service interface {
	Create(ctx context.Context, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error)
	Update(ctx context.Context, id string, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error)
	Patch(ctx context.Context, id string, req EpisodeOfCarePatchRequest) (*satusehat.FHIRResponse, error)
	GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error)
	Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error)
}

type service struct {
	repo Repository
}

// NewService membuat service EpisodeOfCare baru.
func NewService(repo Repository) Service {
	return &service{repo: repo}
}

func (s *service) Create(ctx context.Context, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error) {
	fhirPayload := MapRequestToFHIR(req)
	return s.repo.Create(ctx, fhirPayload)
}

func (s *service) Update(ctx context.Context, id string, req EpisodeOfCareRequest) (*satusehat.FHIRResponse, error) {
	if id == "" {
		return nil, errors.NewValidationError().Message("EpisodeOfCare ID is required").Build()
	}

	fhirPayload := MapRequestToFHIR(req)
	fhirPayload.Set("id", id)

	return s.repo.Update(ctx, id, fhirPayload)
}

func (s *service) Patch(ctx context.Context, id string, req EpisodeOfCarePatchRequest) (*satusehat.FHIRResponse, error) {
	if id == "" {
		return nil, errors.NewValidationError().Message("EpisodeOfCare ID is required").Build()
	}
	if len(req) == 0 {
		return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build()
	}
	return s.repo.Patch(ctx, id, req)
}

func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) {
	if id == "" {
		return nil, errors.NewValidationError().Message("EpisodeOfCare ID is required").Build()
	}
	return s.repo.GetByID(ctx, id)
}

func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) {
	return s.repo.Search(ctx, queryParams)
}
