TeamExportService.java

package no.nav.data.team.team;

import no.nav.data.common.export.ExcelBuilder;
import no.nav.data.common.utils.DateUtil;
import no.nav.data.team.cluster.ClusterService;
import no.nav.data.team.cluster.domain.Cluster;
import no.nav.data.team.member.dto.MemberResponse;
import no.nav.data.team.po.ProductAreaService;
import no.nav.data.team.po.domain.ProductArea;
import no.nav.data.team.resource.NomClient;
import no.nav.data.team.resource.domain.ResourceType;
import no.nav.data.team.shared.Lang;
import no.nav.data.team.team.domain.OfficeHours;
import no.nav.data.team.team.domain.Team;
import no.nav.data.team.team.domain.TeamMember;
import no.nav.data.team.team.domain.Role;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.lang.String.join;
import static java.util.Optional.ofNullable;
import static no.nav.data.common.utils.StreamUtils.convert;
import static no.nav.data.common.utils.StreamUtils.filter;
import static no.nav.data.common.utils.StreamUtils.nullToEmptyList;
import static no.nav.data.common.utils.StreamUtils.safeStream;

@Service
public class TeamExportService {

    public enum SpreadsheetType {
        ALL,
        CLUSTER,
        AREA
    }

    private final TeamService teamService;
    private final ProductAreaService productAreaService;
    private final ClusterService clusterService;
    private final NomClient nomClient = NomClient.getInstance();

    public TeamExportService(TeamService teamService, ProductAreaService productAreaService, ClusterService clusterService) {
        this.teamService = teamService;
        this.productAreaService = productAreaService;
        this.clusterService = clusterService;
    }

    public byte[] generate(SpreadsheetType type, String filter) {
        UUID filterUuid = toUUID(filter);
        var domainPaMap = productAreaService.getAll().stream().collect(Collectors.toMap(ProductArea::getId, Function.identity()));
        var domainClusterMap = clusterService.getAll().stream().collect(Collectors.toMap(Cluster::getId, Function.identity()));
        var domainTeams = switch (type) {
            case ALL -> teamService.getAll();
            case CLUSTER -> teamService.findByCluster(filterUuid);
            case AREA -> teamService.findByProductArea(filterUuid);
        };

        var teams = convert(domainTeams, t -> new TeamInfo(t, domainPaMap.get(t.getProductAreaId()), convert(t.getClusterIds(), domainClusterMap::get)));

        return generate(teams);
    }

    private byte[] generate(List<TeamInfo> teams) {
        var doc = new ExcelBuilder("Teams");

        doc.addRow()
                .addCell(Lang.TEAM_ID)
                .addCell(Lang.NAME)
                .addCell(Lang.TEAM_LEADS)
                .addCell(Lang.TEAM_TYPE)
                .addCell(Lang.AREA_NOM_ID)
                .addCell(Lang.AREA_ID)
                .addCell(Lang.AREA)
                .addCell(Lang.CLUSTER)
                .addCell(Lang.STATUS)
                .addCell(Lang.QA_DONE)
                .addCell(Lang.NAIS_TEAMS)
                .addCell(Lang.TAGS)
                .addCell(Lang.MEMBERS)
                .addCell(Lang.INTERNAL)
                .addCell(Lang.EXTERNAL)
                .addCell(Lang.SLACK)

                .addCell((Lang.CONTACT_PERSON))
                .addCell(Lang.LOCATION)
                .addCell(Lang.OFFICE_HOURS)

                .addCell(Lang.DESCRIPTION)
        ;

        teams.sort(Comparator.comparing(t -> t.team().getName()));
        teams.forEach(t -> add(doc, t));

        return doc.build();
    }

    private void add(ExcelBuilder doc, TeamInfo teamInfo) {
        var team = teamInfo.team();
        var members = convert(team.getMembers(), TeamMember::convertToResponse);


        doc.addRow()
                .addCell(team.getId().toString())
                .addCell(team.getName())
                .addCell(names(members, Role.LEAD))
                .addCell(Lang.teamType(team.getTeamType()))
                .addCell(ofNullable(teamInfo.productArea()).map(ProductArea::getNomId).orElse(""))
                .addCell(ofNullable(team.getProductAreaId()).map(UUID::toString).orElse(""))
                .addCell(ofNullable(teamInfo.productArea()).map(ProductArea::getName).orElse(""))
                .addCell(safeStream(teamInfo.clusters()).map(Cluster::getName).collect(Collectors.joining(", ")))
                .addCell(team.getStatus().toString())
                .addCell(DateUtil.formatDateTimeHumanReadable(team.getQaTime()))
                .addCell(join(", ", nullToEmptyList(team.getNaisTeams())))
                .addCell(join(", ", nullToEmptyList(team.getTags())))
                .addCell(members.size())
                .addCell(filter(members, m -> m.getResource().getResourceType() == ResourceType.INTERNAL).size())
                .addCell(filter(members, m -> m.getResource().getResourceType() == ResourceType.EXTERNAL).size())
                .addCell(team.getSlackChannel())
                .addCell(contactPerson(team.getContactPersonIdent()))
                .addCell(location(team.getOfficeHours()))
                .addCell(officeHours(team.getOfficeHours()))
                .addCell(team.getDescription())


        ;
    }

    private String names(List<MemberResponse> members, Role role) {
        return filter(members, m -> m.getRoles().contains(role)).stream()
                .map(MemberResponse::getResource).map(r -> r.getFamilyName() + ", " + r.getGivenName()).collect(Collectors.joining(" - "));
    }

    private String contactPerson(String ident ) {
        if(ident == null){
            return "";
        }
        var nameOptional = nomClient.getNameForIdent(ident);

        if(nameOptional.isPresent()){
            var stringName = nameOptional.get();
            var splitName = stringName.split(" ");
            return splitName[splitName.length-1] + ", " + String.join(" ", Arrays.copyOf(splitName, splitName.length-1));
        }
        return "";
    }

    private String location(OfficeHours officeHours){
        if(officeHours == null){
            return "";
        }

        return officeHours.getLocationCode();
    }

    private String officeHours(OfficeHours officeHours){
        if(officeHours == null){
            return "";
        }

        var days = officeHours.getDays().toString();

        // Removing the "[" at the start of the variable and the "]" at the end of the variable
        days = days.substring(1, days.length() - 1);

        return days;
    }

    record TeamInfo(Team team, ProductArea productArea, List<Cluster> clusters) {

    }

    private UUID toUUID(String uuid) {
        return uuid == null ? null : UUID.fromString(uuid);
    }
}