package com.example.pb.controller;

import javax.ws.rs.core.MediaType;

import com.example.pb.dto.BankMapRequest;
import com.example.pb.domain.Person;
import com.example.pb.repository.PersonRepository;
import com.example.pb.service.CreditCardService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;package com.example.pb.controller;

import javax.ws.rs.core.MediaType;

import com.example.pb.dto.BankMapRequest;
import com.example.pb.domain.Person;
import com.example.pb.repository.PersonRepository;
import com.example.pb.service.CreditCardService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping(value = "/api/persons")
public class InefficientBanksController {

  @Autowired
  private PersonRepository repository;

  @Autowired
  private CreditCardService creditCardService;

  private static final Map<String, String> CARD_BANK = new HashMap<>();
  static {
    CARD_BANK.put("cc-visa-1", "Bank of Spring");
    CARD_BANK.put("cc-mc-1", "Reactive Credit Union");
  }

  @PostMapping(path = "/banks-inefficient",
               consumes = MediaType.APPLICATION_JSON,
               produces = MediaType.APPLICATION_JSON)
  public Map<String, List<String>> mapPersonToBanksInefficient(@RequestBody BankMapRequest req) {

    List<Person> persons = repository.findAllById(req.getPersonIds())
        .publishOn(Schedulers.parallel())
        .collectList()
        .block();

    List<String> allCards = new ArrayList<>();
    for (Person p : persons) {
      if (p.getCreditCardIds() != null) {
        allCards.addAll(p.getCreditCardIds());
      }
    }

    List<String> filtered = allCards.stream()
        .filter(id -> req.getCreditCardIds() != null && req.getCreditCardIds().contains(id))
        .collect(Collectors.toList());

    Set<String> toLookup = new HashSet<>(filtered);

    Map<String, List<String>> result = new LinkedHashMap<>();

    for (Person p : persons) {
      Map<String, String> card2bank =
          creditCardService.getBankNamesForCardIds(toLookup).block();

      List<String> copy = p.getCreditCardIds() == null
          ? new ArrayList<>()
          : new ArrayList<>(p.getCreditCardIds());
      copy.removeIf(id -> req.getCreditCardIds() == null || !req.getCreditCardIds().contains(id));

      List<String> banks = copy.stream()
          .map(card2bank::get)
          .collect(Collectors.toList());

      banks.removeIf(Objects::isNull);
      banks = new ArrayList<>(new LinkedHashSet<>(banks));

      result.put(p.getName(), banks);
    }

    return result;
  }
}


import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping(value = "/api/persons")
public class InefficientBanksController {

  @Autowired
  private PersonRepository repository;

  @Autowired
  private CreditCardService creditCardService;

  private static final Map<String, String> CARD_BANK = new HashMap<>();
  static {
    CARD_BANK.put("cc-visa-1", "Bank of Spring");
    CARD_BANK.put("cc-mc-1", "Reactive Credit Union");
  }

  @PostMapping(path = "/banks-inefficient",
               consumes = MediaType.APPLICATION_JSON,
               produces = MediaType.APPLICATION_JSON)
  public Map<String, List<String>> mapPersonToBanksInefficient(@RequestBody BankMapRequest req) {

    List<Person> persons = repository.findAllById(req.getPersonIds())
        .publishOn(Schedulers.parallel())
        .collectList()
        .block();

    List<String> allCards = new ArrayList<>();
    for (Person p : persons) {
      if (p.getCreditCardIds() != null) {
        allCards.addAll(p.getCreditCardIds());
      }
    }

    List<String> filtered = allCards.stream()
        .filter(id -> req.getCreditCardIds() != null && req.getCreditCardIds().contains(id))
        .collect(Collectors.toList());

    Set<String> toLookup = new HashSet<>(filtered);

    Map<String, List<String>> result = new LinkedHashMap<>();

    for (Person p : persons) {
      Map<String, String> card2bank =
          creditCardService.getBankNamesForCardIds(toLookup).block();

      List<String> copy = p.getCreditCardIds() == null
          ? new ArrayList<>()
          : new ArrayList<>(p.getCreditCardIds());
      copy.removeIf(id -> req.getCreditCardIds() == null || !req.getCreditCardIds().contains(id));

      List<String> banks = copy.stream()
          .map(card2bank::get)
          .collect(Collectors.toList());

      banks.removeIf(Objects::isNull);
      banks = new ArrayList<>(new LinkedHashSet<>(banks));

      result.put(p.getName(), banks);
    }

    return result;
  }
}
