<?php

declare(strict_types=1);

namespace App\Framework\Console\Components;

use App\Framework\Console\CommandGroupRegistry;
use App\Framework\Console\CommandHistory;
use App\Framework\Console\ConsoleColor;
use App\Framework\Console\ConsoleOutputInterface;
use App\Framework\Console\ExitCode;
use App\Framework\Console\Screen\CursorControlCode;
use App\Framework\Console\Screen\ScreenControlCode;
use App\Framework\Console\SimpleWorkflowExecutor;
use App\Framework\Console\TuiView;
use App\Framework\DI\Container;
use App\Framework\Discovery\Results\DiscoveryRegistry;

/**
 * Main TUI orchestrator - coordinates specialized components
 * Refactored to follow Single Responsibility Principle
 */
final readonly class ConsoleTUI
{
    public function __construct(
        private ConsoleOutputInterface $output,
        private Container $container,
        private DiscoveryRegistry $discoveryRegistry,
        private TuiState $state,
        private TuiRenderer $renderer,
        private TuiInputHandler $inputHandler,
        private TuiCommandExecutor $commandExecutor,
        private CommandHistory $commandHistory,
        private CommandGroupRegistry $groupRegistry,
        private SimpleWorkflowExecutor $workflowExecutor
    ) {
    }

    /**
     * Run the interactive TUI
     */
    public function run(): ExitCode
    {
        $this->initialize();
        $this->mainLoop();
        $this->cleanup();

        return ExitCode::SUCCESS;
    }

    /**
     * Initialize TUI system
     */
    private function initialize(): void
    {
        $this->setupTerminal();
        $this->showWelcomeScreen();
        $this->loadCommands();
        $this->state->setRunning(true);
    }

    /**
     * Main event loop
     */
    private function mainLoop(): void
    {
        while ($this->state->isRunning()) {
            $this->renderCurrentView();
            $this->handleUserInput();
        }
    }

    /**
     * Cleanup and restore terminal
     */
    private function cleanup(): void
    {
        $this->restoreTerminal();
        $this->output->writeLine('');
        $this->output->writeLine('👋 Console session ended. Goodbye!');
    }

    /**
     * Setup terminal for interactive mode
     */
    private function setupTerminal(): void
    {
        $this->output->screen->setInteractiveMode();
        $this->setRawMode(true);
        $this->output->write(CursorControlCode::HIDE->format());

        // Welcome message
        $this->output->write(ScreenControlCode::CLEAR_ALL->format());
        $this->output->write(CursorControlCode::POSITION->format(1, 1));
    }

    /**
     * Restore terminal to normal mode
     */
    private function restoreTerminal(): void
    {
        $this->setRawMode(false);
        $this->output->write(CursorControlCode::SHOW->format());
        $this->output->screen->setInteractiveMode(false);
    }

    /**
     * Load and categorize all available commands
     */
    private function loadCommands(): void
    {
        // Use the new CommandGroupRegistry for organized commands
        $categories = $this->groupRegistry->getOrganizedCommands();
        $this->state->setCategories($categories);

        // Load available workflows
        $workflows = $this->groupRegistry->getWorkflows();
        $this->state->setWorkflows($workflows);
    }

    /**
     * Render the current view
     */
    private function renderCurrentView(): void
    {
        $this->renderer->render($this->state, $this->commandHistory);
    }

    /**
     * Handle user input
     */
    private function handleUserInput(): void
    {
        $key = $this->readKey();

        if ($key !== '') {
            // Handle form mode specially
            if ($this->state->getCurrentView() === TuiView::FORM) {
                $this->handleFormMode();

                return;
            }

            $this->inputHandler->handleInput($key, $this->state, $this->commandHistory);
        }
    }

    /**
     * Handle form mode interaction
     */
    private function handleFormMode(): void
    {
        $command = $this->state->getSelectedCommandForForm();
        if ($command) {
            $this->commandExecutor->startInteractiveForm($command, $this->state);
        }
    }

    /**
     * Read a single key from input (including multi-byte escape sequences)
     * Enhanced for PHPStorm terminal compatibility
     */
    private function readKey(): string
    {
        $key = fgetc(STDIN);
        if ($key === false) {
            return '';
        }

        // Handle escape sequences (arrow keys, etc.)
        if ($key === "\033") {
            $sequence = $key;

            // Use non-blocking read for better compatibility
            $originalBlocking = stream_get_meta_data(STDIN)['blocked'] ?? true;
            stream_set_blocking(STDIN, false);

            // Read the next character with small timeout
            $next = fgetc(STDIN);
            if ($next === false) {
                // Wait a bit and try again (PHPStorm sometimes needs this)
                usleep(10000); // 10ms
                $next = fgetc(STDIN);
            }

            if ($next !== false) {
                $sequence .= $next;

                // If it's a bracket, read more
                if ($next === '[') {
                    $third = fgetc(STDIN);
                    if ($third === false) {
                        usleep(10000); // 10ms
                        $third = fgetc(STDIN);
                    }

                    if ($third !== false) {
                        $sequence .= $third;

                        // Some sequences have more characters (like Page Up/Down)
                        if (in_array($third, ['5', '6', '3', '1', '2', '4'])) {
                            $fourth = fgetc(STDIN);
                            if ($fourth === false) {
                                usleep(5000); // 5ms
                                $fourth = fgetc(STDIN);
                            }
                            if ($fourth !== false) {
                                $sequence .= $fourth;
                            }
                        }
                    }
                }
            }

            // Restore blocking mode
            stream_set_blocking(STDIN, $originalBlocking);

            return $sequence;
        }

        return $key;
    }

    /**
     * Show welcome screen and wait for user input
     */
    private function showWelcomeScreen(): void
    {
        $this->output->write(ScreenControlCode::CLEAR_ALL->format());
        $this->output->write(CursorControlCode::POSITION->format(1, 1));

        $this->output->writeLine('');
        $this->output->writeLine('🚀 Welcome to Interactive Console', ConsoleColor::BRIGHT_CYAN);
        $this->output->writeLine('═══════════════════════════════════', ConsoleColor::GRAY);
        $this->output->writeLine('');
        $this->output->writeLine('Navigate through categories and commands using:');
        $this->output->writeLine('  ↑/↓ Arrow Keys - Navigate up and down');
        $this->output->writeLine('  Enter         - Select/Execute');
        $this->output->writeLine('  /             - Search commands');
        $this->output->writeLine('  R             - Command history');
        $this->output->writeLine('  Q/Esc         - Quit');
        $this->output->writeLine('');
        $this->output->writeLine('Press any key to continue...', ConsoleColor::YELLOW);

        // Wait for user input
        $this->readKey();
    }

    /**
     * Set terminal raw mode with PHPStorm compatibility
     */
    private function setRawMode(bool $enabled): void
    {
        if (! function_exists('shell_exec')) {
            return;
        }

        // Detect PHPStorm/JetBrains terminal
        $isPhpStorm = getenv('TERMINAL_EMULATOR') === 'JetBrains-JediTerm' ||
                      ! empty(getenv('IDE_PROJECT_ROOTS')) ||
                      strpos(getenv('TERM') ?: '', 'jetbrains') !== false;

        if ($enabled) {
            if ($isPhpStorm) {
                // PHPStorm-optimized settings
                shell_exec('stty raw -echo min 1 time 0 2>/dev/null');
            } else {
                // Standard terminal settings
                shell_exec('stty -icanon -echo 2>/dev/null');
            }
        } else {
            if ($isPhpStorm) {
                // PHPStorm-optimized restore
                shell_exec('stty -raw echo 2>/dev/null');
            } else {
                // Standard terminal restore
                shell_exec('stty icanon echo 2>/dev/null');
            }
        }
    }
}
