<?php

declare(strict_types=1);

namespace App\Framework\Console\Examples;

use App\Framework\Console\ConsoleCommand;
use App\Framework\Console\ConsoleInput;
use App\Framework\Console\ConsoleOutputInterface;
use App\Framework\Console\ExitCode;
use App\Framework\Core\ValueObjects\Email;

/**
 * Best practices for Console Command parameters
 *
 * Shows recommended patterns and when to use different parameter styles.
 */
final readonly class ConsoleParameterBestPracticesCommand
{
    /**
     * ✅ RECOMMENDED: Typed parameters for known arguments
     *
     * Usage: php console.php best:typed username --max 20
     */
    #[ConsoleCommand(
        name: 'best:typed',
        description: 'Typed parameters example'
    )]
    public function typedParameters(
        ConsoleOutputInterface $output,
        string $username,
        int $max = 10
    ): ExitCode {
        $output->writeLine("Processing user: {$username}");
        $output->writeLine("Maximum results: {$max}");

        return ExitCode::SUCCESS;
    }

    /**
     * ✅ RECOMMENDED: Value Objects for validation
     *
     * Usage: php console.php best:value-objects user@example.com
     */
    #[ConsoleCommand(
        name: 'best:value-objects',
        description: 'Value Objects for automatic validation'
    )]
    public function valueObjects(
        ConsoleOutputInterface $output,
        Email $email
    ): ExitCode {
        // Email is already validated by Value Object!
        $output->writeLine("Valid email: {$email->value}");

        return ExitCode::SUCCESS;
    }

    /**
     * ✅ RECOMMENDED: Nullable bool for optional flags
     *
     * Usage: php console.php best:flags production        (verbose=null)
     *        php console.php best:flags production --verbose  (verbose=true)
     */
    #[ConsoleCommand(
        name: 'best:flags',
        description: 'Optional flags with nullable bool'
    )]
    public function withFlags(
        ConsoleOutputInterface $output,
        string $environment,
        ?bool $verbose = null,
        ?bool $force = null
    ): ExitCode {
        $output->writeLine("Deploying to: {$environment}");

        if ($verbose === true) {
            $output->writeLine("Verbose mode enabled");
        }

        if ($force === true) {
            $output->writeLine("Force mode enabled");
        }

        if ($verbose === null && $force === null) {
            $output->writeLine("No flags provided");
        }

        return ExitCode::SUCCESS;
    }

    /**
     * ✅ RECOMMENDED: Mix typed params with flags
     *
     * Usage: php console.php best:mixed Alice 25 --verified --active
     */
    #[ConsoleCommand(
        name: 'best:mixed',
        description: 'Mix typed parameters with optional flags'
    )]
    public function mixedParametersAndFlags(
        ConsoleOutputInterface $output,
        string $name,
        int $age,
        ?bool $verified = null,
        ?bool $active = null
    ): ExitCode {
        $output->writeLine("Name: {$name}, Age: {$age}");

        $status = [];
        if ($verified === true) {
            $status[] = 'verified';
        }
        if ($active === true) {
            $status[] = 'active';
        }

        if (!empty($status)) {
            $output->writeLine("Status: " . implode(', ', $status));
        }

        return ExitCode::SUCCESS;
    }

    /**
     * ✅ RECOMMENDED: No framework params needed
     *
     * Usage: php console.php best:minimal Alice
     */
    #[ConsoleCommand(
        name: 'best:minimal',
        description: 'Minimal command without ConsoleOutput'
    )]
    public function minimalCommand(string $name): ExitCode
    {
        // Silent processing - no output needed
        file_put_contents('/tmp/user.txt', $name);

        return ExitCode::SUCCESS;
    }

    /**
     * ⚠️ USE SPARINGLY: ConsoleInput for variable args
     *
     * Only use ConsoleInput when you need:
     * - Variable number of arguments
     * - Raw command line access
     * - Dynamic argument handling
     *
     * Usage: php console.php best:variable file1.txt file2.txt file3.txt
     */
    #[ConsoleCommand(
        name: 'best:variable',
        description: 'Variable arguments with ConsoleInput'
    )]
    public function variableArguments(
        ConsoleInput $input,
        ConsoleOutputInterface $output
    ): ExitCode {
        $files = $input->getArguments();

        if (empty($files)) {
            $output->error('No files provided');
            return ExitCode::FAILURE;
        }

        foreach ($files as $file) {
            $output->writeLine("Processing: {$file}");
        }

        return ExitCode::SUCCESS;
    }

    /**
     * ❌ AVOID: Manual parsing with ConsoleInput
     *
     * This is the OLD style - avoid this!
     */
    #[ConsoleCommand(
        name: 'best:old-style',
        description: 'Old style (avoid this!)'
    )]
    public function oldStyleAvoid(ConsoleInput $input, ConsoleOutputInterface $output): ExitCode
    {
        // ❌ Manual parsing - no type safety
        $name = $input->getArgument('name');
        $age = (int) ($input->getArgument('age') ?? 18);

        $output->writeLine("Name: {$name}, Age: {$age}");

        return ExitCode::SUCCESS;
    }

    /**
     * ✅ BETTER: Typed parameters instead
     *
     * Prefer this over manual ConsoleInput parsing
     */
    #[ConsoleCommand(
        name: 'best:new-style',
        description: 'New style with typed parameters'
    )]
    public function newStylePrefer(
        ConsoleOutputInterface $output,
        string $name,
        int $age = 18
    ): ExitCode {
        // ✅ Already typed and validated
        $output->writeLine("Name: {$name}, Age: {$age}");

        return ExitCode::SUCCESS;
    }

    /**
     * ✅ RECOMMENDED: Complex flags example
     *
     * Shows different flag patterns
     *
     * Usage: php console.php best:complex production --dry-run --skip-backup
     */
    #[ConsoleCommand(
        name: 'best:complex',
        description: 'Complex deployment with multiple flags'
    )]
    public function complexFlags(
        ConsoleOutputInterface $output,
        string $environment,
        ?bool $dryRun = null,
        ?bool $skipBackup = null,
        ?bool $skipTests = null,
        ?bool $force = null
    ): ExitCode {
        $output->writeLine("Deploying to: {$environment}");

        // Check flags
        if ($dryRun === true) {
            $output->writeLine("DRY RUN MODE - No actual changes");
        }

        if ($skipBackup === true) {
            $output->writeLine("Skipping backup");
        } else {
            $output->writeLine("Creating backup...");
        }

        if ($skipTests === true) {
            $output->writeLine("Skipping tests");
        } else {
            $output->writeLine("Running tests...");
        }

        if ($force === true && $environment === 'production') {
            $output->warning("Force deploying to PRODUCTION!");
        }

        return ExitCode::SUCCESS;
    }
}
