<?php

namespace App\Console\Commands;

use App\Contracts\SalesChannel;
use Mtc\MercuryDataModels\Enums\QueueProcessType;
use App\IntegrationRepository;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
use Mtc\MercuryDataModels\QueueProcessLog;
use Mtc\MercuryDataModels\Tenant;

class SalesChannelExportCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'sales-channels:export';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Run sales channel scheduled exports for a global or tenant';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        if (tenant()) {
            $this->getIntegrations()
                ->each(function (SalesChannel $channel) {
                    $this->runChannelExport($channel);
                });
        } else {
            $integrations = collect();

            Tenant::query()->whereNull('suspended_at')->get()->each(function (Tenant $tenant) use (&$integrations) {
                tenancy()->initialize($tenant);
                $integrations = $integrations->merge($this->getIntegrations(true));
            });

            $integrations->each(function (SalesChannel $channel) {
                $this->runChannelExport($channel);
            });
        }

        return Command::SUCCESS;
    }

    private function runChannelExport(SalesChannel $channel): void
    {
        $this->info('Running ' . $channel->name());

        $processLog = QueueProcessLog::start(
            QueueProcessType::Export,
            $channel->name(),
            ['tenant' => tenant('id')]
        );

        try {
            $channel->runScheduledExport();
            $processLog->markCompleted();
        } catch (Exception $exception) {
            $processLog->markFailed($exception->getMessage(), [
                'exception_class' => get_class($exception),
                'file' => $exception->getFile(),
                'line' => $exception->getLine(),
                'trace' => array_slice($exception->getTrace(), 0, 10),
            ]);

            $this->error('Failed: ' . $exception->getMessage());
        }
    }

    private function getIntegrations($global = false)
    {
        return new IntegrationRepository()
            ->getEnabledForType('sales-channels')
            ->filter(fn($integration) => !empty($integration['class']))
            ->filter(fn($integration) => $global
                ? ($integration['global'] ?? false)
                : !($integration['global'] ?? false))
            ->map(fn($integration) => App::make($integration['class']));
    }
}
