<?php

namespace GriffinForms\Admin\App\Html\Modals\FormThemes;

trait Responses
{
    /**
     * Registers AJAX handlers for the FormThemes modal.
     */
    protected function register()
    {
        add_action('wp_ajax_getFormThemeCategories', array($this, 'getFormThemeCategories'));
        add_action('wp_ajax_getFormThemesByCategory', array($this, 'getFormThemesByCategory'));
        add_action('wp_ajax_applyFormTheme', array($this, 'applyFormTheme'));
        add_action('wp_ajax_importFormTheme', array($this, 'importFormTheme'));
    }

    /**
     * AJAX handler: Returns all FormTheme categories with theme counts.
     */
    public function getFormThemeCategories()
    {
        $this->checkRequest('get_form_theme_categories');

        if (!is_object($this->sql)) {
            $this->setSql();
        }

        if (!is_object($this->sql) || !method_exists($this->sql, 'getFormThemeCategories')) {
            wp_send_json_error(array(
                'msg' => __('Unable to load theme categories.', 'griffinforms-form-builder'),
            ));
        }

        $categories = $this->sql->getFormThemeCategories();

        if (empty($categories)) {
            wp_send_json_error(array(
                'msg' => __('No theme categories available.', 'griffinforms-form-builder'),
            ));
        }

        $categories = $this->addAllCategoryOption($categories);
        $requested_category = isset($_POST['active_category']) ? sanitize_text_field(wp_unslash($_POST['active_category'])) : '';
        $active_category = $this->resolveActiveCategory($categories, $requested_category);
        $categories_html = $this->renderThemeCategoriesHtml($categories, $active_category);

        // Extract category names for import form dropdown
        $category_names = array();
        foreach ($categories as $category) {
            $cat_name = is_object($category) ? ($category->category ?? null) : ($category['category'] ?? null);
            if ($cat_name && $cat_name !== 'all') {
                $category_names[] = $cat_name;
            }
        }

        wp_send_json_success(array(
            'categories_html' => $categories_html,
            'active_category' => $active_category,
            'categories' => $category_names,
        ));
    }

    /**
     * AJAX handler: Returns FormThemes for a given category.
     */
    public function getFormThemesByCategory()
    {
        $this->checkRequest('get_form_themes_by_category');

        $category = isset($_POST['category']) ? sanitize_text_field(wp_unslash($_POST['category'])) : '';
        $form_id = isset($_POST['form_id']) ? absint(wp_unslash($_POST['form_id'])) : 0;
        $offset = isset($_POST['offset']) ? max(0, absint(wp_unslash($_POST['offset']))) : 0;
        $limit = isset($_POST['limit']) ? absint(wp_unslash($_POST['limit'])) : 6;

        if ($limit < 1) {
            $limit = 6;
        } elseif ($limit > 50) {
            $limit = 50;
        }

        if (!is_object($this->sql)) {
            $this->setSql();
        }

        if (!is_object($this->sql) || !method_exists($this->sql, 'getFormThemesByCategory')) {
            wp_send_json_error(array(
                'msg' => __('Unable to load themes.', 'griffinforms-form-builder'),
            ));
        }

        $total_count = method_exists($this->sql, 'getFormThemeCount') ? $this->sql->getFormThemeCount($category) : 0;

        if ($offset >= $total_count && $total_count > 0) {
            $themes = array();
        } else {
            $themes = $this->sql->getFormThemesByCategory($category, $offset, $limit);
        }

        $loaded_count = is_array($themes) ? count($themes) : 0;
        $active_theme_id = 0;

        if ($form_id > 0 && method_exists($this->sql, 'itemValues')) {
            $form_row = $this->sql->itemValues($form_id, 'form', array('form_theme'));
            if ($form_row && isset($form_row->form_theme)) {
                $active_theme_id = absint($form_row->form_theme);
            }
        }

        $is_append = $offset > 0;
        $include_default = ($category === 'all' && $offset === 0);

        // Use different rendering methods based on whether this is an append or initial load
        if ($is_append) {
            $themes_html = $this->renderThemeCardsItemsHtml($themes, $active_theme_id);
        } else {
            $themes_html = $this->renderThemeCardsHtml($themes, $active_theme_id, $include_default);
        }

        $has_more = ($offset + $loaded_count) < $total_count;
        $message = '';

        if ($loaded_count === 0 && $offset === 0) {
            $message = __('No themes found in this category.', 'griffinforms-form-builder');
        }

        wp_send_json_success(array(
            'themes_html' => $themes_html,
            'active_theme_id' => $active_theme_id,
            'has_more' => $has_more,
            'loaded_count' => $loaded_count,
            'total_count' => $total_count,
            'message' => $message,
            'is_append' => $is_append,
        ));
    }

    /**
     * AJAX handler: Applies a FormTheme to a specific form.
     */
    public function applyFormTheme()
    {
        $this->checkRequest('apply_form_theme');

        $form_id = isset($_POST['form_id']) ? absint(wp_unslash($_POST['form_id'])) : 0;
        $theme_id = isset($_POST['theme_id']) ? absint(wp_unslash($_POST['theme_id'])) : 0;

        if ($form_id < 1) {
            wp_send_json_error(array(
                'msg' => __('Missing form identifier.', 'griffinforms-form-builder'),
            ));
        }

        if ($theme_id < 0) {
            wp_send_json_error(array(
                'msg' => __('Missing theme identifier.', 'griffinforms-form-builder'),
            ));
        }

        if (!is_object($this->sql)) {
            $this->setSql();
        }

        if (!is_object($this->sql)) {
            wp_send_json_error(array(
                'msg' => __('Unable to process request. Please refresh and try again.', 'griffinforms-form-builder'),
            ));
        }

        if (!$this->sql->itemExists('form', $form_id)) {
            wp_send_json_error(array(
                'msg' => __('The selected form no longer exists.', 'griffinforms-form-builder'),
            ));
        }

        if ($theme_id > 0 && !$this->sql->itemExists('formtheme', $theme_id)) {
            wp_send_json_error(array(
                'msg' => __('The selected theme could not be found.', 'griffinforms-form-builder'),
            ));
        }

        $updated = $this->sql->updateItemValue('form', $form_id, 'form_theme', $theme_id);

        if ($updated === false) {
            wp_send_json_error(array(
                'msg' => __('Failed to apply the theme to the form.', 'griffinforms-form-builder'),
            ));
        }

        $external_fonts = array();
        $page_bg_color  = '';

        if ($theme_id > 0) {
            $form_theme = new \GriffinForms\Items\FormTheme();
            if ($form_theme->loadItem($theme_id)) {
                $fonts = $form_theme->getExternalFontFamilies();
                if (is_array($fonts)) {
                    $external_fonts = array_values(array_filter(array_map('trim', $fonts)));
                }
                $page_bg_color = $form_theme->getPageBackgroundColor();
            }
        }

        if ($theme_id === 0) {
            $message = $updated > 0
                ? __('Default styling restored for form.', 'griffinforms-form-builder')
                : __('Default styling already active for this form.', 'griffinforms-form-builder');
        } else {
            $message = $updated > 0
                ? __('Theme applied to form.', 'griffinforms-form-builder')
                : __('Theme already applied to this form.', 'griffinforms-form-builder');
        }

        if (is_object($this->log)) {
            $this->log->add(
                'info',
                'form',
                $form_id,
                (int) get_current_user_id(),
                $message,
                'audit'
            );
        }

        $this->fireFormModifiedHook($form_id, 'form_theme', array(
            'theme_id' => $theme_id,
            'changed' => ($updated > 0),
        ));

        wp_send_json_success(array(
            'form_id'        => $form_id,
            'theme_id'       => $theme_id,
            'changed'        => ($updated > 0),
            'has_theme'      => ($theme_id > 0),
            'message'        => $message,
            'external_fonts' => $external_fonts,
            'page_bg_color'  => $page_bg_color,
        ));
    }

    /**
     * Fires a unified form modified hook for FormTheme updates.
     *
     * @param int   $form_id Form ID being modified.
     * @param mixed $source  Source area triggering the modification.
     * @param array $meta    Additional context about the modification.
     */
    protected function fireFormModifiedHook(int $form_id, $source, array $meta = array()): void
    {
        if ($form_id <= 0) {
            return;
        }

        /**
         * Fires after a form is modified anywhere in the admin.
         *
         * @param int    $form_id Form ID being modified.
         * @param string $source  Source area triggering the modification.
         * @param array  $meta    Additional context about the modification.
         */
        do_action(
            'griffinforms_form_modified',
            $form_id,
            (string) $source,
            $meta
        );

        /**
         * Fires after a FormTheme is applied to a form.
         *
         * @param int   $form_id  Form ID being modified.
         * @param int   $theme_id Applied theme ID (0 for default).
         * @param array $meta     Additional context about the modification.
         */
        do_action(
            'griffinforms_form_theme_applied',
            $form_id,
            isset($meta['theme_id']) ? (int) $meta['theme_id'] : 0,
            $meta
        );
    }

    /**
     * AJAX handler: Imports a new FormTheme from JSON data.
     */
    public function importFormTheme()
    {
        // Verify nonce - must be done before checkRequest
        if (!isset($_POST['nonce'])) {
            wp_send_json_error(array(
                'msg' => __('Missing security token. Please refresh and try again.', 'griffinforms-form-builder'),
            ));
        }

        $this->checkRequest('import_form_theme');

        // Get POST parameters
        $theme_name = isset($_POST['theme_name']) ? sanitize_text_field(wp_unslash($_POST['theme_name'])) : '';
        $theme_category = isset($_POST['theme_category']) ? sanitize_text_field(wp_unslash($_POST['theme_category'])) : '';
        $theme_description = isset($_POST['theme_description']) ? sanitize_text_field(wp_unslash($_POST['theme_description'])) : '';
        $theme_json = isset($_POST['theme_json']) ? wp_unslash($_POST['theme_json']) : '';

        // Validate that we have JSON data
        if (empty($theme_json)) {
            wp_send_json_error(array(
                'msg' => __('No JSON data provided.', 'griffinforms-form-builder'),
                'field' => 'theme_json',
            ));
        }

        // Parse JSON
        $parsed_json = json_decode($theme_json, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            wp_send_json_error(array(
                'msg' => __('Invalid JSON format.', 'griffinforms-form-builder'),
                'field' => 'theme_json',
            ));
        }

        if (!is_array($parsed_json)) {
            wp_send_json_error(array(
                'msg' => __('JSON must contain an object.', 'griffinforms-form-builder'),
                'field' => 'theme_json',
            ));
        }

        // Use provided values if not empty, otherwise fall back to JSON data
        if (empty($theme_name) && isset($parsed_json['theme_name'])) {
            $theme_name = sanitize_text_field($parsed_json['theme_name']);
        }

        if (empty($theme_category) && isset($parsed_json['theme_category'])) {
            $theme_category = sanitize_text_field($parsed_json['theme_category']);
        }

        if (empty($theme_description) && isset($parsed_json['theme_description'])) {
            $theme_description = sanitize_text_field($parsed_json['theme_description']);
        }

        // Build theme data array for import
        $theme_data = array(
            'theme_name' => $theme_name,
            'theme_category' => $theme_category,
            'theme_description' => $theme_description,
            'styles' => $parsed_json['styles'] ?? []
        );

        // Use FormThemeImport class to import the theme
        try {
            $importer = new \GriffinForms\Includes\ImportExport\FormThemeImport();
            $result = $importer->importTheme($theme_data);

            if (!$result['success']) {
                $error_field = $result['error_field'] ?? 'theme_json';
                wp_send_json_error(array(
                    'msg' => $result['message'],
                    'field' => $error_field,
                ));
            }

            // Success response
            wp_send_json_success(array(
                'msg' => $result['message'],
                'theme_id' => $result['theme_id'],
            ));
        } catch (\Exception $e) {
            wp_send_json_error(array(
                'msg' => __('An error occurred while importing the theme.', 'griffinforms-form-builder'),
            ));
        }
    }

    /**
     * Adds an aggregate "All" category entry to the categories list.
     *
     * @param array $categories Category rows from the database.
     * @return array
     */
    protected function addAllCategoryOption($categories)
    {
        $list = is_array($categories) ? $categories : array();
        $total_count = 0;

        foreach ($list as $category) {
            $count = is_object($category) ? (int) ($category->count ?? 0) : (int) ($category['count'] ?? 0);
            $total_count += $count;
        }

        $all_category = (object) array(
            'category' => 'all',
            'count' => $total_count,
        );

        array_unshift($list, $all_category);

        return $list;
    }
}
