<?php

namespace App\Command;

use App\Entity\User;
use App\Entity\Group;
use App\Entity\Rank;
use Doctrine\ORM\Query;
use App\Repository\GroupRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

#[AsCommand(name: 'vision:adduser', description: 'Add a user to vision')]
class AddUserCommand extends Command
{
    private EntityManagerInterface $entityManager;
    private ParameterBagInterface $params;

    public function __construct(EntityManagerInterface $entityManager, ParameterBagInterface $params)
    {
        parent::__construct();

        $this->entityManager = $entityManager;
        $this->params = $params;
    }

    protected function configure(): void
    {
        $this
            ->addArgument('email', InputArgument::OPTIONAL, 'Email of the user')
            ->addArgument('firstname', InputArgument::OPTIONAL, 'Firstname of the user')
            ->addArgument('lastname', InputArgument::OPTIONAL, 'Lastname of the user')
            ->addArgument('groupid', InputArgument::OPTIONAL, 'Id of the main group of the user')
            ->addArgument('rankid', InputArgument::OPTIONAL, 'Id of user\'s main rank (need to be part of group)')
            ->addArgument('isadmin', InputArgument::OPTIONAL, 'is the user an admin ? (yes/no)')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $helper = $this->getHelper('question');

        $email = $input->getArgument('email');
        //todo: check if the mail is ok
        if (!$email) {
            $questionEmail = new Question('Please enter the user\'s email : ', '');
            $questionEmail->setValidator(function ($answer) {
                if (!is_string($answer) || empty($answer)) {
                    throw new \RuntimeException(
                        'The email c\'ant be empty'
                    );
                }

                return $answer;
            });
            $email = $helper->ask($input, $output, $questionEmail);
        }

        $firstname = $input->getArgument('firstname');

        if (!$firstname) {
            $questionFirstname = new Question('Please enter the user\'s firstname : ', '');
            $questionFirstname->setValidator(function ($answer) {
                if (!is_string($answer) || empty($answer)) {
                    throw new \RuntimeException(
                        'The firstname c\'ant be empty'
                    );
                }

                return $answer;
            });
            $firstname = $helper->ask($input, $output, $questionFirstname);
        }

        $lastname = $input->getArgument('lastname');

        if (!$lastname) {
            $questionLastname = new Question('Please enter the user\'s lastname : ', '');
            $questionLastname->setValidator(function ($answer) {
                if (!is_string($answer) || empty($answer)) {
                    throw new \RuntimeException(
                        'The lastname c\'ant be empty'
                    );
                }

                return $answer;
            });
            $lastname = $helper->ask($input, $output, $questionLastname);
        }

        //GROUP

        $groupid = $input->getArgument('groupid');
        /**
         * @var GroupRepository $groupRepository
         */
        $groupRepository = $this->entityManager->getRepository(Group::class);

        if ($groupid && null === $groupRepository->find($groupid)) {
            $groupid = '';
        }

        if (!$groupid) {
            foreach ($groupRepository->findAll() as $key => $g) {
                $gList[$g->getId()] = $g->getName();
            }


            $questionGroup = new ChoiceQuestion('Please choose the user\'s group: ', $gList);
            $questionGroup->setValidator(function ($answer) {
                if (!is_numeric($answer) || empty($answer)) {
                    throw new \RuntimeException(
                        'The group id c\'ant be empty'
                    );
                }
                global $groupRepository;
                if (null === $this->entityManager->getRepository(Group::class)->find($answer)) {
                    throw new \RuntimeException(
                        'No group find for this id'
                    );
                }

                return $answer;
            });
            $groupid = $helper->ask($input, $output, $questionGroup);
        }

        $group = $groupRepository->find($groupid);

        //RANK

        $rankid = $input->getArgument('rankid');
        /**
         * @var RankRepository $rankRepository
         */
        $rankRepository = $this->entityManager->getRepository(Rank::class);

        if ($rankid && null === $rankRepository->find($rankid)) {
            $rankid = '';
        }

        if (!$rankid) {
            foreach ($rankRepository->findByMainGroup($groupid) as $key => $r) {
                    $rList[$r->getId()] = $r->getName();
            }


            $questionRank = new ChoiceQuestion('Please choose the user\'s rank: ', $rList);
            $questionRank->setValidator(function ($answer) {
                if (!is_numeric($answer) || empty($answer)) {
                    throw new \RuntimeException(
                        'The rank id c\'ant be empty'
                    );
                }
                global $groupRepository;
                if (null === $this->entityManager->getRepository(Rank::class)->find($answer)) {
                    throw new \RuntimeException(
                        'No rank find for this id'
                    );
                }

                return $answer;
            });
            $rankid = $helper->ask($input, $output, $questionRank);
        }

        $rank = $rankRepository->find($rankid);

        $isAdmin = $input->getArgument('isadmin');

        if (!$isAdmin || !in_array(\strtolower($isAdmin), ['yes', 'no'])) {
            $questionFirstname = new ConfirmationQuestion('Is this user an Admin ? (yes/no, default to no): ', false);
            $isAdmin = $helper->ask($input, $output, $questionFirstname);
        }


        $user = new User();
        $user->setEmail($email);
        $user->setFirstname($firstname);
        $user->setLastname($lastname);
        $user->setMainGroup($group);
        $user->setMainRank($rank);
        $user->setPassword(uniqid() . uniqid() . uniqid());
        $user->setIsVerified(1);
        $user->setLocale($this->params->get('kernel.default_locale'));
        if ($isAdmin === true) {
            $user->setRoles(['ROLE_ADMIN']);
        }

        $this->entityManager->persist($user);

        try {
            $this->entityManager->flush();
            $io->success('User ' . $user->getLastname()  . ' ' . $user->getFirstname() . ' created');
            return Command::SUCCESS ;
        } catch (\Throwable $th) {
            throw $th;
            $io->error('Error while creating user ' . $user->getLastname()  . ' ' . $user->getFirstname());
            return Command::FAILURE;
        }
    }
}
