<?php

namespace PHPNative\Ui\Widget;

use PHPNative\Framework\TextRenderer;
use PHPNative\Tailwind\Style\Text as TextStyle;

class TextInput extends Container
{
    private string $value = '';
    private string $placeholder = '';
    private bool $focused = false;
    private $onChange = null;
    private int $cursorPosition = 0;
    private float $cursorBlinkTime = 0;
    private bool $cursorVisible = true;
    private ?int $selectionStart = null;
    private ?int $selectionEnd = null;

    public function __construct(
        string $placeholder = '',
        string $style = '',
        $onChange = null,
    ) {
        parent::__construct($style);

        $this->placeholder = $placeholder;
        $this->onChange = $onChange;
    }

    public function layout(null|TextRenderer $textRenderer = null): void
    {
        // Parse styles first to get computed styles
        $this->computedStyles = \PHPNative\Tailwind\StyleParser::parse($this->style)->getValidStyles(
            \PHPNative\Tailwind\Style\MediaQueryEnum::normal,
            \PHPNative\Tailwind\Style\StateEnum::normal,
        );

        // Call parent layout
        parent::layout($textRenderer);

        // If no explicit height is set, calculate based on text size + padding
        if (!isset($this->computedStyles[\PHPNative\Tailwind\Style\Height::class])) {
            $padding = $this->computedStyles[\PHPNative\Tailwind\Style\Padding::class] ?? null;
            $paddingY = $padding ? ($padding->top + $padding->bottom) : 0;
            $textStyle = $this->computedStyles[\PHPNative\Tailwind\Style\Text::class] ?? new TextStyle();
            $fontSize = $textStyle->size;

            // Calculate text height
            $textHeight = 16; // Default font size
            if ($textRenderer !== null && $textRenderer->isInitialized()) {
                $displayText = empty($this->value) ? ($this->placeholder ?: 'A') : 'A';
                $size = $textRenderer->measureText($displayText, $fontSize);
                $textHeight = $size[1] ?? 16;
            }

            // Set height to text height + padding + borders (2px * 2)
            $this->viewport->height = (int) ($textHeight + $paddingY + 4);
            $this->contentViewport->height = max(0, (int) ($textHeight + $paddingY));
        }
    }

    public function getValue(): string
    {
        return $this->value;
    }

    public function setValue(string $value): void
    {
        $this->value = $value;
        $this->cursorPosition = mb_strlen($value);

        if ($this->onChange !== null) {
            ($this->onChange)($value);
        }
    }

    public function setOnChange(callable $onChange): void
    {
        $this->onChange = $onChange;
    }

    public function handleMouseClick(float $mouseX, float $mouseY, int $button): bool
    {
        // Check if click is within bounds
        if (
            $mouseX >= $this->viewport->x &&
            $mouseX <= ($this->viewport->x + $this->viewport->width) &&
            $mouseY >= $this->viewport->y &&
            $mouseY <= ($this->viewport->y + $this->viewport->height)
        ) {
            $this->focused = true;
            return true;
        } else {
            $this->focused = false;
            return false;
        }
    }

    public function handleTextInput(string $text): void
    {
        if (!$this->focused) {
            return;
        }

        // Delete selection if any
        if ($this->hasSelection()) {
            $this->deleteSelection();
        }

        // Insert text at cursor position
        $before = mb_substr($this->value, 0, $this->cursorPosition);
        $after = mb_substr($this->value, $this->cursorPosition);
        $this->value = $before . $text . $after;
        $this->cursorPosition += mb_strlen($text);

        if ($this->onChange !== null) {
            ($this->onChange)($this->value);
        }
    }

    public function handleKeyDown(int $keycode, int $mod = 0): bool
    {
        if (!$this->focused) {
            return false;
        }

        // Check for modifier keys
        $ctrlPressed = ($mod & \KMOD_CTRL) !== 0;
        $shiftPressed = ($mod & \KMOD_SHIFT) !== 0;

        // Handle Ctrl+A (Select All)
        if ($ctrlPressed && $keycode === \SDLK_A) {
            $this->selectionStart = 0;
            $this->selectionEnd = mb_strlen($this->value);
            return true;
        }

        // Handle Ctrl+C (Copy)
        if ($ctrlPressed && $keycode === \SDLK_C) {
            if ($this->hasSelection()) {
                $selectedText = $this->getSelectedText();
                \sdl_set_clipboard_text($selectedText);
            }
            return true;
        }

        // Handle Ctrl+X (Cut)
        if ($ctrlPressed && $keycode === \SDLK_X) {
            if ($this->hasSelection()) {
                $selectedText = $this->getSelectedText();
                \sdl_set_clipboard_text($selectedText);
                $this->deleteSelection();
            }
            return true;
        }

        // Handle Ctrl+V (Paste)
        if ($ctrlPressed && $keycode === \SDLK_V) {
            $clipboardText = \sdl_get_clipboard_text();
            if (!empty($clipboardText)) {
                // Delete selection if any
                if ($this->hasSelection()) {
                    $this->deleteSelection();
                }

                // Insert clipboard text at cursor
                $before = mb_substr($this->value, 0, $this->cursorPosition);
                $after = mb_substr($this->value, $this->cursorPosition);
                $this->value = $before . $clipboardText . $after;
                $this->cursorPosition += mb_strlen($clipboardText);

                if ($this->onChange !== null) {
                    ($this->onChange)($this->value);
                }
            }
            return true;
        }

        switch ($keycode) {
            case \SDLK_BACKSPACE:
                if ($this->hasSelection()) {
                    $this->deleteSelection();
                } elseif ($this->cursorPosition > 0) {
                    $before = mb_substr($this->value, 0, $this->cursorPosition - 1);
                    $after = mb_substr($this->value, $this->cursorPosition);
                    $this->value = $before . $after;
                    $this->cursorPosition--;

                    if ($this->onChange !== null) {
                        ($this->onChange)($this->value);
                    }
                }
                return true;

            case \SDLK_DELETE:
                if ($this->hasSelection()) {
                    $this->deleteSelection();
                } elseif ($this->cursorPosition < mb_strlen($this->value)) {
                    $before = mb_substr($this->value, 0, $this->cursorPosition);
                    $after = mb_substr($this->value, $this->cursorPosition + 1);
                    $this->value = $before . $after;

                    if ($this->onChange !== null) {
                        ($this->onChange)($this->value);
                    }
                }
                return true;

            case \SDLK_LEFT:
                if ($this->cursorPosition > 0) {
                    if ($shiftPressed) {
                        // Start or extend selection
                        if (!$this->hasSelection()) {
                            $this->selectionStart = $this->cursorPosition;
                        }
                        $this->cursorPosition--;
                        $this->selectionEnd = $this->cursorPosition;
                    } else {
                        // Clear selection and move cursor
                        if ($this->hasSelection()) {
                            // Move cursor to start of selection
                            $this->cursorPosition = min($this->selectionStart, $this->selectionEnd);
                            $this->clearSelection();
                        } else {
                            $this->cursorPosition--;
                        }
                    }
                }
                return true;

            case \SDLK_RIGHT:
                if ($this->cursorPosition < mb_strlen($this->value)) {
                    if ($shiftPressed) {
                        // Start or extend selection
                        if (!$this->hasSelection()) {
                            $this->selectionStart = $this->cursorPosition;
                        }
                        $this->cursorPosition++;
                        $this->selectionEnd = $this->cursorPosition;
                    } else {
                        // Clear selection and move cursor
                        if ($this->hasSelection()) {
                            // Move cursor to end of selection
                            $this->cursorPosition = max($this->selectionStart, $this->selectionEnd);
                            $this->clearSelection();
                        } else {
                            $this->cursorPosition++;
                        }
                    }
                }
                return true;

            case \SDLK_HOME:
                if ($shiftPressed) {
                    // Extend selection to start
                    if (!$this->hasSelection()) {
                        $this->selectionStart = $this->cursorPosition;
                    }
                    $this->cursorPosition = 0;
                    $this->selectionEnd = $this->cursorPosition;
                } else {
                    $this->cursorPosition = 0;
                    $this->clearSelection();
                }
                return true;

            case \SDLK_END:
                if ($shiftPressed) {
                    // Extend selection to end
                    if (!$this->hasSelection()) {
                        $this->selectionStart = $this->cursorPosition;
                    }
                    $this->cursorPosition = mb_strlen($this->value);
                    $this->selectionEnd = $this->cursorPosition;
                } else {
                    $this->cursorPosition = mb_strlen($this->value);
                    $this->clearSelection();
                }
                return true;

            case \SDLK_RETURN:
                // Enter key - can be handled by parent
                return false;
        }

        return false;
    }

    public function isFocused(): bool
    {
        return $this->focused;
    }

    public function focus(): void
    {
        $this->focused = true;
    }

    public function blur(): void
    {
        $this->focused = false;
        $this->clearSelection();
    }

    private function hasSelection(): bool
    {
        return $this->selectionStart !== null &&
               $this->selectionEnd !== null &&
               $this->selectionStart !== $this->selectionEnd;
    }

    private function getSelectedText(): string
    {
        if (!$this->hasSelection()) {
            return '';
        }

        $start = min($this->selectionStart, $this->selectionEnd);
        $end = max($this->selectionStart, $this->selectionEnd);

        return mb_substr($this->value, $start, $end - $start);
    }

    private function deleteSelection(): void
    {
        if (!$this->hasSelection()) {
            return;
        }

        $start = min($this->selectionStart, $this->selectionEnd);
        $end = max($this->selectionStart, $this->selectionEnd);

        $before = mb_substr($this->value, 0, $start);
        $after = mb_substr($this->value, $end);
        $this->value = $before . $after;
        $this->cursorPosition = $start;

        $this->clearSelection();

        if ($this->onChange !== null) {
            ($this->onChange)($this->value);
        }
    }

    private function clearSelection(): void
    {
        $this->selectionStart = null;
        $this->selectionEnd = null;
    }

    public function render(&$renderer, null|TextRenderer $textRenderer = null): void
    {
        // Render background with focus indicator
        if ($this->focused) {
            // Focused: blue border
            sdl_set_render_draw_color($renderer, 59, 130, 246, 255); // Blue-500
        } else {
            // Not focused: gray border
            sdl_set_render_draw_color($renderer, 209, 213, 219, 255); // Gray-300
        }

        // Draw border
        sdl_render_fill_rect($renderer, [
            'x' => $this->viewport->x,
            'y' => $this->viewport->y,
            'w' => $this->viewport->width,
            'h' => $this->viewport->height,
        ]);

        // Draw white background inside
        sdl_set_render_draw_color($renderer, 255, 255, 255, 255);
        sdl_render_fill_rect($renderer, [
            'x' => $this->viewport->x + 2,
            'y' => $this->viewport->y + 2,
            'w' => $this->viewport->width - 4,
            'h' => $this->viewport->height - 4,
        ]);

        $textStyle = $this->computedStyles[\PHPNative\Tailwind\Style\Text::class] ?? new TextStyle();
        $fontSize = $textStyle->size;

        // Render selection highlight
        if ($this->hasSelection() && $textRenderer !== null && $textRenderer->isInitialized()) {
            $start = min($this->selectionStart, $this->selectionEnd);
            $end = max($this->selectionStart, $this->selectionEnd);

            $textBeforeSelection = mb_substr($this->value, 0, $start);
            $selectedText = mb_substr($this->value, $start, $end - $start);

            $selectionX = $this->viewport->x + 6;
            if (!empty($textBeforeSelection)) {
                $size = $textRenderer->measureText($textBeforeSelection, $fontSize);
                $selectionX += $size[0];
            }

            $selectionWidth = 0;
            if (!empty($selectedText)) {
                $size = $textRenderer->measureText($selectedText, $fontSize);
                $selectionWidth = $size[0];
            }

            // Draw selection background (blue)
            sdl_set_render_draw_color($renderer, 59, 130, 246, 100); // Blue with transparency
            sdl_render_fill_rect($renderer, [
                'x' => $selectionX,
                'y' => $this->viewport->y + 4,
                'w' => $selectionWidth,
                'h' => $this->viewport->height - 8,
            ]);
        }

        // Render text or placeholder
        if ($textRenderer !== null && $textRenderer->isInitialized()) {
            $displayText = empty($this->value) ? $this->placeholder : $this->value;
            $textX = $this->viewport->x + 6;
            $textY = $this->viewport->y + 6;

            // Set color: gray for placeholder, black for text
            if (empty($this->value)) {
                $textRenderer->setColor(156/255, 163/255, 175/255, 1.0); // Gray-400
            } else {
                $textRenderer->setColor(0, 0, 0, 1.0); // Black
            }

            $textRenderer->drawText($displayText, (int) $textX, (int) $textY, $fontSize);
        }

        // Render cursor if focused
        if ($this->focused && $this->cursorVisible && $textRenderer) {
            // Calculate cursor position
            $textBeforeCursor = mb_substr($this->value, 0, $this->cursorPosition);
            $cursorX = $this->viewport->x + 6; // Left padding

            if (!empty($textBeforeCursor)) {
                $size = $textRenderer->measureText($textBeforeCursor, $fontSize);
                $cursorX += $size[0];
            }

            // Draw cursor
            sdl_set_render_draw_color($renderer, 0, 0, 0, 255);
            sdl_render_fill_rect($renderer, [
                'x' => $cursorX,
                'y' => $this->viewport->y + 4,
                'w' => 2,
                'h' => $this->viewport->height - 8,
            ]);
        }

        // Don't render children - we handle text rendering directly
    }
}
