<?php

declare(strict_types=1);

namespace App\Command;

use App\Entity\Adherent;
use App\Entity\ExternalAdherentData;
use App\Entity\ExternalDataAgeGroup;
use App\Entity\ExternalDataCCMemberStatus;
use App\Entity\GlobalParameter;
use App\Utils\CustomEntityManager;
use App\Utils\TAVCotisationUtils;
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 Twig\Environment;
use Symfony\Component\Console\Input\InputArgument;

/**
 * This command is used to import data to complete external adherents data
 */
class ImportExternalAdherentData extends Command
{
    protected static $defaultName = 'kohinos:ssa:external-adherent-data-import';

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

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

    protected function configure()
    {
        $this
            ->setDescription('SSA : importer via CSV des informations externes non datées concernant les adhérents.')
            ->addArgument('filepath', InputArgument::OPTIONAL, 'Chemin du fichier csv contenant les données non datées.')
        ;
    }

    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 - importing external adherent data');

        $csvFilePath = $input->getArgument('filepath');

        //Prepare some tables if they do not exist yet
        if (!$this->em->getRepository(ExternalDataAgeGroup::class)->findAll()) {
            $one = new ExternalDataAgeGroup(1);
            $two = new ExternalDataAgeGroup(2);
            $three = new ExternalDataAgeGroup(3);
            $this->em->persist($one);
            $this->em->persist($two);
            $this->em->persist($three);
        }
        if (!$this->em->getRepository(ExternalDataCCMemberStatus::class)->findAll()) {
            $one = new ExternalDataCCMemberStatus(1);
            $two = new ExternalDataCCMemberStatus(2);
            $this->em->persist($one);
            $this->em->persist($two);
        }
        $this->em->flush();

        $ageGroups = [
            "1" => $this->em->getRepository(ExternalDataAgeGroup::class)->find(1),
            "2" => $this->em->getRepository(ExternalDataAgeGroup::class)->find(2),
            "3" => $this->em->getRepository(ExternalDataAgeGroup::class)->find(3)
        ];
        $ccStatus = [
            "1" => $this->em->getRepository(ExternalDataCCMemberStatus::class)->find(1),
            "2" => $this->em->getRepository(ExternalDataCCMemberStatus::class)->find(2)
        ];

        if (($handle = fopen($csvFilePath, "r")) !== FALSE) {
            while (($row = fgetcsv($handle, 1000, "\t")) !== FALSE) {
                if ($row[0] === 'mail') {
                    // headers row
                    continue;
                }

                try {
                    $adherent = $this->em->getRepository(Adherent::class)->findOneByEmail($row[0], false);
                } catch (\Exception $e) {
                    $this->io->warning('Adherent not found: ' . $row[0]);
                    continue;
                }

                $updated = false;

                $data = $this->em->getRepository(ExternalAdherentData::class)->findBy([
                    'adherent' => $adherent
                ]);

                if(!$data) {
                    $data = new ExternalAdherentData();
                    $data->setAdherent($adherent);
                    $updated = true;
                } else {
                    $data = $data[0];
                }

                #If a field is already stored in database, do not update it
                #If no data is provided in the file cell, do not fill (let it empty)
                if (!$data->getExternalDataAgeGroup() && $row[1] !== "") {
                    $data->setExternalDataAgeGroup($ageGroups[$row[1]]);
                    $updated = true;
                }
                if (!$data->getBirthYear() && $row[2] !== "") {
                    $data->setBirthYear(intval($row[2]));
                    $updated = true;
                }
                if (!$data->getAgeIncomeRatioGroup() && $row[3] !== "") {
                    $data->setAgeIncomeRatioGroup(intval($row[3]));
                    $updated = true;
                }
                if (!$data->getHouseholdIncomeRatioGroup() && $row[4] !== "") {
                    $data->setHouseholdIncomeRatioGroup(intval($row[4]));
                    $updated = true;
                }
                if (!$data->getExternalId() && $row[5] !== "") {
                    $data->setExternalId($row[5]);
                    $updated = true;
                }
                if (!$data->getCohort() && $row[6] !== "") {
                    $data->setCohort($row[6]);
                    $updated = true;
                }
                if(count($row) > 7) {
                    if (!$data->getExternalDataCCMemberStatus() && $row[7] !== "") {
                        $data->setExternalDataCCMemberStatus($ccStatus[$row[7]]);
                        $updated = true;
                    }
                }

                if ($updated) {
                    $this->em->persist($data);
                    $this->io->success('Succesfully updated: ' . $row[0]);
                } else {
                    $this->io->warning('No new data for Adherent: '
                        . $row[0] . ' (update ignored)');
                }
            }

            $this->em->flush();
            fclose($handle);
        }

        $this->io->success('End');

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

        return 0;
    }
}
