<?php

declare(strict_types=1);

namespace App\Services\Tmux;

use App\Enums\TmuxPaneRole;
use App\Models\Settings;

/**
 * Service for running tasks in tmux panes
 */
class TmuxTaskRunner
{
    protected TmuxPaneManager $paneManager;

    protected string $sessionName;

    public function __construct(string $sessionName)
    {
        $this->sessionName = $sessionName;
        $this->paneManager = new TmuxPaneManager($sessionName);
    }

    /**
     * Get niceness value from settings or config with sensible default
     */
    protected function getNiceness(): int
    {
        // Try to get from settings first
        $niceness = Settings::settingValue('niceness');

        // If empty string or null, try config
        if (empty($niceness) && $niceness !== 0 && $niceness !== '0') {
            $niceness = config('nntmux.niceness');
        }

        // If still empty, use system default
        if (empty($niceness) && $niceness !== 0 && $niceness !== '0') {
            $niceness = 10; // Standard nice default
        }

        return (int) $niceness;
    }

    /**
     * Run a task in a specific pane
     *
     * @param  array<string, mixed>  $config
     */
    public function runTask(string $taskName, array $config): bool
    {
        $role = $config['role'] ?? null;
        $command = $config['command'] ?? null;
        $enabled = $config['enabled'] ?? true;
        $workAvailable = $config['work_available'] ?? true;

        if (! $role instanceof TmuxPaneRole || ! $command) {
            return false;
        }

        $legacyPane = $config['legacy_pane'] ?? null;
        $pane = $this->paneManager->paneForRole($role, is_string($legacyPane) ? $legacyPane : null);

        // Check if task is enabled and has work
        if (! $enabled) {
            return $this->disablePane($pane, $taskName, 'disabled in settings');
        }

        if (! $workAvailable) {
            return $this->disablePane($pane, $taskName, 'no work available');
        }

        // Respawn the pane with the command
        return $this->paneManager->respawnPane($pane, $command);
    }

    /**
     * Disable a pane with a message
     */
    protected function disablePane(string $pane, string $taskName, string $reason): bool
    {
        $color = $this->getRandomColor();
        $message = "echo -e \"\033[38;5;{$color}m\n{$taskName} has been disabled: {$reason}\"";

        return $this->paneManager->respawnPane($pane, $message, kill: true);
    }

    /**
     * Build a command with logging
     *
     * @param  array<string, mixed>  $options
     */
    public function buildCommand(string $baseCommand, array $options = []): string
    {
        $parts = [$baseCommand];

        // Add sleep timer at the end if specified
        if (isset($options['sleep'])) {
            $sleepCommand = $this->buildSleepCommand($options['sleep']);
            $parts[] = 'date +"%Y-%m-%d %T"';
            $parts[] = $sleepCommand;
        }

        // Add logging if enabled
        if (isset($options['log_pane'])) {
            $logFile = $this->getLogFile($options['log_pane']);
            $command = implode('; ', $parts);

            return "{$command} 2>&1 | tee -a {$logFile}";
        }

        return implode('; ', $parts);
    }

    /**
     * Build sleep command
     */
    protected function buildSleepCommand(int $seconds): string
    {
        $niceness = $this->getNiceness();
        $sleepScript = base_path('app/Services/Tmux/Scripts/showsleep.php');

        if (file_exists($sleepScript)) {
            return "nice -n{$niceness} php {$sleepScript} {$seconds}";
        }

        return "sleep {$seconds}";
    }

    /**
     * Get log file path for a pane
     */
    protected function getLogFile(string $paneName): string
    {
        $logsEnabled = (int) Settings::settingValue('write_logs') === 1;

        if (! $logsEnabled) {
            return '/dev/null';
        }

        $logDir = config('tmux.paths.logs', storage_path('logs/tmux'));

        if (! is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }

        $date = now()->format('Y_m_d');

        return "{$logDir}/{$paneName}-{$date}.log";
    }

    /**
     * Get a random color for terminal output
     */
    protected function getRandomColor(): int
    {
        $start = (int) Settings::settingValue('colors_start');
        $end = (int) Settings::settingValue('colors_end');
        $exclude = Settings::settingValue('colors_exc') ?? '';

        if (empty($exclude)) {
            return random_int($start, $end);
        }

        $exceptions = array_map('intval', explode(',', $exclude));
        sort($exceptions);

        $number = random_int($start, $end - count($exceptions));

        foreach ($exceptions as $exception) {
            if ($number >= $exception) {
                $number++;
            } else {
                break;
            }
        }

        return $number;
    }

    /**
     * Run the IRC scraper
     *
     * @param  array<string, mixed>  $config
     */
    public function runIRCScraper(array $config): bool
    {
        $runScraper = (int) ($config['constants']['run_ircscraper'] ?? 0);
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::IrcScraper, '3.0');

        if ($runScraper !== 1) {
            return $this->disablePane($pane, 'IRC Scraper', 'disabled in settings');
        }

        $niceness = $this->getNiceness();
        $artisan = base_path('artisan');
        $command = "nice -n{$niceness} php {$artisan} irc:scrape";
        $command = $this->buildCommand($command, ['log_pane' => 'scraper']);

        return $this->paneManager->respawnPane($pane, $command);
    }

    /**
     * Run binaries update
     *
     * @param  array<string, mixed>  $config
     */
    public function runBinariesUpdate(array $config): bool
    {
        $enabled = (int) ($config['settings']['binaries_run'] ?? 0);
        $killswitch = $config['killswitch']['pp'] ?? false;
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::Binaries, '0.1');

        if (! $enabled) {
            return $this->disablePane($pane, 'Update Binaries', 'disabled in settings');
        }

        if ($killswitch) {
            return $this->disablePane($pane, 'Update Binaries', 'postprocess kill limit exceeded');
        }

        $artisanCommand = match ((int) $enabled) {
            1 => 'multiprocessing:safe binaries',
            default => null,
        };

        if (! $artisanCommand) {
            return false;
        }

        $niceness = $this->getNiceness();
        $command = "nice -n{$niceness} ".PHP_BINARY." artisan {$artisanCommand}";
        $sleep = (int) ($config['settings']['bins_timer'] ?? 60);
        $command = $this->buildCommand($command, ['log_pane' => 'binaries', 'sleep' => $sleep]);

        return $this->paneManager->respawnPane($pane, $command);
    }

    /**
     * Run backfill
     *
     * @param  array<string, mixed>  $config
     */
    public function runBackfill(array $config): bool
    {
        $enabled = (int) ($config['settings']['backfill'] ?? 0);
        $collKillswitch = $config['killswitch']['coll'] ?? false;
        $ppKillswitch = $config['killswitch']['pp'] ?? false;
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::Backfill, '0.2');

        if (! $enabled) {
            return $this->disablePane($pane, 'Backfill', 'disabled in settings');
        }

        if ($collKillswitch || $ppKillswitch) {
            return $this->disablePane($pane, 'Backfill', 'kill limit exceeded');
        }

        $artisanCommand = match ((int) $enabled) {
            1 => 'multiprocessing:backfill',
            4 => 'multiprocessing:safe backfill',
            default => null,
        };

        if (! $artisanCommand) {
            return false;
        }

        // Calculate sleep time (progressive if enabled)
        $baseSleep = (int) ($config['settings']['back_timer'] ?? 600);
        $collections = (int) ($config['counts']['now']['collections_table'] ?? 0);
        $progressive = (int) ($config['settings']['progressive'] ?? 0);

        $sleep = ($progressive === 1 && floor($collections / 500) > $baseSleep)
            ? floor($collections / 500)
            : $baseSleep;

        $niceness = $this->getNiceness();
        $command = "nice -n{$niceness} ".PHP_BINARY." artisan {$artisanCommand}";
        $command = $this->buildCommand($command, ['log_pane' => 'backfill', 'sleep' => $sleep]);

        return $this->paneManager->respawnPane($pane, $command);
    }

    /**
     * Run releases update
     *
     * @param  array<string, mixed>  $config
     */
    public function runReleasesUpdate(array $config): bool
    {
        $enabled = (int) ($config['settings']['releases_run'] ?? 0);
        $legacyPane = (int) ($config['constants']['sequential'] ?? 0) === 1 ? '0.1' : '0.3';
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::Releases, $legacyPane);

        if (! $enabled) {
            return $this->disablePane($pane, 'Update Releases', 'disabled in settings');
        }

        $niceness = $this->getNiceness();
        $command = "nice -n{$niceness} ".PHP_BINARY.' artisan multiprocessing:releases';
        $sleep = (int) ($config['settings']['rel_timer'] ?? 60);
        $command = $this->buildCommand($command, ['log_pane' => 'releases', 'sleep' => $sleep]);

        return $this->paneManager->respawnPane($pane, $command);
    }

    /**
     * Run a specific pane task based on task name
     *
     * @param  string  $taskName  The name of the task to run
     * @param  array<string, mixed>  $config  Configuration for the task (target pane, etc.)
     * @param  array<string, mixed>  $runVar  Runtime variables and settings
     * @return bool Success status
     */
    public function runPaneTask(string $taskName, array $config, array $runVar): bool
    {
        $sequential = (int) ($runVar['constants']['sequential'] ?? 0);

        return match ($taskName) {
            'main' => $this->runMainTask($sequential, $runVar),
            'fixnames' => $this->runFixNamesTask($runVar),
            'removecrap' => $this->runRemoveCrapTask($runVar),
            'ppadditional' => $this->runPostProcessAdditional($runVar),
            'tv' => $this->runTvTask($runVar),
            'movies' => $this->runMoviesTask($runVar),
            'amazon' => $this->runAmazonTask($runVar),
            'scraper' => $this->runIRCScraper($runVar),
            // Legacy mapping for backward compatibility
            'nonamazon' => $this->runTvTask($runVar),
            default => false,
        };
    }

    /**
     * Run main task (varies by sequential mode)
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runMainTask(int $sequential, array $runVar): bool
    {
        return match ($sequential) {
            0 => $this->runMainNonSequential($runVar),
            1 => $this->runMainBasic($runVar),
            2 => $this->runMainSequential($runVar),
            default => false,
        };
    }

    /**
     * Run main non-sequential task (binaries, backfill, releases)
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runMainNonSequential(array $runVar): bool
    {
        // This runs in pane 0.1, 0.2, 0.3
        // For now, delegate to existing methods
        $this->runBinariesUpdate($runVar);
        $this->runBackfill($runVar);
        $this->runReleasesUpdate($runVar);

        return true;
    }

    /**
     * Run main basic sequential task (just releases)
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runMainBasic(array $runVar): bool
    {
        return $this->runReleasesUpdate($runVar);
    }

    /**
     * Run main full sequential task
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runMainSequential(array $runVar): bool
    {
        // Full sequential mode - runs group:update-all for each group
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::Sequential, '0.1');

        $niceness = $this->getNiceness();
        $artisan = base_path('artisan');
        $command = "nice -n{$niceness} php {$artisan} group:update-all";
        $command = $this->buildCommand($command, ['log_pane' => 'sequential']);

        return $this->paneManager->respawnPane($pane, $command);
    }

    /**
     * Run fix release names task
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runFixNamesTask(array $runVar): bool
    {
        $enabled = (int) ($runVar['settings']['fix_names'] ?? 0);
        $work = (int) ($runVar['counts']['now']['processrenames'] ?? 0);
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::FixNames, '1.0');

        if ($enabled !== 1) {
            return $this->disablePane($pane, 'Fix Release Names', 'disabled in settings');
        }

        if ($work === 0) {
            return $this->disablePane($pane, 'Fix Release Names', 'no releases to process');
        }

        $artisan = base_path('artisan');
        $log = $this->getLogFile('fixnames');

        // Run multiple fix-names passes
        $commands = [];
        foreach ([3, 5, 7, 9, 11, 13, 15, 17, 19] as $level) {
            $commands[] = "php {$artisan} releases:fix-names {$level} --update --category=other --set-status --show 2>&1 | tee -a {$log}";
        }

        $sleep = (int) ($runVar['settings']['fix_timer'] ?? 300);
        $allCommands = implode('; ', $commands);
        $sleepCommand = $this->buildSleepCommand($sleep);
        $fullCommand = "{$allCommands}; date +'%Y-%m-%d %T'; {$sleepCommand}";

        return $this->paneManager->respawnPane($pane, $fullCommand);
    }

    /**
     * Run remove crap releases task
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runRemoveCrapTask(array $runVar): bool
    {
        $option = $runVar['settings']['fix_crap_opt'] ?? 'Disabled';
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::RemoveCrap, '1.1');

        // Handle disabled state
        if ($option === 'Disabled' || $option === 0 || $option === '0') {
            return $this->disablePane($pane, 'Remove Crap', 'disabled in settings');
        }

        $niceness = $this->getNiceness();
        $artisan = base_path('artisan');
        $sleep = (int) ($runVar['settings']['crap_timer'] ?? 300);

        // Handle 'All' mode - run all types with 2 hour time limit
        if ($option === 'All') {
            $command = "nice -n{$niceness} php {$artisan} releases:remove-crap --time=2 --delete";
            $command = $this->buildCommand($command, ['log_pane' => 'removecrap', 'sleep' => $sleep]);

            return $this->paneManager->respawnPane($pane, $command);
        }

        // Handle 'Custom' mode - run all selected types sequentially
        if ($option === 'Custom') {
            $selectedTypes = $runVar['settings']['fix_crap'] ?? '';

            // Convert numeric 0 or empty values to empty string
            if (empty($selectedTypes)) {
                return $this->disablePane($pane, 'Remove Crap', 'no crap types selected');
            }

            $types = is_array($selectedTypes) ? $selectedTypes : explode(',', $selectedTypes);

            // Trim whitespace and filter out empty values and '0'
            $types = array_map('trim', $types);
            $types = array_filter($types, fn ($type) => ! empty($type));

            // Re-index array to ensure sequential keys
            $types = array_values($types);

            if (empty($types)) {
                return $this->disablePane($pane, 'Remove Crap', 'no crap types selected');
            }

            // Get state to determine if this is first run
            $stateFile = storage_path('tmux/removecrap_state.json');
            $state = $this->loadCrapState($stateFile);
            $isFirstRun = $state['first_run'] ?? true;

            // Determine time limit: full on first run, 4 hours otherwise
            $time = $isFirstRun ? 'full' : '4';

            // Build commands for all enabled types to run sequentially
            $log = $this->getLogFile('removecrap');
            $commands = [];
            foreach ($types as $type) {
                $commands[] = "echo \"\nRunning removeCrapReleases for {$type}\"; nice -n{$niceness} php {$artisan} releases:remove-crap --type={$type} --time={$time} --delete 2>&1 | tee -a {$log}";
            }

            // Join all commands with semicolons and add final timestamp and sleep
            $allCommands = implode('; ', $commands);
            $sleepCommand = $this->buildSleepCommand($sleep);
            $fullCommand = "{$allCommands}; date +'%Y-%m-%d %T'; {$sleepCommand}";

            // Mark that we're not on the first run anymore for next cycle
            $this->saveCrapState($stateFile, [
                'first_run' => false,
                'types' => $types,
            ]);

            return $this->paneManager->respawnPane($pane, $fullCommand);
        }

        // Default fallback - disabled
        return $this->disablePane($pane, 'Remove Crap', 'invalid configuration');
    }

    /**
     * Load crap removal state
     *
     * @return array<string, mixed>
     */
    protected function loadCrapState(string $file): array
    {
        if (! file_exists($file)) {
            return ['first_run' => true];
        }

        $content = file_get_contents($file);
        $state = json_decode($content, true);

        return $state ?: ['first_run' => true];
    }

    /**
     * Save crap removal state
     *
     * @param  array<string, mixed>  $state
     */
    protected function saveCrapState(string $file, array $state): void
    {
        $dir = dirname($file);
        if (! is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        file_put_contents($file, json_encode($state, JSON_PRETTY_PRINT));
    }

    /**
     * Run post-process additional task
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runPostProcessAdditional(array $runVar): bool
    {
        $postSetting = (int) ($runVar['settings']['post'] ?? 0);
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::PostAdditional, '2.0');

        // Check if post processing is enabled (1 = additional, 2 = nfo, 3 = both)
        if ($postSetting === 0) {
            return $this->disablePane($pane, 'Post-process Additional', 'disabled in settings');
        }

        $hasWork = (int) ($runVar['counts']['now']['work_available'] ?? $runVar['counts']['now']['work'] ?? 0) > 0;
        $hasNfo = (int) ($runVar['counts']['now']['processnfo'] ?? 0) > 0;

        $niceness = Settings::settingValue('niceness') ?? 2;
        $log = $this->getLogFile('post_additional');
        $sleep = (int) ($runVar['settings']['post_timer'] ?? 300);

        $commands = [];

        // Build commands based on post setting value
        if ($postSetting === 1) {
            // Post = 1: Additional processing only
            if ($hasWork) {
                $commands[] = "nice -n{$niceness} ".PHP_BINARY." artisan multiprocessing:postprocess add 2>&1 | tee -a {$log}";
            }
        } elseif ($postSetting === 2) {
            // Post = 2: NFO processing only
            if ($hasNfo) {
                $commands[] = "nice -n{$niceness} ".PHP_BINARY." artisan multiprocessing:postprocess nfo 2>&1 | tee -a {$log}";
            }
        } elseif ($postSetting === 3) {
            // Post = 3: Both additional and NFO
            if ($hasWork) {
                $commands[] = "nice -n{$niceness} ".PHP_BINARY." artisan multiprocessing:postprocess add 2>&1 | tee -a {$log}";
            }
            if ($hasNfo) {
                $commands[] = "nice -n{$niceness} ".PHP_BINARY." artisan multiprocessing:postprocess nfo 2>&1 | tee -a {$log}";
            }
        }

        // If no work available, disable the pane
        if (empty($commands)) {
            $reason = match ($postSetting) {
                1 => 'no additional work to process',
                2 => 'no NFOs to process',
                3 => 'no additional work or NFOs to process',
                default => 'invalid post setting value',
            };

            return $this->disablePane($pane, 'Post-process Additional', $reason);
        }

        // Build the full command with all parts
        $allCommands = implode('; ', $commands);
        $sleepCommand = $this->buildSleepCommand($sleep);
        $fullCommand = "{$allCommands}; date +'%Y-%m-%d %T'; {$sleepCommand}";

        return $this->paneManager->respawnPane($pane, $fullCommand);
    }

    /**
     * Run TV/Anime post-processing
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runTvTask(array $runVar): bool
    {
        $enabled = (int) ($runVar['settings']['post_non'] ?? 0);
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::PostTv, '2.1');

        if ($enabled !== 1) {
            return $this->disablePane($pane, 'Post-process TV/Anime', 'disabled in settings');
        }

        $niceness = $this->getNiceness();
        $log = $this->getLogFile('post_tv');
        $artisan = PHP_BINARY.' artisan';
        $commands = [];

        // TV processing - Check work count before adding to queue
        $processTv = (int) ($runVar['settings']['processtvrage'] ?? 0);
        $hasTvWork = (int) ($runVar['counts']['now']['processtv'] ?? 0) > 0;
        if ($processTv > 0 && $hasTvWork) {
            $commands[] = "nice -n{$niceness} {$artisan} multiprocessing:postprocess tv 2>&1 | tee -a {$log}";
        }

        // Anime processing
        $processAnime = (int) ($runVar['settings']['processanime'] ?? 0);
        $hasAnimeWork = (int) ($runVar['counts']['now']['processanime'] ?? 0) > 0;
        if ($processAnime > 0 && $hasAnimeWork) {
            $commands[] = "nice -n{$niceness} {$artisan} multiprocessing:postprocess ani 2>&1 | tee -a {$log}";
        }

        // If no work available for any enabled type, disable the pane
        if (empty($commands)) {
            $enabledTypes = [];
            if ($processTv > 0) {
                $enabledTypes[] = 'TV';
            }
            if ($processAnime > 0) {
                $enabledTypes[] = 'Anime';
            }

            if (empty($enabledTypes)) {
                return $this->disablePane($pane, 'Post-process TV/Anime', 'no types enabled (TV/Anime)');
            }

            $typesList = implode(', ', $enabledTypes);

            return $this->disablePane($pane, 'Post-process TV/Anime', "no work for enabled types ({$typesList})");
        }

        $sleep = (int) ($runVar['settings']['post_timer_non'] ?? 300);
        $allCommands = implode('; ', $commands);
        $sleepCommand = $this->buildSleepCommand($sleep);
        $fullCommand = "{$allCommands}; date +'%Y-%m-%d %T'; {$sleepCommand}";

        return $this->paneManager->respawnPane($pane, $fullCommand);
    }

    /**
     * Run Movies post-processing
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runMoviesTask(array $runVar): bool
    {
        $enabled = (int) ($runVar['settings']['post_non'] ?? 0);
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::PostMovies, '2.3');

        if ($enabled !== 1) {
            return $this->disablePane($pane, 'Post-process Movies', 'disabled in settings');
        }

        $niceness = $this->getNiceness();
        $log = $this->getLogFile('post_movies');
        $artisan = PHP_BINARY.' artisan';

        // Movies processing - Uses single-process command
        $processMovies = (int) ($runVar['settings']['processmovies'] ?? 0);
        $hasMoviesWork = (int) ($runVar['counts']['now']['processmovies'] ?? 0) > 0;

        if ($processMovies === 0) {
            return $this->disablePane($pane, 'Post-process Movies', 'disabled in settings');
        }

        if (! $hasMoviesWork) {
            return $this->disablePane($pane, 'Post-process Movies', 'no work available');
        }

        $sleep = (int) ($runVar['settings']['post_timer_non'] ?? 300);
        $command = "nice -n{$niceness} {$artisan} multiprocessing:postprocess mov false 2>&1 | tee -a {$log}";
        $sleepCommand = $this->buildSleepCommand($sleep);
        $fullCommand = "{$command}; date +'%Y-%m-%d %T'; {$sleepCommand}";

        return $this->paneManager->respawnPane($pane, $fullCommand);
    }

    /**
     * Legacy method for backward compatibility - now just calls runTvTask
     *
     * @deprecated Use runTvTask() instead
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runNonAmazonTask(array $runVar): bool
    {
        return $this->runTvTask($runVar);
    }

    /**
     * Run metadata post-processing (Books, Music, Games, Console)
     *
     * @param  array<string, mixed>  $runVar
     */
    protected function runAmazonTask(array $runVar): bool
    {
        $enabled = (int) ($runVar['settings']['post_amazon'] ?? 0);
        $legacyPane = (int) ($runVar['constants']['sequential'] ?? 0) === 2 ? '1.1' : '2.2';
        $pane = $this->paneManager->paneForRole(TmuxPaneRole::PostMetadata, $legacyPane);

        if ($enabled !== 1) {
            return $this->disablePane($pane, 'Post-process Metadata', 'disabled in settings');
        }

        $hasWork = (int) ($runVar['counts']['now']['processmusic'] ?? 0) > 0
            || (int) ($runVar['counts']['now']['processbooks'] ?? 0) > 0
            || (int) ($runVar['counts']['now']['processconsole'] ?? 0) > 0
            || (int) ($runVar['counts']['now']['processgames'] ?? 0) > 0;

        if (! $hasWork) {
            return $this->disablePane($pane, 'Post-process Metadata', 'no music/books/games to process');
        }

        $niceness = Settings::settingValue('niceness') ?? 2;
        $log = $this->getLogFile('post_amazon');
        $artisan = PHP_BINARY.' artisan';
        $sleep = (int) ($runVar['settings']['post_timer_amazon'] ?? 300);

        $command = "nice -n{$niceness} {$artisan} multiprocessing:postprocess ama 2>&1 | tee -a {$log}";
        $sleepCommand = $this->buildSleepCommand($sleep);
        $fullCommand = "{$command}; date +'%Y-%m-%d %T'; {$sleepCommand}";

        return $this->paneManager->respawnPane($pane, $fullCommand);
    }
}
