<?php

namespace GriffinForms\Includes\ImportExport;

use GriffinForms\Items\FormTheme;

class FormThemeImport
{
    protected $wpdb;
    protected $config;
    protected $log;

    // Required keys for theme JSON structure
    protected $required_theme_keys = ['theme_name', 'theme_category', 'styles'];

    // Character limits
    protected $name_max_length = 100;
    protected $description_max_length = 500;
    protected $file_size_limit = 1048576; // 1 MB in bytes

    protected $default_styles_cache = null;

    public function __construct()
    {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->config = \GriffinForms\Config::getInstance();
        $this->log = \GriffinForms\Log::getInstance();
    }

    /**
     * Main entry point for importing a theme
     *
     * @param array $theme_data Theme data array with name, category, description, and styles
     * @return array Response with status and data
     */
    public function importTheme($theme_data)
    {
        // Validate required fields
        $validation = $this->validateThemeData($theme_data);
        if (!$validation['valid']) {
            $this->log->add(
                'warning',
                'formtheme',
                0,
                get_current_user_id(),
                sprintf('Theme import validation failed: %s', $validation['message']),
                'theme_import'
            );
            return [
                'success' => false,
                'message' => $validation['message'],
                'error_field' => $validation['error_field'] ?? null
            ];
        }

        // Sanitize the data
        $sanitized = $this->sanitizeThemeData($theme_data);

        // Insert into database
        $theme_id = $this->insertTheme($sanitized);

        if (!$theme_id) {
            $this->log->add('error', 'theme_import', 0, get_current_user_id(), 'Failed to insert theme into database', 'data');
            return [
                'success' => false,
                'message' => 'Failed to import theme. Database error occurred.'
            ];
        }

        $this->log->add(
            'info',
            'formtheme',
            (int) $theme_id,
            get_current_user_id(),
            sprintf('Theme "%s" imported successfully', sanitize_text_field($theme_data['theme_name'])),
            'theme_import'
        );

        return [
            'success' => true,
            'message' => sprintf('Theme "%s" imported successfully!', sanitize_text_field($theme_data['theme_name'])),
            'theme_id' => $theme_id
        ];
    }

    /**
     * Validate theme data structure and required fields
     *
     * @param array $theme_data
     * @return array Validation result with 'valid' bool, 'message', and optional 'error_field'
     */
    protected function validateThemeData($theme_data)
    {
        if (!is_array($theme_data) || empty($theme_data)) {
            return [
                'valid' => false,
                'message' => 'No theme data provided'
            ];
        }

        // Check required top-level keys
        foreach ($this->required_theme_keys as $key) {
            if (!isset($theme_data[$key]) || $theme_data[$key] === '') {
                return [
                    'valid' => false,
                    'message' => sprintf('Missing required field: %s', $key),
                    'error_field' => $key
                ];
            }
        }

        // Validate theme_name
        $name = $theme_data['theme_name'];
        if (!is_string($name)) {
            return [
                'valid' => false,
                'message' => 'Theme name must be a string',
                'error_field' => 'theme_name'
            ];
        }

        if (strlen($name) > $this->name_max_length) {
            return [
                'valid' => false,
                'message' => sprintf('Theme name cannot exceed %d characters', $this->name_max_length),
                'error_field' => 'theme_name'
            ];
        }

        if (strlen(trim($name)) === 0) {
            return [
                'valid' => false,
                'message' => 'Theme name cannot be empty',
                'error_field' => 'theme_name'
            ];
        }

        // Validate theme_category
        $category = $theme_data['theme_category'];
        if (!is_string($category)) {
            return [
                'valid' => false,
                'message' => 'Category must be a string',
                'error_field' => 'theme_category'
            ];
        }

        if (strlen(trim($category)) === 0) {
            return [
                'valid' => false,
                'message' => 'Category cannot be empty',
                'error_field' => 'theme_category'
            ];
        }

        // Validate theme_description (optional, but check limit if provided)
        if (isset($theme_data['theme_description']) && $theme_data['theme_description'] !== '') {
            $description = $theme_data['theme_description'];
            if (!is_string($description)) {
                return [
                    'valid' => false,
                    'message' => 'Description must be a string',
                    'error_field' => 'theme_description'
                ];
            }

            if (strlen($description) > $this->description_max_length) {
                return [
                    'valid' => false,
                    'message' => sprintf('Description cannot exceed %d characters', $this->description_max_length),
                    'error_field' => 'theme_description'
                ];
            }
        }

        // Validate styles object
        $styles = $theme_data['styles'];
        if (!is_array($styles) || empty($styles)) {
            return [
                'valid' => false,
                'message' => 'Theme styles must be a non-empty object'
            ];
        }

        // Check for required style keys
        // Allow missing sections (they will be auto-filled later), but structure must remain arrays when present
        foreach (FormTheme::getStylePropertyKeys() as $key) {
            if (isset($styles[$key]) && !is_array($styles[$key])) {
                return [
                    'valid' => false,
                    'message' => sprintf('Style property %s must be an object', $key)
                ];
            }
        }

        // Validate that styles are properly structured arrays
        if (!$this->validateStylesStructure($styles)) {
            return [
                'valid' => false,
                'message' => 'Invalid theme styles structure. Expected nested arrays for styles.'
            ];
        }

        return [
            'valid' => true
        ];
    }

    /**
     * Validate that styles have proper array structure
     *
     * @param array $styles
     * @return bool
     */
    protected function validateStylesStructure($styles)
    {
        foreach (FormTheme::getStylePropertyKeys() as $prop) {
            if (isset($styles[$prop]) && !is_array($styles[$prop])) {
                return false;
            }
        }

        return true;
    }

    /**
     * Sanitize theme data recursively
     *
     * @param array $theme_data
     * @return array Sanitized theme data
     */
    protected function sanitizeThemeData($theme_data)
    {
        $sanitized = [];

        // Sanitize text fields
        $sanitized['theme_name'] = sanitize_text_field($theme_data['theme_name']);
        $sanitized['theme_category'] = sanitize_text_field($theme_data['theme_category']);
        $sanitized['theme_description'] = isset($theme_data['theme_description'])
            ? sanitize_text_field($theme_data['theme_description'])
            : '';

        // Recursively sanitize styles (preserve array structure)
        $styles = $this->sanitizeStylesRecursive($theme_data['styles']);
        $styles = $this->ensureRequiredStyleKeys($styles);
        $styles = $this->postProcessStyles($styles);
        $sanitized['styles'] = $styles;

        return $sanitized;
    }

    /**
     * Recursively sanitize style values while preserving structure
     *
     * @param array $styles
     * @return array Sanitized styles
     */
    protected function sanitizeStylesRecursive($styles)
    {
        $sanitized = [];

        foreach ($styles as $key => $value) {
            if (is_array($value)) {
                $sanitized[$key] = $this->sanitizeStylesRecursive($value);
            } elseif (is_string($value)) {
                $sanitized[$key] = FormTheme::sanitizeCssString($value);
            } else {
                // Keep numeric and other values as-is
                $sanitized[$key] = $value;
            }
        }

        return $sanitized;
    }

    /**
     * Make sure every canonical style block exists.
     *
     * @param array $styles
     * @return array
     */
    protected function ensureRequiredStyleKeys(array $styles)
    {
        foreach (FormTheme::getStylePropertyKeys() as $key) {
            if (!array_key_exists($key, $styles)) {
                $styles[$key] = array();
                $this->logSanitizationNotice(sprintf('Missing style block "%s" auto-filled during import.', $key));
            }
        }

        return $styles;
    }

    /**
     * Apply additional normalization rules to style data.
     *
     * @param array $styles
     * @return array
     */
    protected function postProcessStyles(array $styles)
    {
        $styles = $this->normalizeFontWeightsInArray($styles);

        if (isset($styles['field_style']['checkbox_radio'])) {
            $styles['field_style']['checkbox_radio'] = $this->normalizeCheckboxRadioStyles($styles['field_style']['checkbox_radio']);
        }

        if (isset($styles['field_style']['select_input'])) {
            $styles['field_style']['select_input'] = $this->stripSelectBackgroundImages($styles['field_style']['select_input']);
        }

        return $styles;
    }

    protected function normalizeFontWeightsInArray(array $styles)
    {
        array_walk_recursive($styles, function (&$value, $key) {
            if ($key !== 'font-weight' || !is_string($value)) {
                return;
            }
            $value = $this->normalizeFontWeightValue($value);
        });

        return $styles;
    }

    protected function normalizeFontWeightValue($value)
    {
        $value = trim((string) $value);
        if ($value === '') {
            return '400';
        }

        if (is_numeric($value)) {
            return (string) $value;
        }

        $map = array(
            'normal' => '400',
            'regular' => '400',
            'medium' => '500',
            'semibold' => '600',
            'semi-bold' => '600',
            'bold' => '700',
            'light' => '300'
        );

        $lower = strtolower($value);
        return $map[$lower] ?? '400';
    }

    protected function normalizeCheckboxRadioStyles($states)
    {
        if (!is_array($states)) {
            return array();
        }

        $allowed = array('accent_color', 'size', 'margin', 'custom_css');
        $normalized = array();

        foreach ($states as $state => $props) {
            if (!is_array($props)) {
                $normalized[$state] = array();
                continue;
            }

            $clean = array();
            foreach ($props as $key => $value) {
                if (in_array($key, $allowed, true)) {
                    $clean[$key] = $value;
                }
            }

            if (!isset($clean['margin'])) {
                $clean['margin'] = array(
                    'top' => '10px',
                    'right' => '5px',
                    'bottom' => '10px',
                    'left' => '0px'
                );
                $this->logSanitizationNotice(sprintf('Added default margin for checkbox_radio %s state.', $state));
            }

            $normalized[$state] = $clean;

            $removed_keys = array_diff(array_keys($props), array_keys($clean));
            if (!empty($removed_keys)) {
                $this->logSanitizationNotice(sprintf(
                    'Removed unsupported checkbox_radio keys (%s) from %s state.',
                    implode(', ', $removed_keys),
                    $state
                ));
            }
        }

        return $normalized;
    }

    protected function stripSelectBackgroundImages($states)
    {
        if (!is_array($states)) {
            return $states;
        }

        foreach ($states as $state => &$props) {
            if (!is_array($props)) {
                continue;
            }

            $removed = false;
            if (isset($props['background-image'])) {
                unset($props['background-image']);
                $removed = true;
            }
            if (isset($props['background_image'])) {
                unset($props['background_image']);
                $removed = true;
            }
            unset($props['background_mode']);

            if ($removed) {
                $this->logSanitizationNotice(sprintf(
                    'Removed background-image from select_input %s state during import.',
                    $state
                ));
            }
        }
        unset($props);

        return $states;
    }

    protected function logSanitizationNotice($message)
    {
        $this->log->add(
            'notice',
            'formtheme',
            0,
            get_current_user_id(),
            $message,
            'theme_import'
        );
    }

    /**
     * Insert theme into database
     *
     * @param array $theme_data Sanitized theme data
     * @return int|false Theme ID on success, false on failure
     */
    protected function insertTheme($theme_data)
    {
        $table = $this->config->getTable('formtheme');

        // Prepare styles data - serialize for storage
        $styles_json = wp_json_encode($theme_data['styles']);

        try {
            $result = $this->wpdb->insert(
                $table,
                [
                    'name' => $theme_data['theme_name'],
                    'description' => $theme_data['theme_description'],
                    'category' => $theme_data['theme_category'],
                    'form_style' => maybe_serialize($theme_data['styles']['form_style'] ?? []),
                    'page_style' => maybe_serialize($theme_data['styles']['page_style'] ?? []),
                    'row_style' => maybe_serialize($theme_data['styles']['row_style'] ?? []),
                    'field_style' => maybe_serialize($theme_data['styles']['field_style'] ?? []),
                    'button_typography' => maybe_serialize($theme_data['styles']['button_typography'] ?? []),
                    'submit_button' => maybe_serialize($theme_data['styles']['submit_button'] ?? []),
                    'previous_button' => maybe_serialize($theme_data['styles']['previous_button'] ?? []),
                    'next_button' => maybe_serialize($theme_data['styles']['next_button'] ?? []),
                    'form_title' => maybe_serialize($theme_data['styles']['form_title'] ?? []),
                    'form_description' => maybe_serialize($theme_data['styles']['form_description'] ?? []),
                    'page_heading' => maybe_serialize($theme_data['styles']['page_heading'] ?? []),
                    'page_description' => maybe_serialize($theme_data['styles']['page_description'] ?? []),
                    'row_heading' => maybe_serialize($theme_data['styles']['row_heading'] ?? []),
                    'row_description' => maybe_serialize($theme_data['styles']['row_description'] ?? []),
                    'field_label' => maybe_serialize($theme_data['styles']['field_label'] ?? []),
                    'field_description' => maybe_serialize($theme_data['styles']['field_description'] ?? []),
                    'field_errors' => maybe_serialize($theme_data['styles']['field_errors'] ?? []),
                    'success_message' => maybe_serialize($theme_data['styles']['success_message'] ?? []),
                    'origin' => 'user',
                    'author' => get_current_user_id(),
                    'created' => current_time('mysql', true)
                ],
                [
                    '%s', // name
                    '%s', // description
                    '%s', // category
                    '%s', // form_style
                    '%s', // page_style
                    '%s', // row_style
                    '%s', // field_style
                    '%s', // button_typography
                    '%s', // submit_button
                    '%s', // previous_button
                    '%s', // next_button
                    '%s', // form_title
                    '%s', // form_description
                    '%s', // page_heading
                    '%s', // page_description
                    '%s', // row_heading
                    '%s', // row_description
                    '%s', // field_label
                    '%s', // field_description
                    '%s', // field_errors
                    '%s', // success_message
                    '%s', // origin
                    '%d', // author
                    '%s'  // created
                ]
            );

            if ($result === false) {
                $this->log->add('error', 'theme_import', 0, get_current_user_id(), $this->wpdb->last_error, 'data');
                return false;
            }

            return $this->wpdb->insert_id;
        } catch (\Exception $e) {
            $this->log->add('error', 'theme_import', 0, get_current_user_id(), 'Exception: ' . $e->getMessage(), 'data');
            return false;
        }
    }
}
