<?php

namespace App\Command;

use App\Entity\User;
use App\Service\StripeService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'app:stripe:sync',
    description: 'Sync Stripe account status for all organizers',
)]
class StripeSyncCommand extends Command
{
    public function __construct(
        private EntityManagerInterface $em,
        private StripeService $stripeService,
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        $organizers = array_filter(
            $this->em->getRepository(User::class)->findAll(),
            fn (User $u) => \in_array('ROLE_ORGANIZER', $u->getRoles(), true) && null !== $u->getStripeAccountId(),
        );

        if (0 === \count($organizers)) {
            $io->info('No organizers with Stripe accounts found.');

            return Command::SUCCESS;
        }

        $io->info(sprintf('Syncing %d organizer(s)...', \count($organizers)));

        $synced = 0;
        $errors = 0;

        foreach ($organizers as $user) {
            try {
                $status = $this->stripeService->retrieveAccountStatus($user->getStripeAccountId());

                $chargesBefore = $user->isStripeChargesEnabled();
                $payoutsBefore = $user->isStripePayoutsEnabled();

                $user->setStripeChargesEnabled($status['charges_enabled']);
                $user->setStripePayoutsEnabled($status['payouts_enabled']);

                $changed = $chargesBefore !== $user->isStripeChargesEnabled()
                    || $payoutsBefore !== $user->isStripePayoutsEnabled();

                $status = $changed ? '<fg=yellow>UPDATED</>' : '<fg=green>OK</>';
                $io->text(sprintf(
                    '  [%s] %s (%s) — charges: %s, payouts: %s',
                    $status,
                    $user->getCompanyName() ?? $user->getEmail(),
                    $user->getStripeAccountId(),
                    $user->isStripeChargesEnabled() ? 'yes' : 'no',
                    $user->isStripePayoutsEnabled() ? 'yes' : 'no',
                ));

                ++$synced;
            } catch (\Throwable $e) {
                $io->text(sprintf(
                    '  [<fg=red>ERROR</>] %s (%s) — %s',
                    $user->getCompanyName() ?? $user->getEmail(),
                    $user->getStripeAccountId(),
                    $e->getMessage(),
                ));
                ++$errors;
            }
        }

        $this->em->flush();

        $io->success(sprintf('Done: %d synced, %d error(s).', $synced, $errors));

        return $errors > 0 ? Command::FAILURE : Command::SUCCESS;
    }
}
