<?php

declare(strict_types=1);

namespace App\Command;

use App\Entity\Adherent;
use App\Entity\Flux;
use App\Entity\Allocation;
use App\Utils\CustomEntityManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\InputOption;

/**
 * This command is used to create Allocation instances for existing Flux,
 * in order to be used in an external context
 */
class CreateAllocationsFromExistingFlux extends Command
{
    protected static $defaultName = 'kohinos:ssa:create-allocations-from-existing-flux';

    protected $em;
    protected $io;
    protected $param;

    public function __construct(CustomEntityManager $em) {
        $this->em = $em;
        parent::__construct();
    }

    protected function configure()
    {
        $this
            ->setDescription('SSA : créer les instances d\'allocations à partir des flux de cotisation existantes')
            ->addOption(
                'batchamount',
                null,
                InputOption::VALUE_REQUIRED,
                "Nombre de cotisations à traiter lors de cette opération"
            );
        ;
    }

    private function readCsv() {

    }

    /**
     * @param InputInterface  $input
     * @param OutputInterface $output
     *
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->io = new SymfonyStyle($input, $output);

        $this->io->title('START - creating allocations');

        // get batch amount param
        $batchAmount = $input->hasOption('batchamount') ? $input->getOption('batchamount') : null;

        // get cotisations that don't have an allocation set
        $fluxRepository = $this->em->getRepository(Flux::class);
        $cotisations = $fluxRepository->getTavCotisationsWithoutAllocation($batchAmount);

        $processedComplementaryFluxIds = [];
        $count = 0;
        foreach ($cotisations as $key => $cotis) {
            // $this->io->success(json_encode($cotis));

            // create allocation
            $allocation = new Allocation();
            $allocation->setCotisationFlux($fluxRepository->find($cotis["id"]));

            // set adherent
            if ($cotis["adherent_id"] !== null) {
                $adherent_id = $cotis["adherent_id"];
            } else {
                $adherent_id = $cotis["adherent_dest_id"];
            }
            $allocation->setAdherent($this->em->getRepository(Adherent::class)->find($adherent_id));            

            $amount = floatval($cotis["montant"]);

            /**
             * An error can have occured with online payment leading to a payment being processed twice.
             * In this case, two flux with a complementary flux for each of them have been created at the same time.
             * Then, getRelatedTavAllocationFlux() will return multiple results, so we need not to process the same flux twice.
             * 
             * So we look for a complementary flux that exists and that's not been processed before
             */
            $complementaryFlux = null;
            $possibleComplementaryFlux = $fluxRepository->getRelatedTavAllocationFlux($cotis["id"]);
            foreach($possibleComplementaryFlux as $f) {
                if ($f["id"] !== null && array_search($f["id"], $processedComplementaryFluxIds) === false)  {
                    $complementaryFlux = $f;
                    break;
                }
            }

            if ($complementaryFlux !== null) {
                $allocation->setComplementaryFlux($fluxRepository->find($complementaryFlux["id"]));

                // mark as processed
                $processedComplementaryFluxIds[] = $complementaryFlux["id"];

                // if there is a complementary flux, add or subsctract amount to get full allocation amount
                if ($complementaryFlux["type"] == "reversement_cotisation_adherent") {
                    $amount += floatval($complementaryFlux["montant"]);
                } else if ($complementaryFlux["type"] == "prelevement_cotisation_adherent") {
                    $amount -= floatval($complementaryFlux["montant"]);
                }
            }

            $allocation->setAmount($amount);
            $this->em->persist($allocation);

            $count += 1;
        }

        $this->em->flush();

        $this->io->success("End, created {$count} allocations");

        $memoryUsage = memory_get_usage(true) / 1024 / 1024;
        $this->io->text("Batch finished with memory: ${memoryUsage}M");

        return 0;
    }
}
