<?php
/**
 * Migration: remove deprecated behavior fields and contact-card show_fields config.
 *
 * @package BoostBot
 * @since   1.0.0
 */

// Prevent direct access.
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class BoostBot_Migration_Remove_Deprecated_Behavior_Fields
 *
 * Idempotent cleanup migration:
 * - Drops ask_questions/suggest_products columns from bots and personalities tables.
 * - Removes deprecated show_fields key from contact_card widget configs.
 */
class BoostBot_Migration_Remove_Deprecated_Behavior_Fields {

    /**
     * Run migration.
     *
     * @return bool
     */
    public static function run() {
        global $wpdb;

        $success = true;

        $success = self::drop_column_if_exists( $wpdb->prefix . 'boostbot_bots', 'ask_questions' ) && $success;
        $success = self::drop_column_if_exists( $wpdb->prefix . 'boostbot_bots', 'suggest_products' ) && $success;
        $success = self::drop_column_if_exists( $wpdb->prefix . 'boostbot_personalities', 'ask_questions' ) && $success;
        $success = self::drop_column_if_exists( $wpdb->prefix . 'boostbot_personalities', 'suggest_products' ) && $success;

        $success = self::cleanup_contact_card_configs() && $success;

        return $success;
    }

    /**
     * Drop a column when it exists.
     *
     * @param string $table_name Table name.
     * @param string $column_name Column name.
     * @return bool
     */
    private static function drop_column_if_exists( string $table_name, string $column_name ): bool {
        global $wpdb;

        $safe_table  = self::sanitize_identifier( $table_name );
        $safe_column = self::sanitize_identifier( $column_name );

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table identifier sanitized via sanitize_identifier(); values bind via prepare().
        $exists = $wpdb->get_results(
            $wpdb->prepare(
                "SHOW COLUMNS FROM `{$safe_table}` LIKE %s",
                $safe_column
            )
        );
        if ( empty( $exists ) ) {
            return true;
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- DDL cannot use placeholders for identifiers; $table is sanitized, definitions are literals.
        $result = $wpdb->query( "ALTER TABLE `{$safe_table}` DROP COLUMN `{$safe_column}`" );

        if ( false === $result ) {
            if ( class_exists( 'BoostBot_Logger' ) ) {
                BoostBot_Logger::error(
                    'Migration failed while dropping deprecated column',
                    array(
                        'table'  => $table_name,
                        'column' => $column_name,
                        'error'  => $wpdb->last_error,
                    )
                );
            }
            return false;
        }

        if ( class_exists( 'BoostBot_Logger' ) ) {
            BoostBot_Logger::info(
                'Migration dropped deprecated column',
                array(
                    'table'  => $table_name,
                    'column' => $column_name,
                )
            );
        }

        return true;
    }

    /**
     * Remove deprecated show_fields from contact_card widget config.
     *
     * @return bool
     */
    private static function cleanup_contact_card_configs(): bool {
        global $wpdb;

        $widgets_table = self::sanitize_identifier( $wpdb->prefix . 'boostbot_widgets' );

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table identifier sanitized via sanitize_identifier(); values bind via prepare().
        $widgets = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT id, config FROM `{$widgets_table}` WHERE type = %s",
                'contact_card'
            )
        );

        if ( empty( $widgets ) ) {
            return true;
        }

        $all_ok = true;

        foreach ( $widgets as $widget ) {
            $config_raw = $widget->config ?? '';
            if ( empty( $config_raw ) ) {
                continue;
            }

            $decoded = json_decode( $config_raw, true );
            if ( ! is_array( $decoded ) ) {
                continue;
            }

            $changed = false;

            if ( isset( $decoded['show_fields'] ) ) {
                unset( $decoded['show_fields'] );
                $changed = true;
            }

            if ( isset( $decoded['settings'] ) && is_array( $decoded['settings'] ) && isset( $decoded['settings']['show_fields'] ) ) {
                unset( $decoded['settings']['show_fields'] );
                $changed = true;
            }

            if ( ! $changed ) {
                continue;
            }

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table identifier sanitized via sanitize_identifier(); values bind via prepare().
            $updated = $wpdb->update(
                $widgets_table,
                array( 'config' => wp_json_encode( $decoded ) ),
                array( 'id' => (int) $widget->id ),
                array( '%s' ),
                array( '%d' )
            );

            if ( false === $updated ) {
                $all_ok = false;
                if ( class_exists( 'BoostBot_Logger' ) ) {
                    BoostBot_Logger::error(
                        'Migration failed while cleaning contact_card config',
                        array(
                            'widget_id' => (int) $widget->id,
                            'error'     => $wpdb->last_error,
                        )
                    );
                }
            }
        }

        return $all_ok;
    }

    /**
     * Restrict a SQL identifier to [A-Za-z0-9_] characters.
     *
     * @param string $identifier Raw identifier.
     * @return string Identifier with disallowed characters removed.
     */
    private static function sanitize_identifier( $identifier ) {
        return preg_replace( '/[^A-Za-z0-9_]/', '', (string) $identifier );
    }
}

