<?php

namespace GriffinForms\Admin\App\Html\Widgets\PresentationArea\FormElements;

class Format extends \GriffinForms\Admin\App\Html\Widgets\PresentationArea\Format
{
    protected $item_id;
    protected $parent_id;
    protected $item;
    protected $parent;
    protected $form_theme;
    private $is_theme_set = null;

    protected function setItem()
    {
        if ($this->sql->itemExists(strtolower($this->meta), $this->item_id)) {
            $item_class = 'GriffinForms\Items\\' . $this->meta;
            $this->item = new $item_class();
            $this->item->loadItem($this->item_id); 
        } else {
            $this->item = false;
        }
    }

    protected function textUpdateField($name, $attrs = array(), $style = array(), $classes = '')
    {

        $css = '';

        if (is_string($style)) {
            $css .= $this->addImportantToCss($style);
        } elseif (is_array($style)) {
            foreach ($style as $prop => $prop_value) {
                if (is_int($prop)) {
                    $css .= $this->addImportantToCss($prop_value);
                    continue;
                }
                $css .= $prop . ':' . $prop_value . ' !important;';
            }
        }

        // Extract font-size from heading classes if present
        $css .= $this->getHeadingFontSizeCss($classes);

        $value = $this->item->getProp($name);
        $input_classes = 'griffinforms-app-text_update_field form-control' . ($classes ? ' ' . esc_attr($classes) : '');

        echo '<input type="text" ';
        echo 'class="' . esc_attr($input_classes) . '" ';
        echo 'data-gf-itemtype="' . esc_attr(strtolower($this->meta)) . '"';
        echo 'data-gf-itemid="' . esc_attr($this->item_id) . '" ';
        echo 'data-gf-fieldname="' . esc_attr($name) . '" ';
        echo 'data-gf-fieldvalue="' . esc_attr($value) . '" ';
        echo 'style="' . esc_attr($css) . '" ';

        foreach ($attrs as $attr => $attr_value) {
            echo esc_html($attr) . '="' . esc_attr($attr_value) . '" ';
        }

        echo 'value="' . esc_html($value) . '">';
    }

    protected function textAreaUpdateField($name, $attrs = array(), $style = array(), $classes = '')
    {

        $css = '';

        if (is_string($style)) {
            $css .= $this->addImportantToCss($style);
        } elseif (is_array($style)) {
            foreach ($style as $prop => $prop_value) {
                if (is_int($prop)) {
                    $css .= $this->addImportantToCss($prop_value);
                    continue;
                }
                $css .= $prop . ':' . $prop_value . ' !important;';
            }
        }

        // Extract font-size from heading classes if present
        $css .= $this->getHeadingFontSizeCss($classes);

        $value = $this->item->getProp($name);
        $textarea_classes = 'griffinforms-app-textarea_update_field' . ($classes ? ' ' . esc_attr($classes) : '');

        echo '<textarea ';
        echo 'class="' . esc_attr($textarea_classes) . '" ';
        echo 'data-gf-itemtype="' . esc_attr(strtolower($this->meta)) . '"';
        echo 'data-gf-itemid="' . esc_attr($this->item_id) . '" ';
        echo 'data-gf-fieldname="' . esc_attr($name) . '" ';
        echo 'data-gf-fieldvalue="' . esc_attr($value) . '" ';

        foreach ($attrs as $attr => $attr_value) {
            echo esc_html($attr) . '="' . esc_attr($attr_value) . '" ';
        }

        echo 'style="' . esc_attr($css) . '" >';
        echo esc_html($value);
        echo '</textarea>';
    }

    protected function optionalMetadataField($name, $args = array())
    {
        $defaults = array(
            'mode'            => 'input',
            'ghost_label'     => '',
            'wrapper_id'      => '',
            'wrapper_classes' => '',
            'field_classes'   => '',
            'attrs'           => array(),
            'style'           => array(),
            'owner_type'      => strtolower($this->meta),
            'owner_id'        => $this->item_id,
        );

        $args = wp_parse_args($args, $defaults);
        $value = (string) $this->item->getProp($name);
        $is_empty = trim($value) === '';
        $wrapper_classes = 'gf-builder-metadata-surface';
        $wrapper_classes .= $args['mode'] === 'textarea'
            ? ' gf-builder-metadata-surface--textarea'
            : ' gf-builder-metadata-surface--input';

        if (!empty($args['wrapper_classes'])) {
            $wrapper_classes .= ' ' . trim((string) $args['wrapper_classes']);
        }

        $wrapper_id = !empty($args['wrapper_id']) ? ' id="' . esc_attr($args['wrapper_id']) . '"' : '';

        echo '<div' . $wrapper_id . ' class="' . esc_attr($wrapper_classes) . '"';
        echo ' data-gf-structural-metadata="true"';
        echo ' data-gf-fieldname="' . esc_attr($name) . '"';
        echo ' data-gf-empty="' . ($is_empty ? 'true' : 'false') . '"';
        echo ' data-gf-owner-type="' . esc_attr((string) $args['owner_type']) . '"';
        echo ' data-gf-owner-id="' . esc_attr((string) $args['owner_id']) . '"';
        echo '>';

        if ($args['mode'] === 'textarea') {
            $this->textAreaUpdateField(
                $name,
                $args['attrs'],
                $args['style'],
                trim('gf-builder-metadata-editor ' . $args['field_classes'])
            );
        } else {
            $this->textUpdateField(
                $name,
                $args['attrs'],
                $args['style'],
                trim('gf-builder-metadata-editor ' . $args['field_classes'])
            );
        }

        echo '</div>';
    }

    protected function dataAttrs()
    {
        $parent_type = $this->heir->parents(strtolower($this->meta));
        echo 'data-gf-fe="true" ';
        echo 'data-gf-selected="false" ';
        echo 'data-gf-itemtype="' . esc_attr(strtolower($this->meta)) . '" ';
        echo 'data-gf-itemid="' . esc_attr(strtolower($this->item_id)) . '" ';
        echo 'data-gf-parenttype="' . esc_attr(strtolower($parent_type)) . '" ';
        echo 'data-gf-parentid="' . esc_attr(strtolower($this->parent_id)) . '" ';
        echo 'tabindex="0" ';
    }

    protected function renderActionCluster(array $actions = array(), $args = array())
    {
        $has_meta = !empty($args['meta_container']);
        $slab_actions = $this->getActionsByPlacement($actions, 'slab');
        $menu_actions = $this->getActionsByPlacement($actions, 'menu');

        if (empty($slab_actions) && empty($menu_actions) && !$has_meta) {
            return;
        }

        $id_attr = !empty($args['id']) ? ' id="' . esc_attr($args['id']) . '"' : '';
        $class = 'gf-fe-action-cluster';
        if (!empty($args['class'])) {
            $class .= ' ' . trim((string) $args['class']);
        }

        $label = !empty($args['label']) ? $args['label'] : __('Element actions', 'griffinforms-form-builder');

        echo '<div' . $id_attr . ' class="' . esc_attr($class) . '" role="group" aria-label="' . esc_attr($label) . '">';
        if ($has_meta) {
            echo '<span class="gf-fe-action-meta" aria-hidden="true"></span>';
        }
        foreach ($slab_actions as $action) {
            if (!empty($action['children']) && is_array($action['children'])) {
                $this->renderCompositeAction($action);
                continue;
            }

            $this->renderAction($action);
        }

        if (!empty($menu_actions)) {
            $this->renderOverflowTrigger();
            $this->renderActionMenu($menu_actions);
        }
        echo '</div>';
    }

    protected function renderActionGroup(array $actions = array(), $args = array())
    {
        if (empty($actions)) {
            return;
        }

        $class = 'gf-fe-action-group';
        if (!empty($args['class'])) {
            $class .= ' ' . trim((string) $args['class']);
        }

        $label = !empty($args['label']) ? $args['label'] : __('Element actions', 'griffinforms-form-builder');

        echo '<div class="' . esc_attr($class) . '" role="group" aria-label="' . esc_attr($label) . '">';
        foreach ($actions as $action) {
            $this->renderAction($action);
        }
        echo '</div>';
    }

    protected function renderAction(array $action = array())
    {
        if (empty($action['label'])) {
            return;
        }

        $tag = (!empty($action['href'])) ? 'a' : 'button';
        $class = 'gf-fe-action-btn';
        if (!empty($action['class'])) {
            $class .= ' ' . trim((string) $action['class']);
        }

        $context_type = !empty($action['context_type']) ? $action['context_type'] : strtolower($this->meta);
        $context_id = isset($action['context_id']) ? absint($action['context_id']) : absint($this->item_id);
        $placement = !empty($action['placement']) ? $action['placement'] : 'slab';
        $action_id = !empty($action['action']) ? $action['action'] : (!empty($action['id']) ? $action['id'] : 'default');
        $icon = !empty($action['icon']) ? $action['icon'] : 'more_horiz';
        $disabled = !empty($action['disabled']);

        echo '<' . $tag . ' class="' . esc_attr($class) . '"';
        echo ' aria-label="' . esc_attr($action['label']) . '"';
        echo ' data-gf-action="' . esc_attr($action_id) . '"';
        echo ' data-gf-context-type="' . esc_attr($context_type) . '"';
        echo ' data-gf-context-id="' . esc_attr($context_id) . '"';
        echo ' data-gf-action-placement="' . esc_attr($placement) . '"';

        if (!empty($action['id'])) {
            echo ' data-gf-action-id="' . esc_attr($action['id']) . '"';
        }

        if (!empty($action['href'])) {
            echo ' href="' . esc_url($action['href']) . '"';
        } else {
            echo ' type="button"';
        }

        if ($disabled && $tag === 'button') {
            echo ' disabled';
        }

        echo '>';
        $this->renderActionIcon($action, $icon);
        echo '</' . $tag . '>';
    }

    protected function renderOverflowTrigger()
    {
        echo '<button type="button" class="gf-fe-action-btn gf-fe-action-menu-trigger"';
        echo ' aria-label="' . esc_attr__('More actions', 'griffinforms-form-builder') . '"';
        echo ' aria-haspopup="menu"';
        echo ' aria-expanded="false"';
        echo ' data-gf-action="toggle-overflow-menu"';
        echo ' data-gf-action-placement="slab"';
        echo '>';
        $this->renderActionIcon(
            array(
                'icon' => 'more_vert',
                'icon_svg_file' => 'admin/images/toolbar-icons/builder/menu.svg',
            ),
            'more_vert'
        );
        echo '</button>';
    }

    protected function renderActionMenu(array $actions = array())
    {
        if (empty($actions)) {
            return;
        }

        echo '<div class="gf-fe-action-menu" role="menu" hidden>';

        $last_section = null;
        foreach ($actions as $index => $action) {
            $section = isset($action['section']) ? (string) $action['section'] : '';
            if ($index > 0 && $section !== $last_section) {
                echo '<div class="gf-fe-action-menu-divider" role="separator" aria-hidden="true"></div>';
            }
            $this->renderActionMenuItem($action);
            $last_section = $section;
        }

        echo '</div>';
    }

    protected function renderActionMenuItem(array $action = array())
    {
        if (empty($action['label'])) {
            return;
        }

        $tag = (!empty($action['href'])) ? 'a' : 'button';
        $class = 'gf-fe-action-menu-item';
        if (!empty($action['class'])) {
            $class .= ' ' . trim((string) $action['class']);
        }

        $context_type = !empty($action['context_type']) ? $action['context_type'] : strtolower($this->meta);
        $context_id = isset($action['context_id']) ? absint($action['context_id']) : absint($this->item_id);
        $placement = !empty($action['placement']) ? $action['placement'] : 'menu';
        $action_id = !empty($action['action']) ? $action['action'] : (!empty($action['id']) ? $action['id'] : 'default');
        $disabled = !empty($action['disabled']);
        $menu_close = array_key_exists('menu_close', $action) ? (bool) $action['menu_close'] : true;

        echo '<' . $tag . ' class="' . esc_attr($class) . '"';
        echo ' role="menuitem"';
        echo ' aria-label="' . esc_attr($action['label']) . '"';
        echo ' data-gf-action="' . esc_attr($action_id) . '"';
        echo ' data-gf-context-type="' . esc_attr($context_type) . '"';
        echo ' data-gf-context-id="' . esc_attr($context_id) . '"';
        echo ' data-gf-action-placement="' . esc_attr($placement) . '"';
        echo ' data-gf-menu-close="' . esc_attr($menu_close ? 'true' : 'false') . '"';

        if (!empty($action['section'])) {
            echo ' data-gf-menu-section="' . esc_attr($action['section']) . '"';
        }

        if (!empty($action['id'])) {
            echo ' data-gf-action-id="' . esc_attr($action['id']) . '"';
        }

        if (!empty($action['href'])) {
            echo ' href="' . esc_url($action['href']) . '"';
        } else {
            echo ' type="button"';
        }

        if ($disabled && $tag === 'button') {
            echo ' disabled';
        }

        echo '>';
        echo '<span class="gf-fe-action-menu-label">' . esc_html($action['label']) . '</span>';

        if (!empty($action['menu_right_text'])) {
            echo '<span class="gf-fe-action-menu-right-text" aria-hidden="true">' . esc_html($action['menu_right_text']) . '</span>';
        } elseif (!empty($action['menu_right_icon_svg_file'])) {
            echo '<span class="gf-fe-action-menu-right-icon" aria-hidden="true">';
            $this->renderActionSvgFile($action['menu_right_icon_svg_file']);
            echo '</span>';
        } elseif (!empty($action['menu_right_icon'])) {
            echo '<span class="gf-fe-action-menu-right-icon" aria-hidden="true">';
            $this->renderActionIcon(array('icon' => $action['menu_right_icon']), $action['menu_right_icon']);
            echo '</span>';
        }

        echo '</' . $tag . '>';
    }

    protected function renderCompositeAction(array $action = array())
    {
        if (empty($action['children']) || !is_array($action['children'])) {
            return;
        }

        $class = 'gf-fe-action-composite';
        if (!empty($action['class'])) {
            $class .= ' ' . trim((string) $action['class']);
        }

        echo '<div class="' . esc_attr($class) . '" role="group" aria-label="' . esc_attr($action['label']) . '">';
        foreach ($action['children'] as $child_action) {
            if (empty($child_action['label'])) {
                continue;
            }

            $tag = (!empty($child_action['href'])) ? 'a' : 'button';
            $child_class = 'gf-fe-action-composite-btn';
            if (!empty($child_action['class'])) {
                $child_class .= ' ' . trim((string) $child_action['class']);
            }

            $context_type = !empty($child_action['context_type']) ? $child_action['context_type'] : strtolower($this->meta);
            $context_id = isset($child_action['context_id']) ? absint($child_action['context_id']) : absint($this->item_id);
            $placement = !empty($child_action['placement']) ? $child_action['placement'] : 'slab';
            $action_id = !empty($child_action['action']) ? $child_action['action'] : (!empty($child_action['id']) ? $child_action['id'] : 'default');
            $icon = !empty($child_action['icon']) ? $child_action['icon'] : 'more_horiz';
            $disabled = !empty($child_action['disabled']);

            echo '<' . $tag . ' class="' . esc_attr($child_class) . '"';
            echo ' aria-label="' . esc_attr($child_action['label']) . '"';
            echo ' data-gf-action="' . esc_attr($action_id) . '"';
            echo ' data-gf-context-type="' . esc_attr($context_type) . '"';
            echo ' data-gf-context-id="' . esc_attr($context_id) . '"';
            echo ' data-gf-action-placement="' . esc_attr($placement) . '"';

            if (!empty($child_action['id'])) {
                echo ' data-gf-action-id="' . esc_attr($child_action['id']) . '"';
            }

            if (!empty($child_action['href'])) {
                echo ' href="' . esc_url($child_action['href']) . '"';
            } else {
                echo ' type="button"';
            }

            if ($disabled && $tag === 'button') {
                echo ' disabled';
            }

            echo '>';
            $this->renderActionIcon($child_action, $icon);
            echo '</' . $tag . '>';
        }
        echo '</div>';
    }

    protected function renderActionIcon(array $action = array(), $fallback_icon = 'more_horiz')
    {
        if (!empty($action['icon_svg_file'])) {
            $this->renderActionSvgFile($action['icon_svg_file']);
            return;
        }

        if (!empty($action['icon_svg_path'])) {
            echo '<svg class="gf-fe-action-svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false">';
            echo '<path d="' . esc_attr($action['icon_svg_path']) . '" fill="currentColor"></path>';
            echo '</svg>';
            return;
        }

        $icon = !empty($action['icon']) ? $action['icon'] : $fallback_icon;
        echo '<span class="material-symbols-outlined align-middle">' . esc_html($icon) . '</span>';
    }

    protected function renderActionSvgFile(string $relative_path = '')
    {
        $relative_path = ltrim(trim($relative_path), '/');
        if ($relative_path === '') {
            return;
        }

        $full_path = $this->config->getRootPath() . $relative_path;
        if (!file_exists($full_path)) {
            return;
        }

        $svg = file_get_contents($full_path);
        if ($svg === false || trim($svg) === '') {
            return;
        }

        $svg = preg_replace('/<svg\b([^>]*)>/i', '<svg$1 class="gf-fe-action-svg" aria-hidden="true" focusable="false">', $svg, 1);
        $svg = preg_replace('/\sfill="(?!none)([^"]*)"/i', ' fill="currentColor"', $svg);
        $svg = preg_replace('/\sstroke="(?!none)([^"]*)"/i', ' stroke="currentColor"', $svg);
        echo $svg;
    }

    protected function getActionsByPlacement(array $actions = array(), $placement = 'slab')
    {
        $filtered = array();

        foreach ($actions as $action) {
            $action_placement = !empty($action['placement']) ? $action['placement'] : 'slab';
            if ($action_placement === $placement) {
                $filtered[] = $action;
            }
        }

        return $filtered;
    }

    protected function getDeleteMenuAction(string $item_type, string $label, array $args = array())
    {
        $action = array(
            'id'            => 'delete',
            'label'         => $label,
            'action'        => 'delete-selected-item',
            'placement'     => 'menu',
            'section'       => 'danger',
            'context_type'  => $item_type,
            'menu_right_icon_svg_file' => 'admin/images/toolbar-icons/builder/delete.svg',
            'class'         => 'gf-fe-action-menu-item-danger',
        );

        return array_merge($action, $this->getMinimumStructureDeleteMenuArgs($item_type), $args);
    }

    protected function getRemoveFieldMenuAction(string $label, array $args = array())
    {
        $action = array(
            'id'                     => 'remove',
            'label'                  => $label,
            'action'                 => 'remove-selected-field',
            'placement'              => 'menu',
            'section'                => 'danger',
            'context_type'           => 'field',
            'menu_right_icon_svg_file' => 'admin/images/toolbar-icons/builder/remove.svg',
            'class'                  => 'gf-fe-action-menu-item-danger',
        );

        return array_merge($action, $args);
    }

    protected function getMinimumStructureDeleteMenuArgs(string $item_type): array
    {
        $item_type = strtolower(trim($item_type));
        $guard_message = '';
        $parent_item = $this->getParentItem();

        if ($item_type === 'page' || $item_type === 'formpage') {
            if ($parent_item) {
                $page_ids = $parent_item->getProp('formpages');
                $count = is_array($page_ids) ? count($page_ids) : 0;
                if ($count <= 1) {
                    $guard_message = __('You must keep at least one page in the form.', 'griffinforms-form-builder');
                }
            }
        }

        if ($item_type === 'row' || $item_type === 'pagerow') {
            if ($parent_item) {
                $row_ids = $parent_item->getProp('pagerows');
                $count = is_array($row_ids) ? count($row_ids) : 0;
                if ($count <= 1) {
                    $guard_message = __('You must keep at least one row in the page.', 'griffinforms-form-builder');
                }
            }
        }

        if ($item_type === 'column' || $item_type === 'rowcolumn') {
            if ($parent_item) {
                $column_ids = $parent_item->getProp('rowcolumns');
                $count = is_array($column_ids) ? count($column_ids) : 0;
                if ($count <= 1) {
                    $guard_message = __('You must keep at least one column in the row.', 'griffinforms-form-builder');
                }
            }
        }

        if ($guard_message === '') {
            return array();
        }

        return array(
            'disabled' => true,
            'menu_right_text' => '',
            'guard_message' => $guard_message,
        );
    }

    protected function getParentItem()
    {
        if (!is_object($this->parent)) {
            return false;
        }

        if (isset($this->parent->item) && is_object($this->parent->item)) {
            return $this->parent->item;
        }

        if (method_exists($this->parent, 'getProp')) {
            return $this->parent;
        }

        return false;
    }

    public function __construct($id, $parent_id = 0, $parent = false, $form_theme = null)
    {
        $this->item_id = $id;
        $this->parent_id = $parent_id;
        $this->parent = $parent;
        $this->form_theme = $form_theme;
        $this->setAll();
    }

    /**
     * Extracts heading font-size CSS from Bootstrap heading classes (h1-h6).
     * Returns inline CSS with !important flag to override hardcoded styles.
     * Returns empty string if no heading class is found.
     *
     * @param string $classes Space-separated class string to search
     * @return string CSS font-size rule with !important or empty string
     */
    protected function getHeadingFontSizeCss($classes)
    {
        $heading_font_sizes = array(
            'h1' => '2.5rem',
            'h2' => '2rem',
            'h3' => '1.5rem',
            'h4' => '1.25rem',
            'h5' => '1rem',
            'h6' => '0.875rem',
            'small' => '0.75rem'
        );

        foreach ($heading_font_sizes as $heading => $font_size) {
            if (strpos($classes, $heading) !== false) {
                return 'font-size:' . $font_size . ' !important;';
            }
        }

        return '';
    }

    /**
     * Checks if a form theme is set and available.
     * Uses lazy evaluation with caching for minimal overhead.
     * Delegates evaluation to shared evaluateThemeSet() method.
     *
     * @return bool True if theme is set and valid, false otherwise.
     */
    public function isThemeSet()
    {
        if ($this->is_theme_set === null) {
            $this->is_theme_set = $this->evaluateThemeSet($this->form_theme);
        }
        return $this->is_theme_set;
    }

    /**
     * Ensures every declaration in a CSS string ends with !important
     * so inline theme styles override builder input defaults.
     *
     * @param string $css Raw CSS declarations separated by semicolons.
     * @return string CSS string with !important appended per declaration.
     */
    protected function addImportantToCss($css)
    {
        $css = trim((string) $css);
        if ($css === '') {
            return '';
        }

        $declarations = array_filter(array_map('trim', explode(';', $css)));
        $normalized = array();

        foreach ($declarations as $declaration) {
            if ($declaration === '') {
                continue;
            }

            $parts = explode(':', $declaration, 2);
            if (count($parts) !== 2) {
                continue;
            }

            list($property, $value) = array_map('trim', $parts);
            if ($property === '' || $value === '') {
                continue;
            }

            // Remove existing !important to avoid duplication
            $value = preg_replace('/\s*!important$/i', '', $value);
            $normalized[] = $property . ': ' . $value . ' !important;';
        }

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