<?php

namespace Ignite\Core\Console\Dev;

use Illuminate\Console\Command;

/**
 * PostSetupGit Command
 * 
 * This command handles the final step of the initial setup process by adding and committing
 * necessary files to Git version control. It manages both individual files and entire folders
 * that are essential for the base site deployment.
 */
class PostSetupGit extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'ignite:dev:post-setup-git {--no-verify : Skip Git pre-commit hooks}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Final step of the initial setup process. After completing configurations, migrations, theme scaffold, and build, this command will add and commit the necessary files to Git, preparing the base site for deployment. Run this command when you are ready to commit your initial setup to version control.';

    /**
     * Array of individual files to be added to Git.
     * These files are typically static assets and configuration files.
     *
     * @var array<string>
     */
    protected $files = [
        '.env.example',
        'public/apple-touch-icon.png',
        'public/favicon-96x96.png',
        'public/favicon.ico',
        'public/favicon.svg',
        'public/site.webmanifest',
        'public/web-app-manifest-192x192.png',
        'public/web-app-manifest-512x512.png',
    ];

    /**
     * Array of folders to be added to Git.
     * These folders contain important project configurations and resources.
     *
     * @var array<string>
     */
    protected $folders = [
        'config/',
        'modules/Program/database/migrations/',
        'public/themes/',
        'public/vendor/',
        'themes/',
        // 'resources/lang/vendor/',
    ];

    /**
     * Execute the console command.
     * 
     * This method processes both individual files and folders defined in the class properties,
     * adding them to Git version control. It then commits the changes with a descriptive message.
     *
     * @return int Returns 0 on success, 1 on failure
     */
    public function handle()
    {
        // git add the files in the files array
        foreach ($this->files as $file) {
            $this->info("Adding file: {$file}");
            $this->gitAdd($file);
        }

        // git add the folders in the folders array 
        foreach ($this->folders as $folder) {
            $this->info("Adding folder: {$folder}");
            $this->gitAdd($folder);
        }

        // git commit the changes
        $this->info("Committing changes...");
        $this->gitCommit("Initial setup complete");
        $this->gitPush();
    }

    /**
     * Add a file or folder to Git version control.
     *
     * @param string $file The path to the file or folder to be added
     * @return void
     */
    protected function gitAdd($file)
    {
        $this->info(
            shell_exec("git add {$file}")
        );
    }

    /**
     * Commit changes to Git with a specified message.
     *
     * @param string $message The commit message describing the changes
     * @return void
     */
    protected function gitCommit($message)
    {
        $this->info(
            shell_exec(
                $this->gitCommitCommand(
                    $message,
                    (bool) $this->option('no-verify')
                )
            )
        );
    }

    /**
     * Build the setup commit command.
     *
     * Verification remains enabled unless the caller explicitly opts out,
     * allowing automation to bypass hooks without weakening manual commits.
     *
     * @param string $message The commit message describing the changes.
     * @param bool $noVerify Whether Git pre-commit hooks should be skipped.
     * @return string
     */
    protected function gitCommitCommand(string $message, bool $noVerify = false): string
    {
        $verifyOption = $noVerify ? ' --no-verify' : '';

        return 'env HOME="${HOME:-/home/$(whoami)}" git commit'
            . $verifyOption
            . ' -m '
            . escapeshellarg($message);
    }

    /**
     * Push the committed changes to the remote repository.
     *
     * @return void
     */
    protected function gitPush()
    {
        $this->info(
            shell_exec("git push")
        );
    }
}
