<?php


namespace GriffinForms;

require_once __DIR__ . '/admin/choices/general.php';
require_once __DIR__ . '/settings.php';

class InstallData extends Format 
{
    protected $config;
    protected $log;

    public function __construct()
    {
        // Initialize core dependencies (config, settings, log, etc.)
        $this->setAll();
    }
    
    public function addData()
    {
        $this->addDefaultGeneralSettings();
        $this->addDefaultLogSettings();
        $this->addTemplatesToDb();
        $this->addEmailTemplatesToDb();
        $this->addDefaultFormThemes();
        $this->addDefaultFolders();
    }

    protected function addDefaultGeneralSettings(): void
    {
        $settings = Settings::getInstance();
        $exclude_admin = $settings->getOption('exclude_admin_submissions_from_lifetime_count');
        if ($exclude_admin === null || $exclude_admin === '') {
            $settings->updateOption('exclude_admin_submissions_from_lifetime_count', 0, 'general');
        }
    }

    /**
     * Seed default log settings on first install.
     * If logging was explicitly disabled earlier (value = 0), do not override.
     */
    protected function addDefaultLogSettings(): void
    {
        $settings = Settings::getInstance();

        // Respect explicit opt-out
        $enabled = $settings->getOption('enable_native_logging');
        if ($enabled === '0' || $enabled === 0) {
            return;
        }

        // Enable logging by default if not set
        if ($enabled === null || $enabled === '' || $enabled === false) {
            $settings->updateOption('enable_native_logging', 1, 'general');
        }

        // Default message types: all available choices
        $types_current = $settings->getOption('log_message_types');
        if ($types_current === null || $types_current === '' || (is_array($types_current) && count($types_current) === 0)) {
            $choices = \GriffinForms\Admin\Choices\General::getInstance()->getChoices('log_message_types'); // value => label
            if (is_array($choices) && !empty($choices)) {
                $all_keys = array_keys($choices);
                $settings->updateOption('log_message_types', $all_keys, 'general');
            }
        }

        // Default retention: latest_10000
        $retention = $settings->getOption('log_retention');
        if ($retention === null || $retention === '') {
            $settings->updateOption('log_retention', 'latest_10000', 'general');
        }
    }

    public function addTemplatesToDb($force_reimport = false) {
        global $wpdb;
        $table = $this->config->getTable('template');
        $templates_dir = $this->config->getRootPath() . 'admin/templates/';
        $template_files = glob($templates_dir . '*.json');

        if (!$force_reimport && $this->tableHasRows($table)) {
            return;
        }

        $inserted = 0;
        $updated = 0;
        $skipped = 0;

        foreach ($template_files as $file) {
            $template_data = json_decode(file_get_contents($file), true);
            if (!is_array($template_data)) {
                $this->log->add('error', 'template', 0, 0, 'Template import failed: Invalid JSON in ' . basename($file), 'template');
                $skipped++;
                continue;
            }

            $template_data['description'] = $template_data['description'] ?? '';
            $template_data['category']    = $template_data['category'] ?? '';
            $template_data['tags']        = $template_data['tags'] ?? [];
            $template_data['form_data']   = $template_data['form_data'] ?? [];

            $version = isset($template_data['version']) ? intval($template_data['version']) : 1;
            $result = $wpdb->insert($table, [
                'name'        => sanitize_text_field($template_data['name']),
                'description' => sanitize_text_field($template_data['description']),
                'category'    => sanitize_text_field($template_data['category']),
                'tags'        => maybe_serialize($template_data['tags']),
                'author'      => 0,
                'created_at'  => current_time('mysql'),
                'form_data'   => maybe_serialize($template_data['form_data']),
                'origin'      => 'prebuilt',
                'version'     => $version
            ]);
            if ($result === false) {
                $skipped++;
                continue;
            }

            $inserted++;
        }

        $this->log->add('info', 'template', 0, 0, "Template installation summary: Inserted $inserted, Updated $updated, Skipped $skipped", 'template');
    }

    public function addEmailTemplatesToDb($force_reimport = false)
    {
        global $wpdb;

        $table = $this->config->getTable('message');
        $templates_dir = $this->config->getRootPath() . 'admin/email_templates/';

        if (!is_dir($templates_dir)) {
            return;
        }

        $template_files = glob($templates_dir . '*.json');
        if (empty($template_files)) {
            return;
        }

        if (!$force_reimport && $this->tableHasRows($table)) {
            return;
        }

        $inserted = 0;
        $updated = 0;
        $skipped = 0;

        foreach ($template_files as $file) {
            $template_data = json_decode(file_get_contents($file), true);
            if (!is_array($template_data)) {
                $this->log->add('error', 'message', 0, 0, 'Email template import failed: Invalid JSON in ' . basename($file), 'message');
                $skipped++;
                continue;
            }

            $name = sanitize_text_field($template_data['name'] ?? '');
            if ($name === '') {
                $this->log->add('error', 'message', 0, 0, 'Email template import skipped: Missing name in ' . basename($file), 'message');
                $skipped++;
                continue;
            }

            $heading = sanitize_text_field($template_data['heading'] ?? '');
            $description = sanitize_text_field($template_data['description'] ?? '');
            $content = $template_data['content'] ?? '';
            $content = is_string($content) ? wp_kses_post($content) : '';

            $data = array(
                'name'        => $name,
                'heading'     => $heading,
                'description' => $description,
                'content'     => $content,
                'last_editor' => 0,
                'last_edited' => current_time('mysql', true),
            );

            $data['author'] = 0;
            $data['created'] = current_time('mysql', true);

            $result = $wpdb->insert($table, $data);
            if ($result === false) {
                $skipped++;
                continue;
            }

            $inserted++;
        }

        $this->log->add('info', 'message', 0, 0, "Email template installation summary: Inserted $inserted, Updated $updated, Skipped $skipped", 'message');
    }

    /**
     * Import default FormTheme templates from admin/themes directory on activation.
     * Themes are pre-built, professional designs available to all users.
     *
     * @param bool $force_reimport Force reimport even if theme exists
     * @return void
     */
    public function addDefaultFormThemes($force_reimport = false)
    {
        global $wpdb;

        $table      = $this->config->getTable('formtheme');
        $themes_dir = $this->config->getRootPath() . 'admin/themes/';
        $theme_files = glob($themes_dir . '*.json');
        $style_keys = \GriffinForms\Items\FormTheme::getStylePropertyKeys();

        if (!$force_reimport && $this->tableHasRows($table)) {
            return;
        }

        $inserted = 0;
        $updated  = 0;
        $skipped  = 0;

        foreach ($theme_files as $file) {
            $contents   = file_get_contents($file);
            $theme_data = json_decode($contents, true);

            if (!is_array($theme_data)) {
                $this->log->add(
                    'error',
                    'formtheme',
                    0,
                    0,
                    'FormTheme import failed: Invalid JSON in ' . basename($file),
                    'formtheme'
                );
                $skipped++;
                continue;
            }

            $theme_name = sanitize_text_field($theme_data['theme_name'] ?? '');
            if ($theme_name === '') {
                $this->log->add(
                    'error',
                    'formtheme',
                    0,
                    0,
                    'FormTheme import skipped: Missing theme_name in ' . basename($file),
                    'formtheme'
                );
                $skipped++;
                continue;
            }

            if (empty($theme_data['styles']) || !is_array($theme_data['styles'])) {
                $this->log->add(
                    'error',
                    'formtheme',
                    0,
                    0,
                    'FormTheme import skipped: Missing styles block in ' . basename($file),
                    'formtheme'
                );
                $skipped++;
                continue;
            }

            $theme_description = sanitize_text_field($theme_data['theme_description'] ?? '');
            $theme_category    = sanitize_text_field($theme_data['theme_category'] ?? 'default');
            $version           = isset($theme_data['version']) ? floatval($theme_data['version']) : 1.0;

            $styles = $this->sanitizeThemeStylesRecursive($theme_data['styles']);
            $styles = $this->ensureThemeStyleKeys($styles, $style_keys);
            $style_payload = $this->prepareThemeStylePayload($styles, $style_keys);

            $data = array_merge(
                array(
                    'name'        => $theme_name,
                    'description' => $theme_description,
                    'category'    => $theme_category,
                    'origin'      => 'prebuilt',
                    'version'     => $version,
                ),
                $style_payload
            );

            $data['author']  = 0;
            $data['created'] = current_time('mysql', true);

            $result = $wpdb->insert($table, $data);
            if ($result === false) {
                $skipped++;
                continue;
            }

            $inserted++;
        }

        $this->log->add(
            'info',
            'formtheme',
            0,
            0,
            "FormTheme installation summary: Inserted $inserted, Updated $updated, Skipped $skipped",
            'formtheme'
        );
    }

    /**
     * Recursively sanitize style properties while preserving array structure.
     *
     * @param array $styles
     * @return array
     */
    protected function sanitizeThemeStylesRecursive(array $styles)
    {
        $sanitized = array();

        foreach ($styles as $key => $value) {
            if (is_array($value)) {
                $sanitized[$key] = $this->sanitizeThemeStylesRecursive($value);
                continue;
            }

            if (is_string($value)) {
                $sanitized[$key] = \GriffinForms\Items\FormTheme::sanitizeCssString($value);
                continue;
            }

            $sanitized[$key] = $value;
        }

        return $sanitized;
    }

    /**
     * Ensure every canonical style block is available so DB schema stays aligned.
     *
     * @param array $styles
     * @param array $style_keys
     * @return array
     */
    protected function ensureThemeStyleKeys(array $styles, array $style_keys)
    {
        foreach ($style_keys as $key) {
            if (!array_key_exists($key, $styles) || !is_array($styles[$key])) {
                $styles[$key] = array();
            }
        }

        return $styles;
    }

    /**
     * Prepare serialized payload for every style column.
     *
     * @param array $styles
     * @param array $style_keys
     * @return array
     */
    protected function prepareThemeStylePayload(array $styles, array $style_keys)
    {
        $payload = array();

        foreach ($style_keys as $key) {
            $payload[$key] = maybe_serialize($styles[$key] ?? array());
        }

        return $payload;
    }

    protected function addDefaultFolders(): void
    {
        global $wpdb;

        $table = $this->config->getTable('folder');

        if ($this->tableHasRows($table)) {
            return;
        }

        $folders = [
            [
                'name'        => __('Contact Forms', 'griffinforms-form-builder'),
                'description' => __('Forms for general enquiries, get-in-touch requests, and support tickets.', 'griffinforms-form-builder'),
            ],
            [
                'name'        => __('Lead Generation', 'griffinforms-form-builder'),
                'description' => __('Capture prospect information, qualify leads, and grow your email list.', 'griffinforms-form-builder'),
            ],
            [
                'name'        => __('Surveys & Feedback', 'griffinforms-form-builder'),
                'description' => __('Collect customer opinions, NPS scores, and post-purchase reviews.', 'griffinforms-form-builder'),
            ],
            [
                'name'        => __('Event & Bookings', 'griffinforms-form-builder'),
                'description' => __('Registration, RSVPs, appointment requests, and workshop sign-ups.', 'griffinforms-form-builder'),
            ],
            [
                'name'        => __('Orders & Payments', 'griffinforms-form-builder'),
                'description' => __('Product orders, quote requests, and payment collection forms.', 'griffinforms-form-builder'),
            ],
        ];

        $icon_pool = range(1, 8);
        shuffle($icon_pool);
        $icons = array_slice($icon_pool, 0, count($folders));

        $now = current_time('mysql', true);
        $inserted = 0;

        foreach ($folders as $index => $folder) {
            $result = $wpdb->insert($table, [
                'name'        => sanitize_text_field($folder['name']),
                'description' => sanitize_text_field($folder['description']),
                'icon'        => $icons[$index],
                'author'      => 0,
                'created'     => $now,
                'last_editor' => 0,
                'last_edited' => $now,
            ]);

            if ($result !== false) {
                $inserted++;
            }
        }

        $this->log->add('info', 'folder', 0, 0, "Default folder seeding: Inserted $inserted", 'folder');
    }

    protected function tableHasRows(string $table): bool
    {
        global $wpdb;

        $table = trim($table);
        if ($table === '') {
            return false;
        }

        $value = $wpdb->get_var("SELECT 1 FROM `{$table}` LIMIT 1");
        return !empty($value);
    }

}
