<?php

/**
 * Chill is a software for social workers.
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\CalendarBundle\Command;

use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Service\ShortMessageNotification\ShortMessageForCalendarBuilderInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Repository\PersonRepository;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberType;
use libphonenumber\PhoneNumberUtil;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Notifier\TexterInterface;

class SendTestShortMessageOnCalendarCommand extends Command
{
    protected static $defaultDescription = 'Test sending a SMS for a dummy calendar appointment';

    public function __construct(
        private readonly PersonRepository $personRepository,
        private readonly PhoneNumberUtil $phoneNumberUtil,
        private readonly ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder,
        private readonly TexterInterface $transporter,
        private readonly UserRepositoryInterface $userRepository,
    ) {
        parent::__construct('chill:calendar:test-send-short-message');
    }

    protected function configure() {}

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $calendar = new Calendar();
        $calendar->setSendSMS(true);

        /** @var QuestionHelper $helper */
        $helper = $this->getHelper('question');

        // start date
        $question = new Question('When will start the appointment ? (default: "1 hour") ', '1 hour');
        $startDate = new \DateTimeImmutable($helper->ask($input, $output, $question));

        if (false === $startDate) {
            throw new \UnexpectedValueException('could not create a date with this date and time');
        }

        $calendar->setStartDate($startDate);

        // end date
        $question = new Question('How long will last the appointment ? (default: "PT30M") ', 'PT30M');
        $interval = new \DateInterval($helper->ask($input, $output, $question));

        if (false === $interval) {
            throw new \UnexpectedValueException('could not create the interval');
        }

        $calendar->setEndDate($calendar->getStartDate()->add($interval));

        // a person
        $question = new Question('Who will participate ? Give an id for a person. ');
        $question
            ->setValidator(function ($answer): Person {
                if (!is_numeric($answer)) {
                    throw new \UnexpectedValueException('the answer must be numeric');
                }

                if (0 >= (int) $answer) {
                    throw new \UnexpectedValueException('the answer must be greater than zero');
                }

                $person = $this->personRepository->find((int) $answer);

                if (null === $person) {
                    throw new \UnexpectedValueException('The person is not found');
                }

                return $person;
            });

        $person = $helper->ask($input, $output, $question);
        $calendar->addPerson($person);

        // a main user
        $question = new Question('Who will be the main user ? Give an id for a user. ');
        $question
            ->setValidator(function ($answer): User {
                if (!is_numeric($answer)) {
                    throw new \UnexpectedValueException('the answer must be numeric');
                }

                if (0 >= (int) $answer) {
                    throw new \UnexpectedValueException('the answer must be greater than zero');
                }

                $user = $this->userRepository->find((int) $answer);

                if (null === $user) {
                    throw new \UnexpectedValueException('The user is not found');
                }

                return $user;
            });

        $user = $helper->ask($input, $output, $question);
        $calendar->setMainUser($user);

        // phonenumber
        $phonenumberFormatted = null !== $person->getMobilenumber() ?
            $this->phoneNumberUtil->format($person->getMobilenumber(), PhoneNumberFormat::E164) : '';
        $question = new Question(
            sprintf('To which number are we going to send this fake message ? (default to: %s)', $phonenumberFormatted),
            $phonenumberFormatted
        );

        $question->setNormalizer(function ($answer): PhoneNumber {
            if (null === $answer) {
                throw new \UnexpectedValueException('The person is not found');
            }

            $phone = $this->phoneNumberUtil->parse($answer, 'BE');

            if (!$this->phoneNumberUtil->isPossibleNumberForType($phone, PhoneNumberType::MOBILE)) {
                throw new \UnexpectedValueException('Phone number si not a mobile');
            }

            return $phone;
        });


        $messages = $this->messageForCalendarBuilder->buildMessageForCalendar($calendar);

        if (0 === \count($messages)) {
            $output->writeln('no message to send to this user');
        }

        foreach ($messages as $key => $message) {
            $output->writeln("The short message for SMS {$key} will be: ");
            $output->writeln($message->getSubject());
            $output->writeln('The destination number will be:');
            $output->writeln($message->getPhone());

            $question = new ConfirmationQuestion('really send the message to the phone ?');
            $reallySend = (bool) $helper->ask($input, $output, $question);

            if ($reallySend) {
                $this->transporter->send($message);
            }
        }

        return Command::SUCCESS;
    }
}
