package service

import (
	"context"
	"kra/internal/biz/system"

	"kra/internal/service/dto"
)

type DepartmentService struct{ uc *system.DepartmentUsecase }

func NewDepartmentService(uc *system.DepartmentUsecase) *DepartmentService {
	return &DepartmentService{uc: uc}
}

func departmentResponse(value *system.Department) *dto.DepartmentResponse {
	var children []*dto.DepartmentResponse
	if value.Children != nil {
		children = make([]*dto.DepartmentResponse, 0, len(value.Children))
		for _, child := range value.Children {
			children = append(children, departmentResponse(child))
		}
	}
	var leader any
	if value.Leader != nil {
		leader = convertUser(value.Leader)
	}
	return &dto.DepartmentResponse{ID: value.ID, CreatedAt: value.CreatedAt, UpdatedAt: value.UpdatedAt, DeletedAt: nil, Name: value.Name, ParentID: value.ParentID, Ancestors: value.Ancestors, Sort: value.Sort, LeaderID: value.LeaderID, Leader: leader, Status: value.Status, Children: children, NamePath: value.NamePath}
}

func departmentDomain(value *dto.DepartmentRequest) *system.Department {
	return &system.Department{ID: value.ID, Name: value.Name, ParentID: value.ParentID, Sort: value.Sort, LeaderID: value.LeaderID, Status: value.Status}
}

func (s *DepartmentService) Departments(ctx context.Context, name string) ([]*dto.DepartmentResponse, error) {
	items, err := s.uc.Departments(ctx, name)
	if err != nil {
		return nil, err
	}
	out := make([]*dto.DepartmentResponse, 0, len(items))
	for _, item := range items {
		out = append(out, departmentResponse(item))
	}
	return out, nil
}

func (s *DepartmentService) Create(ctx context.Context, req *dto.DepartmentRequest) error {
	return s.uc.CreateDepartment(ctx, departmentDomain(req))
}

func (s *DepartmentService) Update(ctx context.Context, req *dto.DepartmentRequest) error {
	return s.uc.UpdateDepartment(ctx, departmentDomain(req))
}

func (s *DepartmentService) Delete(ctx context.Context, id uint) error {
	return s.uc.DeleteDepartment(ctx, id)
}

func (s *DepartmentService) Department(ctx context.Context, id uint) (*dto.DepartmentResponse, error) {
	value, err := s.uc.Department(ctx, id)
	if err != nil {
		return nil, err
	}
	return departmentResponse(value), nil
}

func (s *DepartmentService) UserIDs(ctx context.Context, id uint) ([]uint, error) {
	return s.uc.DepartmentUserIDs(ctx, id)
}

func (s *DepartmentService) SetUsers(ctx context.Context, req *dto.SetDepartmentUsersRequest) error {
	return s.uc.SetDepartmentUsers(ctx, req.DepartmentID, req.UserIDs)
}

func (s *DepartmentService) SetUserDepartments(ctx context.Context, req *dto.SetUserDepartmentsRequest) error {
	return s.uc.SetUserDepartments(ctx, req.ID, req.DepartmentIDs, req.Primary)
}
