<?php
/**
 * Freemius-aware uninstall cleanup for Noesia Smart Waiter.
 *
 * Preserve-by-default policy:
 * - Deleting the plugin keeps Noesia data unless the administrator explicitly
 *   enabled the full-wipe option inside plugin settings before uninstall.
 *
 * @package Noesia_Smart_Waiter
 */

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

/**
 * Decide whether uninstall should perform a destructive full wipe.
 *
 * @return bool
 */
function noesia_swa_uninstall_should_wipe() {
    $options = get_option( 'noesia_swa_options', array() );

    if ( ! is_array( $options ) ) {
        return false;
    }

    $value = isset( $options['delete_all_data_on_uninstall'] ) ? sanitize_key( (string) $options['delete_all_data_on_uninstall'] ) : 'no';

    return in_array( $value, array( 'yes', '1', 'true', 'on' ), true );
}


/**
 * Get an initialized filesystem instance when available.
 *
 * @return WP_Filesystem_Base|null
 */
function noesia_swa_uninstall_get_filesystem() {
    global $wp_filesystem;

    if ( $wp_filesystem instanceof WP_Filesystem_Base ) {
        return $wp_filesystem;
    }

    if ( ! function_exists( 'WP_Filesystem' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }

    if ( function_exists( 'WP_Filesystem' ) ) {
        WP_Filesystem();
    }

    return ( $wp_filesystem instanceof WP_Filesystem_Base ) ? $wp_filesystem : null;
}

/**
 * Delete a single file using WordPress filesystem helpers.
 *
 * @param string $file_path Absolute file path.
 * @return void
 */
function noesia_swa_uninstall_delete_file( $file_path ) {
    $file_path = is_string( $file_path ) ? trim( $file_path ) : '';

    if ( '' === $file_path ) {
        return;
    }

    if ( ! function_exists( 'wp_delete_file' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }

    if ( function_exists( 'wp_delete_file' ) ) {
        wp_delete_file( $file_path );
    }
}

/**
 * Normalize and validate a plugin table name for uninstall cleanup.
 *
 * @param string $table_name Raw table name.
 * @param wpdb   $wpdb       WordPress database object.
 * @return string
 */
function noesia_swa_uninstall_normalize_table_name( $table_name, $wpdb ) {
    $table_name = is_string( $table_name ) ? trim( $table_name ) : '';

    if ( '' === $table_name || ! preg_match( '/^[A-Za-z0-9_]+$/', $table_name ) ) {
        return '';
    }

    $allowed_prefixes = array(
        $wpdb->prefix . 'noesia_swa_',
        $wpdb->prefix . 'noesia_',
    );

    foreach ( $allowed_prefixes as $allowed_prefix ) {
        if ( 0 === strpos( $table_name, $allowed_prefix ) ) {
            return $table_name;
        }
    }

    return '';
}

/**
 * Delete a directory or file path using WordPress filesystem helpers.
 *
 * @param string $dir Absolute directory path.
 * @return void
 */
function noesia_swa_uninstall_delete_dir( $dir ) {
    $dir = is_string( $dir ) ? trim( $dir ) : '';

    if ( '' === $dir || ! file_exists( $dir ) ) {
        return;
    }

    $filesystem = noesia_swa_uninstall_get_filesystem();

    if ( $filesystem instanceof WP_Filesystem_Base ) {
        if ( $filesystem->exists( $dir ) ) {
            $filesystem->delete( $dir, true, is_dir( $dir ) ? 'd' : 'f' );
        }

        return;
    }

    if ( is_file( $dir ) || is_link( $dir ) ) {
        noesia_swa_uninstall_delete_file( $dir );
    }
}

/**
 * Delete attachment posts by ID.
 *
 * @param array<int|string> $attachment_ids Attachment IDs.
 * @return void
 */
function noesia_swa_uninstall_delete_attachments( $attachment_ids ) {
    if ( ! is_array( $attachment_ids ) || empty( $attachment_ids ) ) {
        return;
    }

    $attachment_ids = array_values( array_unique( array_filter( array_map( 'absint', $attachment_ids ) ) ) );

    foreach ( $attachment_ids as $attachment_id ) {
        if ( $attachment_id > 0 ) {
            wp_delete_attachment( $attachment_id, true );
        }
    }
}

/**
 * Collect attachment IDs stored as post meta values.
 *
 * @param wpdb  $wpdb      WordPress database object.
 * @param array $meta_keys Meta keys that store attachment IDs.
 * @return array<int>
 */
function noesia_swa_uninstall_collect_attachment_ids_from_postmeta_values( $wpdb, $meta_keys ) {
    if ( ! is_array( $meta_keys ) || empty( $meta_keys ) ) {
        return array();
    }

    $attachment_ids = array();

    foreach ( $meta_keys as $meta_key ) {
        $meta_key = is_string( $meta_key ) ? trim( $meta_key ) : '';

        if ( '' === $meta_key ) {
            continue;
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $found_ids = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s",
                $meta_key
            )
        );

        if ( is_array( $found_ids ) ) {
            $attachment_ids = array_merge( $attachment_ids, $found_ids );
        }
    }

    return array_values( array_unique( array_filter( array_map( 'absint', $attachment_ids ) ) ) );
}

/**
 * Collect attachment posts marked with specific attachment flags.
 *
 * @param array $meta_keys Meta keys stored on attachment posts.
 * @return array<int>
 */
function noesia_swa_uninstall_collect_attachment_ids_from_attachment_flags( $meta_keys ) {
    if ( ! is_array( $meta_keys ) || empty( $meta_keys ) ) {
        return array();
    }

    $meta_query = array( 'relation' => 'OR' );

    foreach ( $meta_keys as $meta_key ) {
        $meta_key = is_string( $meta_key ) ? trim( $meta_key ) : '';

        if ( '' !== $meta_key ) {
            $meta_query[] = array(
                'key'     => $meta_key,
                'compare' => 'EXISTS',
            );
        }
    }

    if ( count( $meta_query ) < 2 ) {
        return array();
    }

    $attachment_ids = get_posts(
        array(
            'post_type'        => 'attachment',
            'post_status'      => 'any',
            'numberposts'      => -1,
            'fields'           => 'ids',
                        'meta_query'       => $meta_query, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
        )
    );

    return is_array( $attachment_ids ) ? array_values( array_unique( array_filter( array_map( 'absint', $attachment_ids ) ) ) ) : array();
}

/**
 * Collect attachment-like IDs from module tables that use attachment or photo columns.
 *
 * @param wpdb  $wpdb   WordPress database object.
 * @param array $tables Table names.
 * @return array<int>
 */
function noesia_swa_uninstall_collect_attachment_ids_from_tables( $wpdb, $tables ) {
    if ( ! is_array( $tables ) || empty( $tables ) ) {
        return array();
    }

    $attachment_ids    = array();
    $candidate_columns = array( 'attachment_id', 'photo_id' );

    foreach ( $tables as $table_name ) {
        $table_name = noesia_swa_uninstall_normalize_table_name( $table_name, $wpdb );

        if ( '' === $table_name ) {
            continue;
        }

        foreach ( $candidate_columns as $column_name ) {
            $column_name = in_array( $column_name, $candidate_columns, true ) ? $column_name : '';

            if ( '' === $column_name ) {
                continue;
            }

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $column = $wpdb->get_var( $wpdb->prepare( 'SHOW COLUMNS FROM %i LIKE %s', $table_name, $column_name ) );

            if ( empty( $column ) ) {
                continue;
            }

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $found_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT %i FROM %i WHERE %i > 0', $column_name, $table_name, $column_name ) );

            if ( is_array( $found_ids ) ) {
                $attachment_ids = array_merge( $attachment_ids, $found_ids );
            }
        }
    }

    return array_values( array_unique( array_filter( array_map( 'absint', $attachment_ids ) ) ) );
}

/**
 * Delete uploaded files referenced only by stored upload URLs.
 *
 * @param wpdb   $wpdb      WordPress database object.
 * @param string $baseurl   Upload base URL.
 * @param string $basedir   Upload base directory.
 * @param array  $meta_keys Post meta keys containing upload URLs.
 * @return void
 */
function noesia_swa_uninstall_delete_upload_files_from_meta_urls( $wpdb, $baseurl, $basedir, $meta_keys ) {
    if ( '' === $baseurl || '' === $basedir || ! is_array( $meta_keys ) || empty( $meta_keys ) ) {
        return;
    }

    foreach ( $meta_keys as $meta_key ) {
        $meta_key = is_string( $meta_key ) ? trim( $meta_key ) : '';

        if ( '' === $meta_key ) {
            continue;
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $urls = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s",
                $meta_key
            )
        );

        if ( ! is_array( $urls ) ) {
            continue;
        }

        foreach ( $urls as $url ) {
            $url = is_string( $url ) ? trim( $url ) : '';

            if ( '' === $url || 0 !== strpos( $url, $baseurl ) ) {
                continue;
            }

            $relative_path = ltrim( substr( $url, strlen( $baseurl ) ), '/' );
            $file_path     = wp_normalize_path( trailingslashit( $basedir ) . $relative_path );

            if ( '' === $relative_path || ! file_exists( $file_path ) || ! is_file( $file_path ) ) {
                continue;
            }

            noesia_swa_uninstall_delete_file( $file_path );
        }
    }
}

/**
 * Run after Freemius reports the uninstall event.
 *
 * @return void
 */
function noesia_swa_freemius_after_uninstall() {
    if ( ! noesia_swa_uninstall_should_wipe() ) {
        return;
    }

    global $wpdb;

    $noesia_swa_option_prefixes = array(
        'noesia_swa_',
        'ns_marketing_',
    );
    $noesia_swa_known_options = array(
        'noesia_swa_options',
        'noesia_swa_version',
        'noesia_swa_db_version',
        'noesia_user_templates',
    );
    $noesia_swa_known_cron_hooks = array( 'noesia_swa_daily_cleanup' );
    $noesia_swa_post_type_prefixes = array( 'noesia_' );
    $noesia_swa_transient_prefixes = array(
        'noesia_swa_',
        'ns_marketing_',
    );

    $noesia_swa_option_names = $noesia_swa_known_options;
    $noesia_swa_alloptions   = wp_load_alloptions();

    if ( is_array( $noesia_swa_alloptions ) ) {
        foreach ( array_keys( $noesia_swa_alloptions ) as $noesia_swa_option_name ) {
            foreach ( $noesia_swa_option_prefixes as $noesia_swa_option_prefix ) {
                if ( 0 === strpos( (string) $noesia_swa_option_name, (string) $noesia_swa_option_prefix ) ) {
                    $noesia_swa_option_names[] = (string) $noesia_swa_option_name;
                    break;
                }
            }
        }
    }

    foreach ( $noesia_swa_option_prefixes as $noesia_swa_option_prefix ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $noesia_swa_db_option_names = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
                $wpdb->esc_like( $noesia_swa_option_prefix ) . '%'
            )
        );

        if ( is_array( $noesia_swa_db_option_names ) ) {
            $noesia_swa_option_names = array_merge( $noesia_swa_option_names, $noesia_swa_db_option_names );
        }
    }

    $noesia_swa_option_names = array_unique( array_filter( array_map( 'sanitize_key', $noesia_swa_option_names ) ) );

    foreach ( $noesia_swa_option_names as $noesia_swa_option_name ) {
        delete_option( $noesia_swa_option_name );
        delete_site_option( $noesia_swa_option_name );
    }

    foreach ( $noesia_swa_known_cron_hooks as $noesia_swa_hook_name ) {
        if ( function_exists( 'wp_clear_scheduled_hook' ) ) {
            wp_clear_scheduled_hook( $noesia_swa_hook_name );
        }
    }

    $noesia_swa_crons = get_option( 'cron', array() );

    if ( is_array( $noesia_swa_crons ) && function_exists( 'wp_clear_scheduled_hook' ) ) {
        foreach ( $noesia_swa_crons as $noesia_swa_timestamp => $noesia_swa_cron_hooks ) {
            if ( 'version' === $noesia_swa_timestamp || ! is_array( $noesia_swa_cron_hooks ) ) {
                continue;
            }

            foreach ( array_keys( $noesia_swa_cron_hooks ) as $noesia_swa_hook_name ) {
                if ( 0 === strpos( (string) $noesia_swa_hook_name, 'noesia_swa_' ) ) {
                    wp_clear_scheduled_hook( $noesia_swa_hook_name );
                }
            }
        }
    }

    $noesia_swa_attachment_ids = array();
    $noesia_swa_attachment_ids = array_merge(
        $noesia_swa_attachment_ids,
        noesia_swa_uninstall_collect_attachment_ids_from_postmeta_values(
            $wpdb,
            array(
                '_noesia_swa_pocket_attachment_id',
                '_safelog_photo_id',
            )
        )
    );
    $noesia_swa_attachment_ids = array_merge(
        $noesia_swa_attachment_ids,
        noesia_swa_uninstall_collect_attachment_ids_from_attachment_flags(
            array(
                '_noesia_swa_smart_pocket_attachment',
                '_noesia_swa_crm_lite_file',
            )
        )
    );

    $table_like_patterns = array(
        $wpdb->prefix . 'noesia_swa_%',
    );
    $noesia_swa_tables = array();

    foreach ( $table_like_patterns as $table_like ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $tables = $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_like ) );

        if ( is_array( $tables ) ) {
            $noesia_swa_tables = array_merge( $noesia_swa_tables, $tables );
        }
    }

    $noesia_swa_tables         = array_values( array_unique( array_filter( array_map( 'strval', $noesia_swa_tables ) ) ) );
    $noesia_swa_attachment_ids = array_merge( $noesia_swa_attachment_ids, noesia_swa_uninstall_collect_attachment_ids_from_tables( $wpdb, $noesia_swa_tables ) );
    $noesia_swa_attachment_ids = array_values( array_unique( array_filter( array_map( 'absint', $noesia_swa_attachment_ids ) ) ) );

    $noesia_swa_post_types = array();

    foreach ( $noesia_swa_post_type_prefixes as $noesia_swa_post_type_prefix ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $noesia_swa_found_post_types = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT post_type FROM {$wpdb->posts} WHERE post_type LIKE %s",
                $wpdb->esc_like( $noesia_swa_post_type_prefix ) . '%'
            )
        );

        if ( is_array( $noesia_swa_found_post_types ) ) {
            $noesia_swa_post_types = array_merge( $noesia_swa_post_types, $noesia_swa_found_post_types );
        }
    }

    $noesia_swa_post_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $noesia_swa_post_types ) ) ) );

    if ( ! empty( $noesia_swa_post_types ) ) {
        $noesia_swa_post_ids = get_posts(
            array(
                'post_type'   => $noesia_swa_post_types,
                'post_status' => 'any',
                'numberposts' => -1,
                'fields'      => 'ids',
                'orderby'     => 'ID',
                'order'       => 'ASC',
            )
        );

        if ( is_array( $noesia_swa_post_ids ) ) {
            foreach ( $noesia_swa_post_ids as $noesia_swa_post_id ) {
                wp_delete_post( (int) $noesia_swa_post_id, true );
            }
        }
    }

    $upload = wp_get_upload_dir();

    if ( is_array( $upload ) && ! empty( $upload['basedir'] ) ) {
        $roots = array(
            trailingslashit( $upload['basedir'] ) . 'noesia-smart-waiter',
            trailingslashit( $upload['basedir'] ) . 'noesia',
            trailingslashit( $upload['basedir'] ) . 'noesia-swa-screen-recorder',
        );

        $attachment_meta_prefixes = array(
            trailingslashit( 'noesia-smart-waiter' ),
            trailingslashit( 'noesia' ),
            trailingslashit( 'noesia-swa-screen-recorder' ),
        );

        foreach ( $attachment_meta_prefixes as $meta_prefix ) {
            $attachment_ids = get_posts(
                array(
                    'post_type'        => 'attachment',
                    'post_status'      => 'any',
                    'numberposts'      => -1,
                    'fields'           => 'ids',
                                        'meta_query'       => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                        array(
                            'key'     => '_wp_attached_file',
                            'value'   => $meta_prefix,
                            'compare' => 'LIKE',
                        ),
                    ),
                )
            );

            if ( is_array( $attachment_ids ) ) {
                $noesia_swa_attachment_ids = array_merge( $noesia_swa_attachment_ids, $attachment_ids );
            }
        }

        noesia_swa_uninstall_delete_upload_files_from_meta_urls(
            $wpdb,
            isset( $upload['baseurl'] ) ? (string) $upload['baseurl'] : '',
            isset( $upload['basedir'] ) ? (string) $upload['basedir'] : '',
            array( 'noesia_receipt_url' )
        );

        noesia_swa_uninstall_delete_attachments( $noesia_swa_attachment_ids );

        foreach ( $roots as $root ) {
            noesia_swa_uninstall_delete_dir( $root );
        }
    }

    foreach ( $noesia_swa_transient_prefixes as $noesia_swa_transient_prefix ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
                '_transient_' . $wpdb->esc_like( $noesia_swa_transient_prefix ) . '%',
                '_transient_timeout_' . $wpdb->esc_like( $noesia_swa_transient_prefix ) . '%'
            )
        );
    }

    $noesia_swa_drop_tables = array_merge(
        $noesia_swa_tables,
        array(
            $wpdb->prefix . 'noesia_business_log',
        )
    );
    $noesia_swa_drop_tables = array_values( array_unique( array_filter( array_map( 'strval', $noesia_swa_drop_tables ) ) ) );

    foreach ( $noesia_swa_drop_tables as $table_name ) {
        $table_name = noesia_swa_uninstall_normalize_table_name( $table_name, $wpdb );

        if ( '' === $table_name ) {
            continue;
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
        $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table_name ) );
    }
}
