<?php
/**
 * BookiFlex
 *
 * @package   BookiFlex
 * @author    BookiFlex
 * @copyright Copyright (c) 2025 BookiFlex
 * @license   GPL-2.0-or-later
 *
 * @link https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Plugin\UI;

defined('ABSPATH') || exit;

/**
 * Builds the <bookiflex-search-form> markup from a normalized attribute array.
 *
 * Shared between the Gutenberg block and the Elementor widget so both emit
 * byte-for-byte identical output. Attribute keys are the camelCase names used
 * by the block.json schema (layout, buttonText, maxAdults, colorPrimary, ...).
 */
class SearchFormRenderer
{
    /**
     * @param array<string, mixed> $attrs
     */
    public function renderTag(array $attrs): string
    {
        $htmlAttrs = $this->buildHtmlAttributes($attrs);
        $style     = $this->buildInlineStyle($attrs);
        $styleAttr = $style !== '' ? sprintf(' style="%s"', esc_attr($style)) : '';

        return sprintf(
            '<bookiflex-search-form %s%s></bookiflex-search-form>',
            $htmlAttrs,
            $styleAttr
        );
    }

    /**
     * @param array<string, mixed> $attrs
     */
    public function buildHtmlAttributes(array $attrs): string
    {
        $stringMap = [
            'layout'             => 'layout',
            'actionUrl'          => 'action-url',
            'submitMode'         => 'submit-mode',
            'locale'             => 'locale',
            'buttonText'         => 'button-text',
            'accommodationTypes' => 'accommodation-types',
            'ratePlans'          => 'rate-plans',
        ];

        $numericMap = [
            'maxAdults'   => 'max-adults',
            'maxChildren' => 'max-children',
            'maxChildAge' => 'max-child-age',
        ];

        $boolMap = [
            'hideGuests'   => 'hide-guests',
            'hidePromo'    => 'hide-promo',
            'hideChildren' => 'hide-children',
        ];

        $parts = [];

        foreach ($stringMap as $blockAttr => $htmlAttr) {
            $val = $attrs[$blockAttr] ?? '';
            if ($val !== '') {
                $parts[] = sprintf('%s="%s"', $htmlAttr, esc_attr((string) $val));
            }
        }

        foreach ($numericMap as $blockAttr => $htmlAttr) {
            if (isset($attrs[$blockAttr])) {
                $parts[] = sprintf('%s="%d"', $htmlAttr, (int) $attrs[$blockAttr]);
            }
        }

        foreach ($boolMap as $blockAttr => $htmlAttr) {
            if (!empty($attrs[$blockAttr])) {
                $parts[] = $htmlAttr;
            }
        }

        return implode(' ', $parts);
    }

    /**
     * @param array<string, mixed> $attrs
     */
    public function buildInlineStyle(array $attrs): string
    {
        $tokenMap = [
            'colorPrimary'        => '--bflex-primary',
            'colorPrimaryHover'   => '--bflex-primary-hover',
            'colorOnPrimary'      => '--bflex-on-primary',
            'colorSurface'        => '--bflex-surface',
            'colorOnSurface'      => '--bflex-on-surface',
            'colorBorder'         => '--bflex-border',
            'colorMuted'          => '--bflex-muted',
            'radius'              => '--bflex-radius',
            'borderWidth'         => '--bflex-border-width',
            'gap'                 => '--bflex-gap',
            'fieldPadding'        => '--bflex-field-padding',
            'fontFamily'          => '--bflex-font-family',
            'fontSize'            => '--bflex-font-size',
            'buttonTextTransform' => '--bflex-button-text-transform',
            'shadow'              => '--bflex-shadow',
        ];

        $cssVars = [];

        foreach ($tokenMap as $blockAttr => $cssVar) {
            $val = $attrs[$blockAttr] ?? '';
            if ($val !== '') {
                $cssVars[] = sprintf('%s: %s', $cssVar, sanitize_text_field((string) $val));
            }
        }

        // Panels/dropdowns use an opaque version of the background (alpha stripped)
        $surfaceVal = $attrs['colorSurface'] ?? '';
        if ($surfaceVal !== '') {
            $cssVars[] = sprintf('--bflex-panel-bg: %s', sanitize_text_field($this->toOpaque((string) $surfaceVal)));
        }

        $cornerMap = [
            'radiusTl' => '--bflex-radius-tl',
            'radiusTr' => '--bflex-radius-tr',
            'radiusBr' => '--bflex-radius-br',
            'radiusBl' => '--bflex-radius-bl',
        ];
        foreach ($cornerMap as $blockAttr => $cssVar) {
            if (isset($attrs[$blockAttr])) {
                $cssVars[] = sprintf('%s: %dpx', $cssVar, (int) $attrs[$blockAttr]);
            }
        }

        return implode('; ', $cssVars);
    }

    // #rrggbbaa (8-digit hex with alpha) → #rrggbb
    private function toOpaque(string $color): string
    {
        return preg_match('/^#[0-9a-fA-F]{8}$/', $color) ? substr($color, 0, 7) : $color;
    }
}
