<?php

namespace FiloBlu\ActiveCampaign\Console\Command;

use Exception;
use FiloBlu\ActiveCampaign\Api\Data\JobsInterface;
use FiloBlu\ActiveCampaign\Cron\JobManager as JobManagerCron;
use FiloBlu\ActiveCampaign\Model\Config\Source\DirectionType;
use FiloBlu\ActiveCampaign\Model\Config\Source\EntityType;
use FiloBlu\ActiveCampaign\Model\Config\Source\JobStatus;
use FiloBlu\ActiveCampaign\Model\Config\Source\Type;
use FiloBlu\ActiveCampaign\Model\JobManager as JobManagerModel;
use Magento\Framework\App\Area;
use Magento\Framework\App\State;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Class JobProcess
 * @package FiloBlu\ActiveCampaign\Console\Command
 */
class JobProcess extends Command
{

    /**
     * @var JobManagerCron
     */
    protected $jobManager;
    /**
     * @var State
     */
    private $state;


    /**
     * JobProcess constructor.
     * @param JobManagerCron $jobManager
     * @param State $state
     * @param string|null $name
     */
    public function __construct(
        JobManagerCron $jobManager,
        State $state,
        string $name = null
    ) {
        parent::__construct($name);
        $this->jobManager = $jobManager;
        $this->state = $state;
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return void
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {

        //Area Code Fix
        try {
            $this->state->setAreaCode(Area::AREA_GLOBAL);
        } catch (Exception $e) {
            //Area code is already set
        }

        $options = $this->createOptionArguments($input, $output);

        if ($options === false) {
            return;
        }
        $statuses = $options[JobsInterface::STATUS];

        foreach ($statuses as $statusToProcess) {
            $options[JobsInterface::STATUS] = $statusToProcess;
            list($status, $message) = $this->jobManager->executeJob($options);
            $output->writeln("<$status>$message</$status>");
        }

        return 0;
    }

    /**
     * @param $input
     * @param $output
     * @return array|bool
     */
    protected function createOptionArguments($input, $output)
    {
        $options = [];
        $type = $input->getArgument(JobsInterface::TYPE);
        $direction = $input->getArgument(JobsInterface::DIRECTION);
        $entity = $input->getArgument(JobsInterface::ENTITY);
        $status = $input->getArgument(JobsInterface::STATUS);
        $consoleError = JobManagerModel::CONSOLE_ERROR;

        $options[JobManagerCron::OPERATION] = JobManagerCron::OPERATION_PROCESS;

        if (!in_array($type, Type::TYPE_AVAILABLE)) {
            $allowed_type = implode(',',Type::TYPE_AVAILABLE);
            $output->writeln("<{$consoleError}>The type '{$type}' is not available. Please choose between [{$allowed_type}]</{$consoleError}>");
            return false;
        }
        if (!in_array($direction, DirectionType::DIRECTION_AVAILABLE)) {
            $allowed_direction = implode(',',DirectionType::DIRECTION_AVAILABLE);
            $output->writeln("<{$consoleError}>The direction '{$direction}' is not available. Please choose between [{$allowed_direction}]</{$consoleError}>");
            return false;
        }
        if (!in_array($entity, EntityType::ENTITY_AVAILABLE)) {
            $allowed_entity = implode(',',EntityType::ENTITY_AVAILABLE);
            $output->writeln("<{$consoleError}>The entity '{$entity}' is not available. Please choose between [{$allowed_entity}]</{$consoleError}>");
            return false;
        }

        if(empty($status)){
            $stat = [JobStatus::JOB_STATUS_BULK_WAITING, JobStatus::JOB_STATUS_WAITING];
        }
        else {
            if (!in_array($status, [JobStatus::JOB_STATUS_WAITING,JobStatus::JOB_STATUS_BULK_WAITING])) {
                $allowed_status = implode(',',[JobStatus::JOB_STATUS_WAITING,JobStatus::JOB_STATUS_BULK_WAITING]);
                $output->writeln("<{$consoleError}>The entity '{$entity}' is not available. Please choose between [{$allowed_status}]</{$consoleError}>");
                return false;
            }
            $stat = [$status];
        }

        $options[JobsInterface::TYPE] = $type;
        $options[JobsInterface::DIRECTION] = $direction;
        $options[JobsInterface::ENTITY] = $entity;
        $options[JobsInterface::STATUS] = $stat;

        return $options;
    }

    /**
     * @inheritDoc
     */
    protected function configure()
    {
        $this->setName('activecampaign:job:process');
        $this->setDescription('ActiveCampaign job manager');
        $this->setDefinition([
            new InputArgument(JobsInterface::ENTITY, InputArgument::REQUIRED, 'entity'),
            new InputArgument(JobsInterface::DIRECTION, InputArgument::OPTIONAL, 'direction', DirectionType::DIRECTION_EXPORT),
            new InputArgument(JobsInterface::STATUS, InputArgument::OPTIONAL, 'status', ''),
            new InputArgument(JobsInterface::TYPE, InputArgument::OPTIONAL, 'type', Type::TYPE_REST)
        ]);
    }
}
