package ru.micord.ervu.converter;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import ru.micord.ervu.dto.Restriction;
import ru.micord.ervu.dto.SubpoenaResponseDto;
import org.springframework.stereotype.Component;
import proto.ervu.rp.summons.MeasuresTemporary;
import proto.ervu.rp.summons.ResponseDataAddress;
import proto.ervu.rp.summons.SummonsInfo;
import proto.ervu.rp.summons.SummonsResponseData;

import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
import static java.util.Objects.requireNonNull;
import static ru.micord.ervu.util.DateUtil.convertToString;
import static ru.micord.ervu.util.DateUtil.getDaysTill;

/**
 * @author gulnaz
 */
@Component
public class SummonsResponseDataConverter {

  private static final String RESIDENCE_ADDRESS_CODE = "_1";
  private static final String STAY_ADDRESS_CODE = "_2";
  private static final String ACTUAL_ADDRESS_CODE = "_3";

  public SubpoenaResponseDto convert(SummonsResponseData responseData) {
    SubpoenaResponseDto.Builder builder = new SubpoenaResponseDto.Builder()
        .personName(responseData.getFirstName(), responseData.getMiddleName(),
            responseData.getLastName()
        )
        .birthDate(responseData.getBirthDate())
        .docType(responseData.getType())
        .docNumber(responseData.getSeries(), responseData.getNumber())
        .issueDate(responseData.getIssueDate())
        .issueOrg(responseData.getIssueOrg())
        .issueIdCode(responseData.getIssueIdCode())
        .residenceAddress(getAddressByCode(responseData.getAddressesList(), RESIDENCE_ADDRESS_CODE))
        .stayAddress(getAddressByCode(responseData.getAddressesList(), STAY_ADDRESS_CODE))
        .actualAddress(getAddressByCode(responseData.getAddressesList(), ACTUAL_ADDRESS_CODE));
    Optional<SummonsInfo> summonsInfoOpt = responseData.getSummonsInfosList().stream()
        // get last subpoena
        .max(Comparator.comparing(
            s -> requireNonNull(convertToLocalDate(s.getPlacementDateSummons()))));

    if (summonsInfoOpt.isPresent()) {
      SummonsInfo summonsInfo = summonsInfoOpt.get();
      String estimatedDate = summonsInfo.getEstimatedDateSummons();

      builder.seriesAndNumber(summonsInfo.getSummonsSeries(), summonsInfo.getSummonsNumber())
          .visitDateTime(summonsInfo.getVisitDate(), summonsInfo.getVisitTime())
          .militaryCommissariatName(summonsInfo.getMilitaryCommissariatName())
          .militaryCommissariatAddress(summonsInfo.getMilitaryCommissariatAddress())
          .militaryCommissar(summonsInfo.getMilitaryComissar(),
              summonsInfo.getMilitaryComissarFirstName(),
              summonsInfo.getMilitaryComissarMiddleName()
          )
          .placementDateSummons(summonsInfo.getPlacementDateSummons())
          .reasonName(summonsInfo.getReasonName())
          .summonsStatusName(summonsInfo.getSummonsStatusName())
          .deliveryTypeSummonsName(summonsInfo.getDeliveryTypeSummonsName())
          .estimatedDateSummons(estimatedDate)
          .recruitmentStatusCode(
              Integer.parseInt(responseData.getRecruitmentInfo().getRecruitmentStatusCode()))
          .recruitmentStartDate(responseData.getRecruitmentInfo().getRecruitmentStart())
          .daysToAppearance(getDaysTill(convertToLocalDate(estimatedDate)));

      List<Restriction> restrictions = new ArrayList<>();
      summonsInfo.getMeasuresTemporaryPackagesList().forEach(
          measuresTemporaryPackage -> measuresTemporaryPackage.getMeasuresTemporariesList()
              .forEach(measuresTemporary ->
                  restrictions.add(new Restriction(measuresTemporary.getMeasureName(),
                      convertToString(convertToLocalDate(measuresTemporary.getStartDate()))))
              ));

      if (!restrictions.isEmpty()) {
        builder.addRestrictions(restrictions);
        Restriction firstRestriction = restrictions.get(0);
        builder.firstRestrictionName(firstRestriction.name());
        builder.firstRestrictionStartDate(firstRestriction.startDate());
      }
      builder.otherRestrictionCount(restrictions.size() - 1);
    }
    return builder.build();
  }

  private String getAddressByCode(List<ResponseDataAddress> addresses, String code) {
    return addresses.stream()
        .filter(responseDataAddress -> responseDataAddress.getAddressCode().equals(code))
        .findFirst()
        .map(ResponseDataAddress::getAddressReg)
        .orElse("");
  }
}
