<?php
/**
 * Data Cleaner Class
 *
 * Handles deletion of all plugin data based on registry and scanner results
 *
 * @package Switchboard
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

class Switchboard_Data_Cleaner {

    /**
     * Clear all plugin data
     *
     * @param array $data_map Optional pre-scanned data map
     * @param string $mode Cleanup mode: 'full' (DROP tables) or 'data_only' (TRUNCATE tables)
     * @return array Result with counts
     */
    public function clear_all_data($data_map = null, $mode = 'full') {
        global $wpdb;

        // Scan if not provided
        if ($data_map === null) {
            $scanner = new Switchboard_Data_Scanner();
            $data_map = $scanner->scan_all_data();
        }

        $result = [
            'options_deleted' => 0,
            'tables_dropped' => 0,
            'tables_truncated' => 0,
            'post_meta_deleted' => 0,
            'user_meta_deleted' => 0,
            'errors' => [],
            'mode' => $mode,
        ];

        try {
            // 1. Delete options
            foreach ($data_map['options'] as $option_name => $info) {
                if (delete_option($option_name)) {
                    $result['options_deleted']++;
                } else {
                    // Try direct delete for transients
                    $deleted = $wpdb->delete($wpdb->options, ['option_name' => $option_name]); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    if ($deleted) {
                        $result['options_deleted']++;
                    }
                }
            }

            // 2. Handle tables based on mode
            foreach ($data_map['tables'] as $table_name => $info) {
                $full_name = $info['full_name'];

                // Defense-in-depth: Escape table name even though it comes from trusted source
                $escaped_table_name = esc_sql($full_name);

                if ($mode === 'data_only') {
                    // TRUNCATE: Remove data but keep schema
                    // Better for inactive modules that might be re-enabled
                    $truncated = $wpdb->query("TRUNCATE TABLE {$escaped_table_name}"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    if ($truncated !== false) {
                        $result['tables_truncated']++;
                    } else {
                        // Fallback to DELETE if TRUNCATE fails
                        $wpdb->query("DELETE FROM {$escaped_table_name}"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                        $result['tables_truncated']++;
                    }
                } else {
                    // DROP: Remove entire table including schema
                    // For complete cleanup when uninstalling
                    $dropped = $wpdb->query("DROP TABLE IF EXISTS {$escaped_table_name}"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Intentional cleanup of plugin tables
                    if ($dropped !== false) {
                        $result['tables_dropped']++;
                    } else {
                        $result['errors'][] = "Failed to drop table: {$full_name}";
                    }
                }
            }

            // 3. Delete post meta
            foreach ($data_map['post_meta'] as $meta_key => $info) {
                $deleted = $wpdb->delete($wpdb->postmeta, ['meta_key' => $meta_key]); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key
                if ($deleted) {
                    $result['post_meta_deleted'] += $deleted;
                }
            }

            // 4. Delete user meta
            foreach ($data_map['user_meta'] as $meta_key => $info) {
                $deleted = $wpdb->delete($wpdb->usermeta, ['meta_key' => $meta_key]); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key
                if ($deleted) {
                    $result['user_meta_deleted'] += $deleted;
                }
            }

            // 5. Log the action
            $this->log_cleanup_action($result, $data_map);

        } catch (Exception $e) {
            $result['errors'][] = $e->getMessage();
        }

        return $result;
    }

    /**
     * Clear only options
     *
     * @param array $option_names Option names to delete
     * @return int Number deleted
     */
    public function clear_options($option_names) {
        $deleted = 0;

        foreach ($option_names as $option_name) {
            if (delete_option($option_name)) {
                $deleted++;
            }
        }

        return $deleted;
    }

    /**
     * Drop tables
     *
     * @param array $table_names Table names (without prefix)
     * @return int Number dropped
     */
    public function drop_tables($table_names) {
        global $wpdb;
        $dropped = 0;

        foreach ($table_names as $table_name) {
            $full_name = $wpdb->prefix . $table_name;
            // Defense-in-depth: Escape table name
            $escaped_table_name = esc_sql($full_name);
            $result = $wpdb->query("DROP TABLE IF EXISTS {$escaped_table_name}"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Intentional cleanup of plugin tables
            if ($result !== false) {
                $dropped++;
            }
        }

        return $dropped;
    }

    /**
     * Log cleanup action for audit trail
     *
     * @param array $result Cleanup result
     * @param array $data_map Data that was deleted
     */
    private function log_cleanup_action($result, $data_map) {
        $log_entry = [
            'timestamp' => current_time('mysql'),
            'user_id' => get_current_user_id(),
            'user_login' => wp_get_current_user()->user_login,
            'result' => $result,
            'summary' => $data_map['summary'],
        ];

        // Store in a special option (won't be deleted since it's created after cleanup)
        $cleanup_history = get_option('switchboard_cleanup_history', []);
        array_unshift($cleanup_history, $log_entry);

        // Keep only last 10 entries
        $cleanup_history = array_slice($cleanup_history, 0, 10);

        update_option('switchboard_cleanup_history', $cleanup_history, false);
    }

    /**
     * Get cleanup history
     *
     * @return array Cleanup history entries
     */
    public function get_cleanup_history() {
        return get_option('switchboard_cleanup_history', []);
    }
}
