<?php

namespace AutoAdmin\Bundle\Admin\Command\Admin;

use AutoAdmin\Bundle\Admin\Service\AdministratorManager;
use AutoAdmin\Bundle\Content\Entity\Locale;
use AutoAdmin\Bundle\Content\Entity\Site;
use AutoAdmin\Bundle\Content\Site\SiteContextHelper;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
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\Console\Question\Question;

#[AsCommand(name: 'aa:admin:create-administrator')]
class CreateAdministratorCommand extends Command
{
    public function __construct(
        protected AdministratorManager $adminService,
        protected SiteContextHelper $siteContextHelper,
        protected EntityManagerInterface $em,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->setDescription('Create a new Admin account.');
    }

    public function execute(InputInterface $input, OutputInterface $output): int
    {
        $outputStyle = new OutputFormatterStyle('red', null);
        $output->getFormatter()->setStyle('error', $outputStyle);

        $adminData = $this->askInformations($input, $output);

        if (!$adminData) {
            $output->writeln("<comment>Command Canceled</comment>");
        }

        try {
            // we need to prepare site context in the case of merged administrator+user entities,
            // as user can be tied to Site even if administrator model is not
            if (
                ($site = $this->em->getRepository(Site::class)->findOneBy([], ['id' => 'ASC']))
                && ($locale = $this->em->getRepository(Locale::class)->findOneBy([], ['id' => 'ASC']))
            ) {
                $this->siteContextHelper->loadSiteAndLocale($site, $locale);
            }

            $admin = $this->adminService->create(
                $adminData['username'],
                $adminData['email'],
                $adminData['password'],
                $adminData['roles'],
                true
            );

            if (
                $adminData['site_auto_allow'] === true
                && $site = $this->em->getRepository(Site::class)->findOneBy([], ['id' => 'ASC'])
            ) {
                $admin->addAdministratorSite($site);
                $this->em->persist($admin);
                $this->em->flush($admin);
            }

        } catch (Exception $e) {
            $output->writeln("<error>Error: ".$e->getMessage()."</error>");

            return self::FAILURE;
        }

        $output->writeln("<info>The admin '".$adminData['username']."' has been created</info>");

        return self::SUCCESS;
    }

    private function askInformations(InputInterface $input, OutputInterface $output)
    {
        $helper = $this->getHelper('question');

        $usernameQuestion = new Question('Username: [superadmin] ', 'superadmin');
        $emailQuestion = new Question('Email: [superadmin@gda.fr]', 'superadmin@gda.fr');
        $passwordQuestion = new Question('Password: ', 'not_secret_change_it');
        $rolesQuestion = new ChoiceQuestion('Roles: [1] (csv format) ', [
            // This can be dynamic ?
            'ROLE_ADMIN',
            'ROLE_SUPER_ADMIN',
        ], '1');

        $rolesQuestion->setMultiselect(true);

        $siteAutoAllowQuestion = new ConfirmationQuestion('Auto-allow to first site? (Y/n)', true);

        // Confirmation
        $confirmationQuestion = new ConfirmationQuestion('Confirm creation? (y/N)', false);

        // Ask questions to user
        $username = $helper->ask($input, $output, $usernameQuestion);
        $email = $helper->ask($input, $output, $emailQuestion);
        $password = $helper->ask($input, $output, $passwordQuestion);
        $roles = $helper->ask($input, $output, $rolesQuestion);

        // Reformatting values
        $username = strtolower($username);
        $email = strtolower($email);

        foreach ($roles as $k => $value) {
            $roles[$k] = trim(strtoupper($value));
        }

        $siteAutoAllow = $helper->ask($input, $output, $siteAutoAllowQuestion);

        // User validate infos
        if (!$helper->ask($input, $output, $confirmationQuestion)) {
            return false;
        }

        // Return statements
        return [
            'username' => strtolower($username),
            'email' => strtolower($email),
            'password' => $password,
            'roles' => $roles,
            'site_auto_allow' => $siteAutoAllow,
        ];
    }
}
