<?php

namespace GriffinForms\Admin\Js\Local;

class FormTheme extends \GriffinForms\Admin\Js\Local\Single
{
    /**
     * Add FormTheme-specific JavaScript.
     * Inherits core CRUD functionality from Single class.
     */

    protected function setListPage()
    {
        parent::setListPage();
        $this->list_page['formtheme'] = 'formthemes';
    }

    /**
     * Override localJs to include FormTheme-specific helper functions
     */
    protected function localJs()
    {
        $js = parent::localJs();
        $js .= $this->validateDimensionInputs() . PHP_EOL;
        $js .= $this->colorPickerJs() . PHP_EOL;
        $js .= $this->stylePreviewJs() . PHP_EOL;
        $js .= $this->updateStylePreviewJs() . PHP_EOL;
        return $js;
    }

    /**
     * Get theme name with validation
     */
    public function getName()
    {
        return 'function getName() {
            var fieldValue = $("#griffinforms-name-inputtext").val();
            $("#griffinforms-name-inputtext").removeClass("border-danger");
            fieldValue = $.trim(fieldValue);

            if (fieldValue == "") {
                $("#griffinforms-name-inputtext").val("");
                $("#griffinforms-name-inputtext").addClass("border-danger");
                showItemError("' . esc_js($this->lang->getText('name_required')) . '");
            } else {
                return fieldValue;
            }
        }';
    }

    /**
     * Get theme description with validation
     */
    public function getDescription()
    {
        return 'function getDescription() {
            var fieldValue = $("#griffinforms-description-textarea").val();
            $("#griffinforms-description-textarea").removeClass("border-danger");
            fieldValue = $.trim(fieldValue);

            if (fieldValue.length > 2000) {
                $("#griffinforms-description-textarea").addClass("border-danger");
                showItemError("' . esc_js($this->lang->getText('description_too_long')) . '");
            } else {
                return fieldValue;
            }
        }';
    }

    /**
     * Get theme category
     */
    public function getCategory()
    {
        return 'function getCategory() {
            var fieldValue = $("#griffinforms-category-row select").val();
            return fieldValue || "default";
        }';
    }

    /**
     * Get basic theme information (name, heading, description, category)
     */
    public function getBasicInfo()
    {
        return 'function getBasicInfo() {
            return {
                "name": $("#griffinforms-name-inputtext").val(),
                "heading": $("#griffinforms-heading-inputtext").val(),
                "description": $("#griffinforms-description-textarea").val(),
                "category": $("#griffinforms-category-row select").val()
            };
        }';
    }

    /**
     * Get form styling data
     */
    public function getFormStyle()
    {
        return 'function getFormStyle() {
            return collectStyleData("form_style");
        }';
    }

    /**
     * Get page styling data
     */
    public function getPageStyle()
    {
        return 'function getPageStyle() {
            return collectStyleData("page_style");
        }';
    }

    /**
     * Get row styling data
     */
    public function getRowStyle()
    {
        return 'function getRowStyle() {
            return collectStyleData("row_style");
        }';
    }

    /**
     * Get field styling data
     */
    public function getFieldStyle()
    {
        return 'function getFieldStyle() {
            return collectStyleData("field_style");
        }';
    }

    /**
     * Get submit button styling data
     */
    public function getSubmitButton()
    {
        return 'function getSubmitButton() {
            return collectStyleData("submit_button");
        }';
    }

    /**
     * Get previous button styling data
     */
    public function getPreviousButton()
    {
        return 'function getPreviousButton() {
            return collectStyleData("previous_button");
        }';
    }

    /**
     * Get next button styling data
     */
    public function getNextButton()
    {
        return 'function getNextButton() {
            return collectStyleData("next_button");
        }';
    }

    /**
     * Get button typography data
     */
    public function getButtonTypography()
    {
        return 'function getButtonTypography() {
            return collectStyleData("button_typography");
        }';
    }

    /**
     * Get form title typography data
     */
    public function getFormTitle()
    {
        return 'function getFormTitle() {
            return collectStyleData("form_title");
        }';
    }

    /**
     * Get form description typography data
     */
    public function getFormDescription()
    {
        return 'function getFormDescription() {
            return collectStyleData("form_description");
        }';
    }

    /**
     * Get page heading typography data
     */
    public function getPageHeading()
    {
        return 'function getPageHeading() {
            return collectStyleData("page_heading");
        }';
    }

    /**
     * Get page description typography data
     */
    public function getPageDescription()
    {
        return 'function getPageDescription() {
            return collectStyleData("page_description");
        }';
    }

    /**
     * Get row heading typography data
     */
    public function getRowHeading()
    {
        return 'function getRowHeading() {
            return collectStyleData("row_heading");
        }';
    }

    /**
     * Get row description typography data
     */
    public function getRowDescription()
    {
        return 'function getRowDescription() {
            return collectStyleData("row_description");
        }';
    }

    /**
     * Get field label typography data
     */
    public function getFieldLabel()
    {
        return 'function getFieldLabel() {
            return collectStyleData("field_label");
        }';
    }

    /**
     * Get field description typography data
     */
    public function getFieldDescription()
    {
        return 'function getFieldDescription() {
            return collectStyleData("field_description");
        }';
    }

    /**
     * Get field errors styling data
     */
    public function getFieldErrors()
    {
        return 'function getFieldErrors() {
            return getFieldErrorsData();
        }';
    }

    /**
     * Get success message styling data
     */
    public function getSuccessMessage()
    {
        return 'function getSuccessMessage() {
            return getSuccessMessageData();
        }';
    }

    /**
     * Collect all form data for submission
     */
    public function getFormData()
    {
        return 'function getFormData() {
            const formData = new FormData(document.querySelector("form"));
            const data = {};

            for (const [key, value] of formData.entries()) {
                if (key === "nonce" || key === "action" || key === "item_type") {
                    // Skip WordPress standard fields
                    continue;
                }
                data[key] = value;
            }

            return data;
        }';
    }

    /**
     * JavaScript for color picker interaction
     */
    public function colorPickerJs()
    {
        return 'function initColorPickers() {
            if (typeof jQuery.fn.spectrum === "function") {
                $(".griffinforms-color-picker").spectrum({
                    preferredFormat: "hex",
                    showInput: true,
                    showAlpha: true,
                    allowEmpty: false,
                    move: function(color) {
                        updateStylePreview();
                    }
                });
            }
        }';
    }

    /**
     * JavaScript for style preview generation
     */
    public function stylePreviewJs()
    {
        return 'function generateStylePreview() {
            const styleData = getThemeStyleData();
            const css = generateCSSFromTheme(styleData);
            const styleTag = document.getElementById("griffinforms-theme-preview-style");

            if (styleTag) {
                styleTag.innerHTML = css;
            }
        }

        function generateCSSFromTheme(themeData) {
            let css = "";

            if (themeData.form_style) {
                css += generateElementCSS(".griffinforms-form-container", themeData.form_style);
            }

            if (themeData.page_style) {
                css += generateElementCSS(".griffinforms-page-container", themeData.page_style);
            }

            if (themeData.row_style) {
                css += generateElementCSS(".griffinforms-form-row", themeData.row_style);
            }

            if (themeData.field_style) {
                css += generateFieldTypeCSS(themeData.field_style);
            }

            if (themeData.submit_button) {
                css += generateElementCSS(".griffinforms-submit-button", themeData.submit_button);
            }

            if (themeData.previous_button) {
                css += generateElementCSS(".griffinforms-previous-button", themeData.previous_button);
            }

            if (themeData.next_button) {
                css += generateElementCSS(".griffinforms-next-button", themeData.next_button);
            }

            return css;
        }

        function generateElementCSS(selector, styleData) {
            let css = "";

            if (!styleData) return css;

            if (styleData.default) {
                css += selector + " { " + flattenStyleObject(styleData.default) + " }\\n";
            }

            if (styleData.focus) {
                css += selector + ":focus { " + flattenStyleObject(styleData.focus) + " }\\n";
            }

            if (styleData.hover) {
                css += selector + ":hover { " + flattenStyleObject(styleData.hover) + " }\\n";
            }

            if (styleData.active) {
                css += selector + ":active { " + flattenStyleObject(styleData.active) + " }\\n";
            }

            return css;
        }

        function generateFieldTypeCSS(fieldStyleData) {
            let css = "";

            if (!fieldStyleData) return css;

            Object.keys(fieldStyleData).forEach(fieldType => {
                const selector = getFieldTypeSelector(fieldType);
                const states = fieldStyleData[fieldType];

                Object.keys(states).forEach(state => {
                    const stateSelector = state === "default" ? selector : selector + ":" + state;
                    css += stateSelector + " { " + flattenStyleObject(states[state]) + " }\n";
                });
            });

            return css;
        }

        function getFieldTypeSelector(fieldType) {
            const selectors = {
                "text_input": "input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], input[type=\"url\"], input[type=\"tel\"], input[type=\"password\"], input[type=\"date\"], input[type=\"time\"]",
                "textarea": "textarea",
                "select_input": "select",
                "checkbox_radio": "input[type=\"checkbox\"], input[type=\"radio\"]",
                "file_upload": "input[type=\"file\"]",
                "address": ".griffinforms-address-field"
            };

            return selectors[fieldType] || ".griffinforms-field";
        }

        function flattenStyleObject(styleObj) {
            let css = "";

            Object.keys(styleObj).forEach(prop => {
                const cssProp = convertToCssProp(prop);
                const value = styleObj[prop];

                if (typeof value === "object") {
                    // Handle multi-value properties like padding, margin, border
                    if (Array.isArray(value)) {
                        css += cssProp + ": " + value.join(" ") + "; ";
                    } else {
                        // Handle nested objects like border, box-shadow
                        css += handleComplexProperty(cssProp, value);
                    }
                } else {
                    css += cssProp + ": " + value + "; ";
                }
            });

            return css;
        }

        function convertToCssProp(prop) {
            return prop.replace(/_/g, "-").toLowerCase();
        }

        function handleComplexProperty(prop, value) {
            let css = "";

            if (prop === "border") {
                css += "border-color: " + (value.color || "#000") + "; ";
                css += "border-style: " + (value.style || "solid") + "; ";
                if (value.width) {
                    css += "border-width: " + formatSides(value.width) + "; ";
                }
            } else if (prop === "box-shadow") {
                css += prop + ": " + value.offset_x + " " + value.offset_y + " " + value.blur + " " + value.spread + " " + value.color + "; ";
            }

            return css;
        }

        function formatSides(sideObj) {
            if (typeof sideObj === "object") {
                return sideObj.top + " " + sideObj.right + " " + sideObj.bottom + " " + sideObj.left;
            }
            return sideObj;
        }';
    }

    /**
     * JavaScript for theme preview updates
     */
    public function updateStylePreviewJs()
    {
        return 'function updateStylePreview() {
            generateStylePreview();
        }

        function getThemeStyleData() {
            return {
                form_style: getFormStyleData(),
                page_style: getPageStyleData(),
                row_style: getRowStyleData(),
                field_style: getFieldStyleData(),
                submit_button: getSubmitButtonData(),
                previous_button: getPreviousButtonData(),
                next_button: getNextButtonData(),
                button_typography: getButtonTypographyData(),
                form_title: getFormTitleData(),
                form_description: getFormDescriptionData(),
                page_heading: getPageHeadingData(),
                page_description: getPageDescriptionData(),
                row_heading: getRowHeadingData(),
                row_description: getRowDescriptionData(),
                field_label: getFieldLabelData(),
                field_description: getFieldDescriptionData(),
                field_errors: getFieldErrorsData(),
                success_message: getSuccessMessageData()
            };
        }

        function getFormStyleData() {
            return collectStyleData("form_style");
        }

        function getPageStyleData() {
            return collectStyleData("page_style");
        }

        function getRowStyleData() {
            return collectStyleData("row_style");
        }

        function getFieldStyleData() {
            return collectStyleData("field_style");
        }

        function getSubmitButtonData() {
            return collectStyleData("submit_button");
        }

        function getPreviousButtonData() {
            return collectStyleData("previous_button");
        }

        function getNextButtonData() {
            return collectStyleData("next_button");
        }

        function getButtonTypographyData() {
            return collectStyleData("button_typography");
        }

        function getFormTitleData() {
            return collectStyleData("form_title");
        }

        function getFormDescriptionData() {
            return collectStyleData("form_description");
        }

        function getPageHeadingData() {
            return collectStyleData("page_heading");
        }

        function getPageDescriptionData() {
            return collectStyleData("page_description");
        }

        function getRowHeadingData() {
            return collectStyleData("row_heading");
        }

        function getRowDescriptionData() {
            return collectStyleData("row_description");
        }

        function getFieldLabelData() {
            return collectStyleData("field_label");
        }

        function getFieldDescriptionData() {
            return collectStyleData("field_description");
        }

        function getFieldErrorsData() {
            const typography = collectStyleData("field_errors");
            const container = collectStyleData("field_errors_style");
            return mergeStyleSections(container, typography);
        }

        function getSuccessMessageData() {
            const typography = collectStyleData("success_message");
            const container = collectStyleData("success_message_style");
            return mergeStyleSections(container, typography);
        }

        function collectStyleData(styleKey) {
            const styleData = {};
            const inputs = document.querySelectorAll("input, select, textarea");

            inputs.forEach(function(input) {
                const name = input.name;

                if (input.type === "radio" && !input.checked) {
                    return;
                }

                let value = input.value;

                if (input.type === "checkbox") {
                    value = input.checked ? input.value : "";
                }

                if (!name || !name.startsWith(styleKey + "[")) {
                    return;
                }

                const segments = name
                    .replace(/\\]/g, "")
                    .split("[")
                    .filter(Boolean);

                // Remove base key
                segments.shift();

                if (segments.length < 2) {
                    return;
                }

                const lastSegment = segments[segments.length - 1];
                if (lastSegment === "value" || lastSegment === "unit") {
                    return;
                }

                setNestedValue(styleData, segments, value);
            });

            const pruned = pruneStyleOverrides(styleData);
            return pruned && Object.keys(pruned).length > 0 ? pruned : null;
        }

        function setNestedValue(target, segments, value) {
            let current = target;

            segments.forEach(function(segment, index) {
                if (index === segments.length - 1) {
                    current[segment] = value;
                    return;
                }

                if (!current[segment] || typeof current[segment] !== "object") {
                    current[segment] = {};
                }

                current = current[segment];
            });
        }

        function pruneStyleOverrides(styleData) {
            if (!styleData || typeof styleData !== "object" || Array.isArray(styleData)) {
                return styleData;
            }

            if (styleData.default && typeof styleData.default === "object" && !Array.isArray(styleData.default)) {
                Object.keys(styleData).forEach((state) => {
                    if (state === "default" || typeof styleData[state] !== "object" || Array.isArray(styleData[state])) {
                        return;
                    }

                    pruneMatchingValues(styleData[state], styleData.default);
                    if (Object.keys(styleData[state]).length === 0) {
                        delete styleData[state];
                    }
                });

                return styleData;
            }

            Object.keys(styleData).forEach((key) => {
                if (typeof styleData[key] === "object" && styleData[key] !== null && !Array.isArray(styleData[key])) {
                    const prunedChild = pruneStyleOverrides(styleData[key]);
                    if (!prunedChild || typeof prunedChild !== "object" || Array.isArray(prunedChild) || Object.keys(prunedChild).length === 0) {
                        delete styleData[key];
                    } else {
                        styleData[key] = prunedChild;
                    }
                }
            });

            return styleData;
        }

        function pruneMatchingValues(target, reference) {
            if (!target || typeof target !== "object" || Array.isArray(target)) {
                return;
            }

            Object.keys(target).forEach((key) => {
                const targetValue = target[key];
                const referenceValue = reference && typeof reference === "object" ? reference[key] : undefined;

                if (targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
                    pruneMatchingValues(targetValue, referenceValue || {});
                    if (Object.keys(targetValue).length === 0) {
                        delete target[key];
                    }
                } else if (referenceValue !== undefined && String(targetValue) === String(referenceValue)) {
                    delete target[key];
                }
            });
        }';
    }

    /**
     * Validate all dimension inputs contain only numbers
     */
    public function validateDimensionInputs()
    {
        return 'function validateDimensionInputs() {
            const dimensionInputs = document.querySelectorAll(".griffinforms-dimension-input, .griffinforms-side-dimension");
            const validPattern = /^-?[\d.]+$/;

            for (const input of dimensionInputs) {
                const value = input.value.trim();

                // Skip empty inputs (they default to 0)
                if (!value) {
                    continue;
                }

                // Check if value is a valid number
                if (!validPattern.test(value)) {
                    input.classList.add("border-danger");
                    showItemError("Dimension must be a number (e.g., 10, 1.5, -5). Do not include units here.");
                    return false;
                } else {
                    input.classList.remove("border-danger");
                }
            }

            return true;
        }';
    }

    /**
     * Check if all required data getter functions exist
     */
    public function checkItemDataFunctions()
    {
        $required_functions = array(
            'getName', 'getDescription', 'getCategory',
            'getFormStyle', 'getPageStyle', 'getRowStyle', 'getFieldStyle',
            'getSubmitButton', 'getPreviousButton', 'getNextButton',
            'getFormTitle', 'getFormDescription',
            'getPageHeading', 'getPageDescription',
            'getRowHeading', 'getRowDescription',
            'getFieldLabel', 'getFieldDescription', 'getFieldErrors', 'getSuccessMessage'
        );

        $js = $this->getMergeJsHelpers();
        $js .= 'function checkItemDataFunctions() {';

        foreach ($required_functions as $function_name) {
            $js .= 'if (typeof ' . esc_html($function_name) . ' !== "function") {
                alert("Missing JS function: ' . esc_js($function_name) . '");
            }' . PHP_EOL;
        }

        $js .= '};';
        return $js;
    }

    /**
     * Deep merge helper for style sections (used in getFieldErrorsData/getSuccessMessageData).
     */
    protected function getMergeJsHelpers()
    {
        return '
        function mergeStyleSections(primary, secondary) {
            if (!primary && !secondary) {
                return null;
            }

            const base = cloneDeep(primary || {});
            mergeObjects(base, secondary || {});

            return Object.keys(base).length > 0 ? base : null;
        }

        function mergeObjects(target, source) {
            if (!source || typeof source !== "object") {
                return;
            }

            Object.keys(source).forEach((key) => {
                const sourceValue = source[key];

                if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
                    if (!target[key] || typeof target[key] !== "object") {
                        target[key] = {};
                    }
                    mergeObjects(target[key], sourceValue);
                } else {
                    target[key] = sourceValue;
                }
            });
        }

        function cloneDeep(value) {
            if (value === null || value === undefined) {
                return value;
            }

            return JSON.parse(JSON.stringify(value));
        }
        ';
    }

    /**
     * Assemble theme data from individual getter functions
     */
    public function itemData()
    {
        $js = 'function getItemData() {
            const itemData = {};

            // Validate dimension inputs first
            if (!validateDimensionInputs()) {
                return null;
            }

            itemData["name"] = getName();
            itemData["description"] = getDescription();
            itemData["category"] = getCategory();
            itemData["form_style"] = getFormStyle();
            itemData["page_style"] = getPageStyle();
            itemData["row_style"] = getRowStyle();
            itemData["field_style"] = getFieldStyle();
            itemData["submit_button"] = getSubmitButton();
            itemData["previous_button"] = getPreviousButton();
            itemData["next_button"] = getNextButton();
            itemData["button_typography"] = getButtonTypographyData();
            itemData["form_title"] = getFormTitle();
            itemData["form_description"] = getFormDescription();
            itemData["page_heading"] = getPageHeading();
            itemData["page_description"] = getPageDescription();
            itemData["row_heading"] = getRowHeading();
            itemData["row_description"] = getRowDescription();
            itemData["field_label"] = getFieldLabel();
            itemData["field_description"] = getFieldDescription();
            itemData["field_errors"] = getFieldErrors();
            itemData["success_message"] = getSuccessMessage();
            return itemData;
        };';

        return $js;
    }
}
