<?php

namespace PHPNative\Ui\Widget;

use PHPNative\Framework\TextRenderer;
use PHPNative\Tailwind\Style\Basis;
use PHPNative\Tailwind\Style\DirectionEnum;
use PHPNative\Tailwind\Style\Flex;
use PHPNative\Tailwind\Style\FlexTypeEnum;
use PHPNative\Tailwind\Style\Height;
use PHPNative\Tailwind\Style\Unit;
use PHPNative\Tailwind\Style\Width;
use PHPNative\Ui\Component;
use PHPNative\Ui\Viewport;

class Container extends Component
{
    // Scroll state
    private float $scrollX = 0;
    private float $scrollY = 0;
    private float $contentWidth = 0;
    private float $contentHeight = 0;

    // Scrollbar state
    private bool $isDraggingScrollbarX = false;
    private bool $isDraggingScrollbarY = false;
    private float $dragStartX = 0;
    private float $dragStartY = 0;
    private float $scrollStartX = 0;
    private float $scrollStartY = 0;

    // Scrollbar dimensions
    private const SCROLLBAR_WIDTH = 16;
    private const SCROLLBAR_MIN_SIZE = 20;

    public function __construct(string $style = '')
    {
        parent::__construct($style);
    }

    /**
     * Clear all child components
     */
    public function clearChildren(): void
    {
        $this->children = [];
        $this->contentWidth = 0;
        $this->contentHeight = 0;
        $this->scrollX = 0;
        $this->scrollY = 0;
    }

    public function layout(null|TextRenderer $textRenderer = null): void
    {
        // Call parent to compute styles and setup viewports
        parent::layout($textRenderer);
        // Check if container has explicit width/height or is a flex child
        $flexStyle = $this->computedStyles[Flex::class] ?? null;
        $hasFlexGrow = $flexStyle && $flexStyle->type !== FlexTypeEnum::none;

        // Check if overflow is set (if yes, container should not auto-expand)
        $overflow = $this->computedStyles[\PHPNative\Tailwind\Style\Overflow::class] ?? null;
        $hasOverflowX =
            $overflow &&
            in_array($overflow->x, [
                \PHPNative\Tailwind\Style\OverflowEnum::scroll,
                \PHPNative\Tailwind\Style\OverflowEnum::auto,
            ]);
        $hasOverflowY =
            $overflow &&
            in_array($overflow->y, [
                \PHPNative\Tailwind\Style\OverflowEnum::scroll,
                \PHPNative\Tailwind\Style\OverflowEnum::auto,
            ]);

        // A container is a flex container if it has flex/flex-row/flex-col in style
        // (but not flex-1, flex-auto, flex-none which make it a flex child)
        $isFlexContainer =
            $flexStyle &&
            (
                preg_match('/\bflex-row\b/', $this->style) ||
                    preg_match('/\bflex-col\b/', $this->style) ||
                    preg_match('/(?<![a-z-])flex(?![a-z-])/', $this->style)
            );

        // If overflow is set, treat it as explicit size (don't auto-expand)
        $hasExplicitWidth =
            isset($this->computedStyles[Width::class]) ||
            isset($this->computedStyles[Basis::class]) ||
            $hasFlexGrow ||
            $hasOverflowX;
        $hasExplicitHeight =
            isset($this->computedStyles[Height::class]) ||
            isset($this->computedStyles[Basis::class]) ||
            $hasFlexGrow ||
            $hasOverflowY;

        // Check if this container has flex layout
        if ($isFlexContainer) {
            $this->layoutChildren($flexStyle, $textRenderer);
        } else {
            // Non-flex layout: stack children vertically
            $currentY = $this->contentViewport->y;

            foreach ($this->children as $child) {
                // Skip overlays in normal layout flow
                if ($child->isOverlay()) {
                    continue;
                }

                // Create a viewport for the child with available width but let height be determined by child
                $childViewport = new Viewport(
                    x: $this->contentViewport->x,
                    y: (int) $currentY,
                    width: $this->contentViewport->width,
                    height: $this->contentViewport->height,
                    windowWidth: $this->contentViewport->windowWidth,
                    windowHeight: $this->contentViewport->windowHeight,
                    uiScale: $this->contentViewport->uiScale,
                );

                $child->setViewport($childViewport);
                $child->layout($textRenderer);

                // Get the actual height after layout
                $actualHeight = $child->getViewport()->height;
                $currentY += $actualHeight;
            }
        }

        // Layout overlays separately (they position themselves)
        foreach ($this->children as $child) {
            if ($child->isOverlay()) {
                // Overlays always get a full-window viewport; they will decide inner layout themselves
                $overlayViewport = new Viewport(
                    x: 0,
                    y: 0,
                    width: $this->contentViewport->windowWidth,
                    height: $this->contentViewport->windowHeight,
                    windowWidth: $this->contentViewport->windowWidth,
                    windowHeight: $this->contentViewport->windowHeight,
                    uiScale: $this->contentViewport->uiScale,
                );
                $child->setViewport($overlayViewport);
                $child->setContentViewport(clone $overlayViewport);
                $child->layout($textRenderer);
            }
        }

        // Calculate total content size after children are laid out
        $this->calculateContentSize();

        // Adjust viewport to content size if no explicit size
        // But limit to available parent size (for proper overflow/scrolling)
        $padding = $this->computedStyles[\PHPNative\Tailwind\Style\Padding::class] ?? null;
        $paddingX = $padding ? ($padding->left + $padding->right) : 0;
        $paddingY = $padding ? ($padding->top + $padding->bottom) : 0;

        // Store original available size before adjustment
        $availableWidth = $this->viewport->width;
        $availableHeight = $this->viewport->height;

        if (!$hasExplicitWidth) {
            // Set viewport to min(contentSize + padding, availableSize)
            $desiredWidth = $this->contentWidth + $paddingX;
            $this->viewport->width = (int) min($desiredWidth, $availableWidth);
            $this->contentViewport->width = max(0, $this->viewport->width - ((int) $paddingX));
        }

        if (!$hasExplicitHeight) {
            // Set viewport to content height + padding (don't expand to fill available space unnecessarily)
            $desiredHeight = $this->contentHeight + $paddingY;
            // Only limit to availableHeight if we're not trying to measure natural size
            $this->viewport->height = (int) $desiredHeight;
            $this->contentViewport->height = max(0, $this->viewport->height - ((int) $paddingY));
        }
    }

    private function layoutChildren(Flex $flex, null|TextRenderer $textRenderer): void
    {
        if (empty($this->children)) {
            return;
        }

        $isRow = $flex->direction === DirectionEnum::row;
        $availableSpace = $isRow ? $this->contentViewport->width : $this->contentViewport->height;

        // Get gap from styles
        $gap = $this->computedStyles[\PHPNative\Tailwind\Style\Gap::class] ?? null;
        $gapSize = 0;
        if ($gap) {
            $gapSize = $isRow ? $gap->x : $gap->y;
        }

        // First pass: calculate fixed sizes and count flex-grow items
        $childSizes = [];
        $flexGrowCount = 0;
        $usedSpace = 0;
        $nonOverlayCount = 0;

        // Count non-overlay children first
        foreach ($this->children as $child) {
            if (!$child->isOverlay()) {
                $nonOverlayCount++;
            }
        }

        // Add gap space to used space (n-1 gaps for n children)
        if ($nonOverlayCount > 1 && $gapSize > 0) {
            $usedSpace += ($nonOverlayCount - 1) * $gapSize;
        }

        foreach ($this->children as $index => $child) {
            // Skip overlays in flex layout
            if ($child->isOverlay()) {
                continue;
            }
            // Parse child styles to get basis, width, height, and flex
            $childStyles = \PHPNative\Tailwind\StyleParser::parse($child->style)->getValidStyles(
                \PHPNative\Tailwind\Style\MediaQueryEnum::normal,
                \PHPNative\Tailwind\Style\StateEnum::normal,
            );

            $childFlex = $childStyles[Flex::class] ?? null;
            $basis = $childStyles[Basis::class] ?? null;
            $width = $childStyles[Width::class] ?? null;
            $height = $childStyles[Height::class] ?? null;

            // Track explicit cross-axis sizing so we don't stretch components unintentionally.
            $crossSize = null;
            $hasExplicitCrossSize = false;
            if ($isRow && $height) {
                $crossSize = $this->calculateSize($height, $this->contentViewport->height);
                $hasExplicitCrossSize = true;
            } elseif (!$isRow && $width) {
                $crossSize = $this->calculateSize($width, $this->contentViewport->width);
                $hasExplicitCrossSize = true;
            }

            $size = 0;
            $hasExplicitSize = false;

            // Check if child has flex-grow
            if ($childFlex && $childFlex->type !== FlexTypeEnum::none) {
                $flexGrowCount++;
                $childSizes[$index] = [
                    'size' => 0,
                    'flexGrow' => true,
                    'natural' => false,
                    'crossSize' => $crossSize,
                    'crossExplicit' => $hasExplicitCrossSize,
                ];
            } else {
                // Calculate fixed size from basis, width, or height
                if ($basis) {
                    $size = $this->calculateSize($basis, $availableSpace);
                    $hasExplicitSize = true;
                } elseif ($isRow && $width) {
                    $size = $this->calculateSize($width, $availableSpace);
                    $hasExplicitSize = true;
                } elseif (!$isRow && $height) {
                    $size = $this->calculateSize($height, $availableSpace);
                    $hasExplicitSize = true;
                }

                if (!$hasExplicitSize) {
                    // Need to measure natural size - do a temporary layout
                    // For flex-col without explicit height, give minimal space to measure intrinsic size
                    // For flex-row without explicit width, give minimal space to measure intrinsic size
                    $tempViewport = new Viewport(
                        x: $this->contentViewport->x,
                        y: $this->contentViewport->y,
                        width: $isRow ? 9999 : $this->contentViewport->width,
                        height: $isRow ? $this->contentViewport->height : 9999,
                        windowWidth: $this->contentViewport->windowWidth,
                        windowHeight: $this->contentViewport->windowHeight,
                        uiScale: $this->contentViewport->uiScale,
                    );
                    $child->setViewport($tempViewport);
                    $child->layout($textRenderer);

                    // Get natural size (the actual size the child computed after layout)
                    $size = $isRow ? $child->getViewport()->width : $child->getViewport()->height;
                }

                $usedSpace += $size;
                $childSizes[$index] = [
                    'size' => $size,
                    'flexGrow' => false,
                    'natural' => !$hasExplicitSize,
                    'crossSize' => $crossSize,
                    'crossExplicit' => $hasExplicitCrossSize,
                ];
            }
        }

        // Calculate remaining space for flex-grow items
        $remainingSpace = max(0, $availableSpace - $usedSpace);
        $flexGrowSize = $flexGrowCount > 0 ? ($remainingSpace / $flexGrowCount) : 0;

        // Second pass: assign sizes and position children
        $currentPosition = $isRow ? $this->contentViewport->x : $this->contentViewport->y;
        $childIndex = 0;

        foreach ($this->children as $index => $child) {
            // Skip overlays in flex layout
            if ($child->isOverlay()) {
                continue;
            }

            $childSize = $childSizes[$index];
            $size = $childSize['flexGrow'] ? $flexGrowSize : $childSize['size'];
            $crossSize = $childSize['crossSize'] ?? null;
            $hasExplicitCrossSize = $childSize['crossExplicit'] ?? false;

            // Add gap before this child (except for first child)
            if ($childIndex > 0 && $gapSize > 0) {
                $currentPosition += $gapSize;
            }

            // Create viewport for child
            if ($isRow) {
                // Flex row
                $childHeight = $hasExplicitCrossSize && $crossSize !== null
                    ? min($crossSize, $this->contentViewport->height)
                    : $this->contentViewport->height;

                $childViewport = new Viewport(
                    x: (int) $currentPosition,
                    y: $this->contentViewport->y,
                    width: $size,
                    height: $childHeight,
                    windowWidth: $this->contentViewport->windowWidth,
                    windowHeight: $this->contentViewport->windowHeight,
                    uiScale: $this->contentViewport->uiScale,
                );
                $currentPosition += $size;
            } else {
                $childWidth = $hasExplicitCrossSize && $crossSize !== null
                    ? min($crossSize, $this->contentViewport->width)
                    : $this->contentViewport->width;

                // Flex column
                $childViewport = new Viewport(
                    x: $this->contentViewport->x,
                    y: (int) $currentPosition,
                    width: $childWidth,
                    height: $size,
                    windowWidth: $this->contentViewport->windowWidth,
                    windowHeight: $this->contentViewport->windowHeight,
                    uiScale: $this->contentViewport->uiScale,
                );
                $currentPosition += $size;
            }

            $child->setViewport($childViewport);
            $child->layout($textRenderer);
            $childIndex++;
        }
    }

    private function calculateSize(Width|Height|Basis $style, float $availableSpace): float
    {
        return match ($style->unit) {
            Unit::Pixel => ((float) $style->value) * $this->contentViewport->uiScale,
            Unit::Point => (float) $style->value,
            Unit::Percent => ($availableSpace * $style->value) / 100,
        };
    }

    private function calculateContentSize(): void
    {
        if (empty($this->children)) {
            // No children: content size is 0
            $this->contentWidth = 0;
            $this->contentHeight = 0;
            return;
        }

        $maxX = 0;
        $maxY = 0;

        foreach ($this->children as $child) {
            // Skip overlays - they don't contribute to content size
            if ($child->isOverlay()) {
                continue;
            }

            $childViewport = $child->getViewport();
            $maxX = max($maxX, ($childViewport->x + $childViewport->width) - $this->contentViewport->x);
            $maxY = max($maxY, ($childViewport->y + $childViewport->height) - $this->contentViewport->y);
        }

        // Content size is the actual space used by children within contentViewport
        $this->contentWidth = $maxX;
        $this->contentHeight = $maxY;
    }

    private function hasOverflow(): array
    {
        $overflow = $this->computedStyles[\PHPNative\Tailwind\Style\Overflow::class] ?? null;
        if (!$overflow) {
            return ['x' => false, 'y' => false];
        }

        $needsScrollX = $this->contentWidth > $this->contentViewport->width;
        $needsScrollY = $this->contentHeight > $this->contentViewport->height;

        return [
            'x' =>

                    $needsScrollX &&
                    in_array($overflow->x, [
                        \PHPNative\Tailwind\Style\OverflowEnum::scroll,
                        \PHPNative\Tailwind\Style\OverflowEnum::auto,
                    ])
                ,
            'y' =>

                    $needsScrollY &&
                    in_array($overflow->y, [
                        \PHPNative\Tailwind\Style\OverflowEnum::scroll,
                        \PHPNative\Tailwind\Style\OverflowEnum::auto,
                    ])
                ,
        ];
    }

    public function render(&$renderer, null|TextRenderer $textRenderer = null): void
    {
        parent::render($renderer, $textRenderer);
    }

    public function renderContent(&$renderer, null|TextRenderer $textRenderer = null): void
    {
        if (!$this->visible) {
            return;
        }

        // First pass: Render shadows of all children (behind them)
        foreach ($this->children as $child) {
            if (!$child->isOverlay() && method_exists($child, 'renderShadowIfPresent')) {
                $child->renderShadowIfPresent($renderer);
            }
        }

        $overflow = $this->hasOverflow();

        // Save original viewport
        $originalViewport = $this->contentViewport;

        // Apply scroll offset to children
        if ($overflow['x'] || $overflow['y']) {
            // Enable clipping
            $scissorX = (int) $this->contentViewport->x;
            $scissorY = (int) $this->contentViewport->y;
            $scissorW = (int) $this->contentViewport->width;
            $scissorH = (int) $this->contentViewport->height;

            // SDL3: Set clip rect for clipping
            sdl_set_render_clip_rect($renderer, [
                'x' => $scissorX,
                'y' => $scissorY,
                'w' => $scissorW,
                'h' => $scissorH,
            ]);

            // Render children with scroll offset (skip overlays)
            foreach ($this->children as $child) {
                // Skip overlays - they'll be rendered later
                if ($child->isOverlay()) {
                    continue;
                }

                // Apply scroll offset recursively to child and all its descendants
                $child->applyScrollOffset((int) $this->scrollX, (int) $this->scrollY);

                // Performance optimization: skip completely invisible children
                $childViewport = $child->getViewport();
                $isVisible =
                    ($childViewport->x + $childViewport->width) > $scissorX &&
                    $childViewport->x < ($scissorX + $scissorW) &&
                    ($childViewport->y + $childViewport->height) > $scissorY &&
                    $childViewport->y < ($scissorY + $scissorH);

                if ($isVisible) {
                    $child->render($renderer, $textRenderer);
                    $child->renderContent($renderer, $textRenderer);
                }

                // Restore by applying negative offset
                $child->applyScrollOffset((int) -$this->scrollX, (int) -$this->scrollY);
            }

            // Disable clipping
            sdl_set_render_clip_rect($renderer, null);

            // Render scrollbars
            $this->renderScrollbars($renderer, $overflow);
        } else {
            // No overflow, render normally (skip overlays)
            foreach ($this->children as $child) {
                if (!$child->isOverlay()) {
                    $child->render($renderer, $textRenderer);
                    $child->renderContent($renderer, $textRenderer);
                }
            }
        }

        // Note: Overlays are NOT rendered here - they will be rendered by Window.php
        // at the global level to ensure they appear on top of everything
    }

    /**
     * Returns the computed content width/height within the container (excludes overlays).
     */
    public function getContentSize(): array
    {
        return [
            'width' => $this->contentWidth,
            'height' => $this->contentHeight,
        ];
    }

    /**
     * Get current scroll position.
     */
    public function getScrollPosition(): array
    {
        return [
            'x' => $this->scrollX,
            'y' => $this->scrollY,
        ];
    }

    /**
     * Restore scroll position (used e.g. after re-rendering children).
     */
    public function setScrollPosition(float $x, float $y): void
    {
        $this->scrollX = max(0, $x);
        $this->scrollY = max(0, $y);
    }

    private function renderScrollbars(&$renderer, array $overflow): void
    {
        $scrollbarColor = [120, 120, 120, 230];

        // Vertical scrollbar
        if ($overflow['y']) {
            $scrollbarHeight = $this->contentViewport->height;
            $thumbHeight = max(
                self::SCROLLBAR_MIN_SIZE,
                ($this->contentViewport->height / $this->contentHeight) * $scrollbarHeight,
            );
            $maxScroll = $this->contentHeight - $this->contentViewport->height;
            $thumbY = $this->contentViewport->y + (($this->scrollY / $maxScroll) * ($scrollbarHeight - $thumbHeight));

            $scrollbarX = ($this->contentViewport->x + $this->contentViewport->width) - self::SCROLLBAR_WIDTH;

            // Track (light gray background)
            sdl_set_render_draw_color($renderer, 220, 220, 220, 255);
            sdl_render_fill_rect($renderer, [
                'x' => (int) $scrollbarX,
                'y' => (int) $this->contentViewport->y,
                'w' => (int) self::SCROLLBAR_WIDTH,
                'h' => (int) $scrollbarHeight,
            ]);

            // Thumb (darker gray, moved part) - using regular rect for now
            $thumbX = (int) ($scrollbarX + 2);
            $thumbW = (int) (self::SCROLLBAR_WIDTH - 4);
            sdl_set_render_draw_color($renderer, 128, 128, 128, 255);
            sdl_render_fill_rect($renderer, [
                'x' => $thumbX,
                'y' => (int) $thumbY,
                'w' => $thumbW,
                'h' => (int) $thumbHeight,
            ]);
        }

        // Horizontal scrollbar
        if ($overflow['x']) {
            $scrollbarWidth = $this->contentViewport->width;
            $thumbWidth = max(
                self::SCROLLBAR_MIN_SIZE,
                ($this->contentViewport->width / $this->contentWidth) * $scrollbarWidth,
            );
            $maxScroll = $this->contentWidth - $this->contentViewport->width;
            $thumbX = $this->contentViewport->x + (($this->scrollX / $maxScroll) * ($scrollbarWidth - $thumbWidth));

            $scrollbarY = ($this->contentViewport->y + $this->contentViewport->height) - self::SCROLLBAR_WIDTH;

            // Track
            sdl_set_render_draw_color($renderer, 200, 200, 200, 100);
            sdl_render_fill_rect($renderer, [
                'x' => (int) $this->contentViewport->x,
                'y' => (int) $scrollbarY,
                'w' => (int) $scrollbarWidth,
                'h' => (int) self::SCROLLBAR_WIDTH,
            ]);

            // Thumb - using sdl_rounded_box for rounded rectangle
            $thumbY = (int) ($scrollbarY + 2);
            $thumbH = (int) (self::SCROLLBAR_WIDTH - 4);
            sdl_rounded_box(
                $renderer,
                (int) $thumbX,
                $thumbY,
                (int) ($thumbX + $thumbWidth),
                $thumbY + $thumbH,
                4,
                $scrollbarColor[0],
                $scrollbarColor[1],
                $scrollbarColor[2],
                $scrollbarColor[3],
            );
        }
    }

    public function handleMouseClick(float $mouseX, float $mouseY, int $button): bool
    {
        // Don't handle events if container is not visible
        if (!$this->visible) {
            return false;
        }

        // Check if click is on scrollbar
        $overflow = $this->hasOverflow();

        if ($overflow['y']) {
            $scrollbarX = ($this->contentViewport->x + $this->contentViewport->width) - self::SCROLLBAR_WIDTH;
            if (
                $mouseX >= $scrollbarX &&
                    $mouseX <= ($scrollbarX + self::SCROLLBAR_WIDTH) &&
                    $mouseY >= $this->contentViewport->y &&
                    $mouseY <= ($this->contentViewport->y + $this->contentViewport->height)
            ) {
                $this->isDraggingScrollbarY = true;
                $this->dragStartY = $mouseY;
                $this->scrollStartY = $this->scrollY;
                return true;
            }
        }

        if ($overflow['x']) {
            $scrollbarY = ($this->contentViewport->y + $this->contentViewport->height) - self::SCROLLBAR_WIDTH;
            if (
                $mouseY >= $scrollbarY &&
                    $mouseY <= ($scrollbarY + self::SCROLLBAR_WIDTH) &&
                    $mouseX >= $this->contentViewport->x &&
                    $mouseX <= ($this->contentViewport->x + $this->contentViewport->width)
            ) {
                $this->isDraggingScrollbarX = true;
                $this->dragStartX = $mouseX;
                $this->scrollStartX = $this->scrollX;
                return true;
            }
        }

        // Propagate to children if not on scrollbar
        // Only adjust coordinates if we have active scrolling
        $adjustedMouseX = $overflow['x'] || $overflow['y'] ? ($mouseX + $this->scrollX) : $mouseX;
        $adjustedMouseY = $overflow['x'] || $overflow['y'] ? ($mouseY + $this->scrollY) : $mouseY;

        $handled = false;
        foreach ($this->children as $child) {
            if (method_exists($child, 'handleMouseClick')) {
                if ($child->handleMouseClick($adjustedMouseX, $adjustedMouseY, $button)) {
                    $handled = true;
                }
            }
        }

        return $handled;
    }

    public function handleMouseMove(float $mouseX, float $mouseY): void
    {
        parent::handleMouseMove($mouseX, $mouseY);

        $overflow = $this->hasOverflow();

        if ($this->isDraggingScrollbarY) {
            $deltaY = $mouseY - $this->dragStartY;
            $scrollbarHeight = $this->contentViewport->height;
            $thumbHeight = max(
                self::SCROLLBAR_MIN_SIZE,
                ($this->contentViewport->height / $this->contentHeight) * $scrollbarHeight,
            );
            $maxScroll = $this->contentHeight - $this->contentViewport->height;
            $scrollRatio = $deltaY / ($scrollbarHeight - $thumbHeight);
            $this->scrollY = max(0, min($maxScroll, $this->scrollStartY + ($scrollRatio * $maxScroll)));
        }

        if ($this->isDraggingScrollbarX) {
            $deltaX = $mouseX - $this->dragStartX;
            $scrollbarWidth = $this->contentViewport->width;
            $thumbWidth = max(
                self::SCROLLBAR_MIN_SIZE,
                ($this->contentViewport->width / $this->contentWidth) * $scrollbarWidth,
            );
            $maxScroll = $this->contentWidth - $this->contentViewport->width;
            $scrollRatio = $deltaX / ($scrollbarWidth - $thumbWidth);
            $this->scrollX = max(0, min($maxScroll, $this->scrollStartX + ($scrollRatio * $maxScroll)));
        }

        // Propagate to children - only adjust coordinates if we have active scrolling
        $adjustedMouseX = $overflow['x'] || $overflow['y'] ? ($mouseX + $this->scrollX) : $mouseX;
        $adjustedMouseY = $overflow['x'] || $overflow['y'] ? ($mouseY + $this->scrollY) : $mouseY;

        foreach ($this->children as $child) {
            if (method_exists($child, 'handleMouseMove')) {
                $child->handleMouseMove($adjustedMouseX, $adjustedMouseY);
            }
        }
    }

    public function handleMouseRelease(float $mouseX, float $mouseY, int $button): void
    {
        $this->isDraggingScrollbarX = false;
        $this->isDraggingScrollbarY = false;

        // Propagate to children - only adjust coordinates if we have active scrolling
        $overflow = $this->hasOverflow();
        $adjustedMouseX = $overflow['x'] || $overflow['y'] ? ($mouseX + $this->scrollX) : $mouseX;
        $adjustedMouseY = $overflow['x'] || $overflow['y'] ? ($mouseY + $this->scrollY) : $mouseY;

        foreach ($this->children as $child) {
            if (method_exists($child, 'handleMouseRelease')) {
                $child->handleMouseRelease($adjustedMouseX, $adjustedMouseY, $button);
            }
        }
    }

    public function handleMouseWheel(float $mouseX, float $mouseY, float $deltaY): bool
    {
        // Don't handle events if container is not visible
        if (!$this->visible) {
            return false;
        }

        $overflow = $this->hasOverflow();

        // Check if mouse is over this container
        if (
            $mouseX >= $this->contentViewport->x &&
                $mouseX <= ($this->contentViewport->x + $this->contentViewport->width) &&
                $mouseY >= $this->contentViewport->y &&
                $mouseY <= ($this->contentViewport->y + $this->contentViewport->height)
        ) {
            if ($overflow['y']) {
                $maxScroll = $this->contentHeight - $this->contentViewport->height;
                $this->scrollY = max(0, min($maxScroll, $this->scrollY + ($deltaY * 20)));
                return true;
            }

            if ($overflow['x']) {
                $maxScroll = $this->contentWidth - $this->contentViewport->width;
                $this->scrollX = max(0, min($maxScroll, $this->scrollX + ($deltaY * 20)));
                return true;
            }
        }

        // Propagate to children - only adjust coordinates if we have active scrolling
        $adjustedMouseX = $overflow['x'] || $overflow['y'] ? ($mouseX + $this->scrollX) : $mouseX;
        $adjustedMouseY = $overflow['x'] || $overflow['y'] ? ($mouseY + $this->scrollY) : $mouseY;

        foreach ($this->children as $child) {
            if (method_exists($child, 'handleMouseWheel')) {
                if ($child->handleMouseWheel($adjustedMouseX, $adjustedMouseY, $deltaY)) {
                    return true;
                }
            }
        }

        return false;
    }
}
