package ru.micord.ervu.account_applications.service.processor.impl;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import ru.micord.ervu.account_applications.dao.RecruitmentDao;
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.RecruitmentRecord;
import ru.micord.ervu.account_applications.model.RecruitmentData;
import ru.micord.ervu.account_applications.model.RecruitmentIpData;
import ru.micord.ervu.account_applications.model.ReferenceEntity;
import ru.micord.ervu.account_applications.service.processor.DataProcessor;


/**
 * @author Adel Kalimullin
 */
@Component
public class RecruitmentProcessor implements DataProcessor<RecruitmentData, RecruitmentRecord> {
  private final RecruitmentDao dao;
  private final RecruitmentSolutionProcessor recruitmentSolutionProcessor;
  private final RecruitmentIpProcessor recruitmentIpProcessor;

  public RecruitmentProcessor(RecruitmentDao dao,
      RecruitmentSolutionProcessor recruitmentSolutionProcessor,
      RecruitmentIpProcessor recruitmentIpProcessor) {
    this.dao = dao;
    this.recruitmentSolutionProcessor = recruitmentSolutionProcessor;
    this.recruitmentIpProcessor = recruitmentIpProcessor;
  }

  @Override
  public void upsertData(RecruitmentData data) {
    RecruitmentRecord recruitmentRecord = mapToRecord(data);
    if (!CollectionUtils.isEmpty(data.getSolutions())) {
      Set<String> solutionsIds = data.getSolutions().stream()
          .map(ReferenceEntity::getId)
          .collect(Collectors.toSet());

      recruitmentSolutionProcessor.upsertRecruitmentSolutions(data.getId(), solutionsIds);
    }
    if (!CollectionUtils.isEmpty(data.getIpAddresses())) {
      Set<String> incomingIps = data.getIpAddresses().stream()
          .map(RecruitmentIpData::getIpAddress)
          .collect(Collectors.toSet());

      recruitmentIpProcessor.upsertRecruitmentIpAddresses(data.getId(), incomingIps);
    }

    dao.upsertData(recruitmentRecord);
  }

  @Override
  public void changeActiveStatus(String id, boolean active) {
    dao.setActiveStatus(id, active);
  }

  @Override
  public Class<RecruitmentData> getType() {
    return RecruitmentData.class;
  }

  public RecruitmentRecord mapToRecord(RecruitmentData data) {
    Optional<UUID> idByIdmId = dao.getIdByIdmId(data.getId());
    Timestamp updatedAt = Timestamp.from(Instant.ofEpochMilli(data.getModified()));
    Timestamp createdAt = Timestamp.from(Instant.ofEpochMilli(data.getCreated()));
    RecruitmentRecord recruitmentRecord = dao.newRecord();
    recruitmentRecord.setIdmId(data.getId());
    recruitmentRecord.setVersion(data.getVersion());
    recruitmentRecord.setSchema(data.getType());
    recruitmentRecord.setShortname(data.getShortName());
    recruitmentRecord.setFullname(data.getFullName());
    recruitmentRecord.setName(data.getName());
    recruitmentRecord.setActive(data.isActive());
    recruitmentRecord.setTimezone(data.getTimeZone());
    recruitmentRecord.setReportsEnabled(data.isReportsEnabled());
    recruitmentRecord.setParentId(data.getParent() != null ? data.getParent().getId() : null);
    recruitmentRecord.setSubpoenaSeriesCode(data.getSubpoenaSeriesCode());
    recruitmentRecord.setAddressId(data.getAddressId());
    recruitmentRecord.setPostalAddressId(data.getPostalAddressId());
    recruitmentRecord.setRegionCode(data.getRegion() != null ? data.getRegion().getCode() : null);
    recruitmentRecord.setMilitaryCode(data.getMilitaryCode());
    recruitmentRecord.setCreatedAt(createdAt);
    recruitmentRecord.setUpdatedAt(updatedAt);
    recruitmentRecord.setTs(new Timestamp(System.currentTimeMillis()));
    idByIdmId.ifPresent(recruitmentRecord::setId);
    return recruitmentRecord;
  }
}
