package com.dev.registration.company.flow.search;

import static com.dev.registration.company.document.security.SecurityAll.OFFICER;

import com.dev.registration.company.data.CompanyEntity;
import com.dev.registration.company.data.dm.CompanySearchableDto;
import com.dev.registration.company.document.CompanyDocument;
import com.dev.registration.company.document.document.events.CompanySearchableDtoSearchEvent;
import com.dev.registration.company.mappers.CompanyMapper;
import java.util.ArrayList;
import java.util.Optional;

import com.strategyobject.sokit.extensions.core.context.SOContext;
import com.strategyobject.sokit.extensions.core.search.Pageable;
import com.strategyobject.sokit.extensions.document.api.annotations.DocumentAware;
import com.strategyobject.sokit.extensions.document.api.dm.DocumentMetadata;
import com.strategyobject.sokit.extensions.document.api.dm.DocumentSearchable;
import com.strategyobject.sokit.extensions.qdsl.QueryAst;

@DocumentAware(CompanyDocument.class)
public class DefaultSearchEvent implements CompanySearchableDtoSearchEvent {

  private final CompanyMapper mapper;

  public DefaultSearchEvent(CompanyMapper mapper) {
    this.mapper = mapper;
  }

  @Override
  public Optional<QueryAst> pre(SOContext ctx, Pageable pageable, Optional<QueryAst> filter) {
    final var currentSubject = ctx.identity().getSubject();
    final var isOfficer = ctx.identity().hasAnyRole(OFFICER);
    final var newFilter = filter.orElse(new QueryAst());

    newFilter.setStatements(new ArrayList<>(newFilter.getStatements()));
    newFilter.getStatements().forEach(s -> s.setExpressions(new ArrayList<>(s.getExpressions())));

    if (!isOfficer) {
      QueryAst.QueryExpression expression =
          QueryAst.QueryExpression.builder()
              .field(QueryAst.QueryExpression.QueryField.ofString("data.creatorSubject"))
              .operation(QueryAst.QueryExpression.QueryOperationType.EQ)
              .value(currentSubject)
              .build();
      newFilter.filterExpression(expression);
    }

    return Optional.of(newFilter);
  }

  @Override
  public CompanySearchableDto map(SOContext ctx, DocumentMetadata metadata, CompanyEntity entity) {
    // map the entity to a searchable dto
    return mapper.mapSearchable(entity);
  }

  @Override
  public void post(SOContext ctx, DocumentSearchable<CompanySearchableDto> searchable) {
    // you can modify the searchable object before returning it
    // useful for adding additional data or hiding sensitive information for certain users

  }
}
