<?php

namespace App\Commands;

use App\Services\Command;
use Illuminate\Process\Pipe;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Process;
use MirazMac\DotEnv\Writer as EnvWriter;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\error;
use function Laravel\Prompts\info;
use function Laravel\Prompts\spin;
use function Laravel\Prompts\text;

class Create extends Command
{
    protected $signature = 'create';
    protected $description = 'Create a new project';

    protected array $notifications = [];
    protected array $op = [];


    protected array $flags = [
        'clone'    => true,
        'push'     => true,
        'git_init' => true,
        'git_push' => true,
    ];

    private function hasFlag(string $flag): bool
    {
        return in_array($flag, $this->flags) && $this->flags[$flag] === true;
    }

    private function logNotification(string $type, string $message): void
    {
        $this->notifications[] = [
            'type'    => $type,
            'message' => $message,
        ];

        $this->{$type}($message);
    }

    private function logOP($output): void
    {
        $this->op[] = $output;
    }

    private function cloneStarter(): bool
    {
        $gitClone = Process::forever()->run('git clone git@github.com:probots-io/probots-wp-starter-2024.git .', function (string $type, string $output) {
            $this->logOP($output);
        });

        if (!$gitClone->successful()) {
            $this->logNotification('error', 'Error cloning project');
            return false;
        }

        return true;
    }


    private function initializeGit($repositoryUrl): bool
    {
        $result = Process::pipe(static function (Pipe $pipe) use ($repositoryUrl) {
            $pipe->command('git init');
            $pipe->command('git remote add origin ' . $repositoryUrl);
            $pipe->command('git add .');
            $pipe->command('git commit -m "Initial commit"');
        }, function ($string, $output) {
            $this->logOP($output);
        });

        if (!$result->successful()) {
            return false;
        }

        if (!$this->hasFlag('git_push')) {
            return true;
        }

        $result = Process::forever()->run('git push -u origin master --force', function ($string, $output) {
            $this->logOP($output);
        });

        if (!$result->successful()) {
            return false;
        }

        return true;
    }

    public function getLatestWordpressVersion(): string
    {
        $versions = Http::get('https://api.wordpress.org/core/version-check/1.7/');

        return $versions->json('offers.0.version');
    }

    public function handle(): void
    {

        /**
         * Todo:
         * Check if standalone project, if it is we need to add a build direct and add the volume to the docker-compose file
         *
         */

        $result = Process::run('ls -A1 | wc -l');
        $isEmpty = trim($result->output()) === '0';

        if(!$isEmpty) {
            $confirmed = confirm(
                label: 'The current folder is not empty. Are you sure you want to continue? The folder will be deleted and recreated.',
                default: false,
                yes: 'Ok, go on.',
                no: 'Nooooo, cancel',
                hint: sprintf('Folder: %s', getcwd())
            );

            if(!$confirmed) {
                return;
            }

        }




        // Ask user for repository url
        $repositoryUrl = text(
            label: 'What is the new projects repository ssh url?',
            placeholder: 'git@github.com:probots-io/xxx.git',
            default: 'git@github.com:probots-io/test-wp-cli.git',
            hint: 'Copy and paste the url from the repository settings page'
        );

        $slug = text(
            label: 'What is the new projects slug?',
            placeholder: 'text-wp-cli',
            default: 'project-slug',
            hint: 'The slug of the project'
        );

        $url = text(
            label: 'What is the local url?',
            placeholder: 'xxx.prbts',
            default: $slug . '.prbts',
            hint: 'How do you want to reach your local site'
        );

        $dbName = text(
            label: 'What is the database name?',
            placeholder: 'wordpress',
            default: $slug,
            hint: 'Database Name'
        );

        $dbHost = text(
            label: 'What is the database name?',
            placeholder: 'wordpress',
            default: 'host.db.docker.internal:7689',
            hint: 'Database Host with Port'
        );

        $wordpress = text(
            label: 'Wordpress Version?',
            placeholder: 'pick a specific version, like 6.7.1 or use latest',
            default: 'latest',
            hint: ''
        );


        if ($wordpress === 'latest') {
            $wordpress = $this->getLatestWordpressVersion();
        }


        // Remove all files
        if ($forceFlush) {
            Process::forever()->run('rm -rf .* *');
        }

        if ($this->hasFlag('clone')) {

            // Clone wp starter
            $response = spin(
                callback: fn() => $this->cloneStarter(),
                message: 'Cloning Starter Package...'
            );

            if (!$response) {
                error('Error cloning starter');
                return;
            }

            info('✓ Starter cloned successfully');

        } else {
            Process::forever()->run('touch text.txt');
        }

        // RM .git folder
        Process::forever()->run('rm -rf .git');


        if ($this->hasFlag('git_init')) {
            // Initialize git
            $response = spin(
                callback: fn() => $this->initializeGit($repositoryUrl),
                message: 'Initializing git repository...'
            );

            if (!$response) {
                error('Error initializing git repository');
                return;
            }

            info('✓ Repository initialized successfully');
        }


        // Copy env.example to .env
        Process::forever()->run('rm -rf.env');

        $envExamplePath = getcwd() . '/.env.example';
        $envPath = getcwd() . '/.env';


        $writer = new EnvWriter($envExamplePath);

        $basePort = random_int(8001, 8999);

        // Replace env vars
        $writer->set('VIRTUAL_HOST', $url);

        $writer->set('PORT_WP', $basePort);
        $writer->set('PORT_DEV', $basePort + 1);

        $writer->set('DB_NAME', $dbName);
        $writer->set('DB_HOST', $dbHost);

        $writer->set('CDN_URL', sprintf('http://%s/media', $url));

        $writer->set('WORDPRESS_VERSION', $wordpress);

        $writer->set('THEME_NAME', $slug);

        $writer->write(true, $envPath);


        // Starting Docker containers
        $response = spin(
            callback: fn() => Process::forever()->run('docker compose up -d'),
            message: 'Starting Docker containers...'
        );

        if (!$response) {
            error('Error starting docker containers');
            return;
        }

        info('✓ Containers started');

        spin(
            callback: fn() => sleep(5),
            message: 'Waiting for containers to start...'
        );

        // Create Database
        spin(
            callback: fn() => Process::forever()->run('docker compose exec wp mysql -h host.db.docker.internal -P 7689 -u root -e "CREATE DATABASE  IF NOT EXISTS $DB_NAME;"'),
            message: 'Trying to create database...'
        );


        // Installing Yarn
        spin(
            callback: fn() => $this->call('Yarn', ['commands' => ['install']]),
            message: 'Running Yarn Install...'
        );

        // Installing Wordpress
//        spin(
//            callback: fn() => $this->call('Run', ['bin' => ['install']]),
//            message: 'Installing Wordpress...'
//        );


        info('Done. Please run wp install to install wordpress.');
        info(sprintf('Afterwards your site is available at http://%s', $url));

    }
}


