package service

import (
	"context"

	"eslogad-be/internal/contract"
	"eslogad-be/internal/entities"
	"eslogad-be/internal/repository"
	"eslogad-be/internal/transformer"

	"github.com/google/uuid"
)

type MasterServiceImpl struct {
	labelRepo       *repository.LabelRepository
	priorityRepo    *repository.PriorityRepository
	institutionRepo *repository.InstitutionRepository
	dispRepo        *repository.DispositionActionRepository
}

func NewMasterService(label *repository.LabelRepository, priority *repository.PriorityRepository, institution *repository.InstitutionRepository, disp *repository.DispositionActionRepository) *MasterServiceImpl {
	return &MasterServiceImpl{labelRepo: label, priorityRepo: priority, institutionRepo: institution, dispRepo: disp}
}

// Labels
func (s *MasterServiceImpl) CreateLabel(ctx context.Context, req *contract.CreateLabelRequest) (*contract.LabelResponse, error) {
	entity := &entities.Label{Name: req.Name, Color: req.Color}
	if err := s.labelRepo.Create(ctx, entity); err != nil {
		return nil, err
	}
	resp := transformer.LabelsToContract([]entities.Label{*entity})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) UpdateLabel(ctx context.Context, id uuid.UUID, req *contract.UpdateLabelRequest) (*contract.LabelResponse, error) {
	entity := &entities.Label{ID: id}
	if req.Name != nil {
		entity.Name = *req.Name
	}
	if req.Color != nil {
		entity.Color = req.Color
	}
	if err := s.labelRepo.Update(ctx, entity); err != nil {
		return nil, err
	}
	e, err := s.labelRepo.Get(ctx, id)
	if err != nil {
		return nil, err
	}
	resp := transformer.LabelsToContract([]entities.Label{*e})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) DeleteLabel(ctx context.Context, id uuid.UUID) error {
	return s.labelRepo.Delete(ctx, id)
}
func (s *MasterServiceImpl) ListLabels(ctx context.Context) (*contract.ListLabelsResponse, error) {
	list, err := s.labelRepo.List(ctx)
	if err != nil {
		return nil, err
	}
	return &contract.ListLabelsResponse{Labels: transformer.LabelsToContract(list)}, nil
}

// Priorities
func (s *MasterServiceImpl) CreatePriority(ctx context.Context, req *contract.CreatePriorityRequest) (*contract.PriorityResponse, error) {
	entity := &entities.Priority{Name: req.Name, Level: req.Level}
	if err := s.priorityRepo.Create(ctx, entity); err != nil {
		return nil, err
	}
	resp := transformer.PrioritiesToContract([]entities.Priority{*entity})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) UpdatePriority(ctx context.Context, id uuid.UUID, req *contract.UpdatePriorityRequest) (*contract.PriorityResponse, error) {
	entity := &entities.Priority{ID: id}
	if req.Name != nil {
		entity.Name = *req.Name
	}
	if req.Level != nil {
		entity.Level = *req.Level
	}
	if err := s.priorityRepo.Update(ctx, entity); err != nil {
		return nil, err
	}
	e, err := s.priorityRepo.Get(ctx, id)
	if err != nil {
		return nil, err
	}
	resp := transformer.PrioritiesToContract([]entities.Priority{*e})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) DeletePriority(ctx context.Context, id uuid.UUID) error {
	return s.priorityRepo.Delete(ctx, id)
}
func (s *MasterServiceImpl) ListPriorities(ctx context.Context) (*contract.ListPrioritiesResponse, error) {
	list, err := s.priorityRepo.List(ctx)
	if err != nil {
		return nil, err
	}
	return &contract.ListPrioritiesResponse{Priorities: transformer.PrioritiesToContract(list)}, nil
}

// Institutions
func (s *MasterServiceImpl) CreateInstitution(ctx context.Context, req *contract.CreateInstitutionRequest) (*contract.InstitutionResponse, error) {
	entity := &entities.Institution{Name: req.Name, Type: entities.InstitutionType(req.Type), Address: req.Address, ContactPerson: req.ContactPerson, Phone: req.Phone, Email: req.Email}
	if err := s.institutionRepo.Create(ctx, entity); err != nil {
		return nil, err
	}
	resp := transformer.InstitutionsToContract([]entities.Institution{*entity})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) UpdateInstitution(ctx context.Context, id uuid.UUID, req *contract.UpdateInstitutionRequest) (*contract.InstitutionResponse, error) {
	entity := &entities.Institution{ID: id}
	if req.Name != nil {
		entity.Name = *req.Name
	}
	if req.Type != nil {
		entity.Type = entities.InstitutionType(*req.Type)
	}
	if req.Address != nil {
		entity.Address = req.Address
	}
	if req.ContactPerson != nil {
		entity.ContactPerson = req.ContactPerson
	}
	if req.Phone != nil {
		entity.Phone = req.Phone
	}
	if req.Email != nil {
		entity.Email = req.Email
	}
	if err := s.institutionRepo.Update(ctx, entity); err != nil {
		return nil, err
	}
	e, err := s.institutionRepo.Get(ctx, id)
	if err != nil {
		return nil, err
	}
	resp := transformer.InstitutionsToContract([]entities.Institution{*e})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) DeleteInstitution(ctx context.Context, id uuid.UUID) error {
	return s.institutionRepo.Delete(ctx, id)
}
func (s *MasterServiceImpl) ListInstitutions(ctx context.Context, req *contract.ListInstitutionsRequest) (*contract.ListInstitutionsResponse, error) {
	list, err := s.institutionRepo.ListWithSearch(ctx, req.Search)
	if err != nil {
		return nil, err
	}
	return &contract.ListInstitutionsResponse{Institutions: transformer.InstitutionsToContract(list)}, nil
}

// Disposition Actions
func (s *MasterServiceImpl) CreateDispositionAction(ctx context.Context, req *contract.CreateDispositionActionRequest) (*contract.DispositionActionResponse, error) {
	entity := &entities.DispositionAction{Code: req.Code, Label: req.Label, Description: req.Description}
	if req.RequiresNote != nil {
		entity.RequiresNote = *req.RequiresNote
	}
	if req.GroupName != nil {
		entity.GroupName = req.GroupName
	}
	if req.SortOrder != nil {
		entity.SortOrder = req.SortOrder
	}
	if req.IsActive != nil {
		entity.IsActive = *req.IsActive
	}
	if err := s.dispRepo.Create(ctx, entity); err != nil {
		return nil, err
	}
	resp := transformer.DispositionActionsToContract([]entities.DispositionAction{*entity})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) UpdateDispositionAction(ctx context.Context, id uuid.UUID, req *contract.UpdateDispositionActionRequest) (*contract.DispositionActionResponse, error) {
	entity := &entities.DispositionAction{ID: id}
	if req.Code != nil {
		entity.Code = *req.Code
	}
	if req.Label != nil {
		entity.Label = *req.Label
	}
	if req.Description != nil {
		entity.Description = req.Description
	}
	if req.RequiresNote != nil {
		entity.RequiresNote = *req.RequiresNote
	}
	if req.GroupName != nil {
		entity.GroupName = req.GroupName
	}
	if req.SortOrder != nil {
		entity.SortOrder = req.SortOrder
	}
	if req.IsActive != nil {
		entity.IsActive = *req.IsActive
	}
	if err := s.dispRepo.Update(ctx, entity); err != nil {
		return nil, err
	}
	e, err := s.dispRepo.Get(ctx, id)
	if err != nil {
		return nil, err
	}
	resp := transformer.DispositionActionsToContract([]entities.DispositionAction{*e})[0]
	return &resp, nil
}
func (s *MasterServiceImpl) DeleteDispositionAction(ctx context.Context, id uuid.UUID) error {
	return s.dispRepo.Delete(ctx, id)
}
func (s *MasterServiceImpl) ListDispositionActions(ctx context.Context) (*contract.ListDispositionActionsResponse, error) {
	list, err := s.dispRepo.List(ctx)
	if err != nil {
		return nil, err
	}
	return &contract.ListDispositionActionsResponse{Actions: transformer.DispositionActionsToContract(list)}, nil
}
