<?php declare(strict_types=1);

namespace Atl\DiscountExtension\Command;

use Shopware\Core\Framework\Adapter\Console\ShopwareStyle;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class CheckDiscountEligibility extends Command
{
    protected static $defaultName = 'atl:check-discount-eligibility';

    /**
     * @var SystemConfigService
     */
    private $systemConfigService;

    /**
     * @var EntityRepositoryInterface
     */
    private $repeatDiscountRepository;

    /**
     * @var EntityRepositoryInterface
     */
    private $customerTagRepository;

    public function __construct
    (
        SystemConfigService $systemConfigService,
        EntityRepositoryInterface $repeatDiscountRepository,
        EntityRepositoryInterface $customerTagRepository
    )
    {
        parent::__construct();
        $this->systemConfigService = $systemConfigService;
        $this->repeatDiscountRepository = $repeatDiscountRepository;
        $this->customerTagRepository = $customerTagRepository;
    }

    protected function configure(): void
    {
        $this->setDescription('Checks the discount eligibility and removes the discount customer tag if it expired.');
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new ShopwareStyle($input, $output);

        $expiredDiscounts = $this->getExpiredDiscounts();

        if (empty($expiredDiscounts)) {
            $io->success('No customer tags were removed.');
            return self::SUCCESS;
        }

        $tags = [];
        $discounts = [];
        foreach ($expiredDiscounts as $expiredDiscount) {
            $salesChannelId = $expiredDiscount->getCustomer()->getSalesChannelId();
            $tagId = $this->systemConfigService->get('AtlDiscountExtension.config.tag', $salesChannelId);

            if (empty($tagId)) {
                $io->warning('Customer tag assignment in plugin configuration is missing.');
                return self::FAILURE;
            }

            $tags[] = [
                'customerId' => $expiredDiscount->getCustomerId(),
                'tagId' => $tagId
            ];

            $discounts[] = [
                'id' => $expiredDiscount->getId()
            ];
        }

        $this->removeCustomerTags($tags);
        $this->removeDiscounts($discounts);

        $io->success(sprintf('Successfully deleted %d expired discounts.', count($expiredDiscounts)));

        return self::SUCCESS;
    }

    /**
     * @return array
     */
    private function getExpiredDiscounts(): array
    {
        $expirationDays = $this->systemConfigService->get('AtlDiscountExtension.config.expirationDays');

        // Go $expirationDays back in time
        $expirationDate = (new \DateTime())->add(\DateInterval::createFromDateString('-' . $expirationDays . ' days'));

        $criteria = new Criteria();
        $criteria->addFilter(
            new RangeFilter('lastOrderDate',
            [
                // last order date is earlier than expiration date
                RangeFilter::LTE => $expirationDate->format(\DATE_ATOM),
            ]
        ));
        $criteria->addAssociation('customer');
        $criteria->setLimit(999);

        return $this->repeatDiscountRepository->search($criteria, Context::createDefaultContext())->getElements();
    }

    /**
     * @param array $tags
     * @return void
     */
    private function removeCustomerTags(array $tags): void
    {
        $this->customerTagRepository->delete($tags, Context::createDefaultContext());
    }

    /**
     * @param array $discounts
     * @return void
     */
    private function removeDiscounts(array $discounts): void
    {
        $this->repeatDiscountRepository->delete($discounts, Context::createDefaultContext());
    }
}