<?php
/**
 * BookiFlex
 *
 * @package   BookiFlex
 * @author    BookiFlex
 * @copyright Copyright (c) 2025 BookiFlex
 * @license   GPL-2.0-or-later
 *
 * @link      https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Plugin\Admin\Lifecycle;

use BookiFlex\Core\Admin\CPT\RatePlan;
use BookiFlex\Core\Admin\Lifecycle\AbstractUninstaller;
use BookiFlex\Plugin\Admin\CPT\AccommodationType;
use BookiFlex\Plugin\Admin\CPT\CancellationPolicy;
use BookiFlex\Plugin\Admin\CPT\PaymentType;

defined( 'ABSPATH' ) || exit;

/**
 * Unified Plugin Uninstaller
 *
 * Performs complete cleanup of all BookiFlex data using pattern-based deletion.
 * Integrates with Freemius SDK for proper uninstall tracking.
 */
class Uninstaller extends AbstractUninstaller
{
    /**
     * Register uninstall hook via Freemius
     *
     * Overrides parent to use Freemius after_uninstall action instead of
     * WordPress register_uninstall_hook(). This allows Freemius to track
     * uninstall events and collect user feedback before cleanup runs.
     *
     * @param \BookiFlex\Core\Contract\PluginInterface $plugin Plugin instance
     */
    public static function register(\BookiFlex\Core\Contract\PluginInterface $plugin): void
    {
        // Use Freemius after_uninstall hook instead of WordPress register_uninstall_hook()
        // This allows Freemius to send analytics and collect feedback before our cleanup
        $plugin->fs()->add_action('after_uninstall', [static::class, 'uninstallStatic']);
    }

    /**
     * Delete version-specific data
     *
     * For unified plugin, we don't have version-specific data.
     * All cleanup happens in deleteSharedData().
     */
    protected function deleteVersionData(): void
    {
        // Extension uninstallers may have version-specific data
        $this->callExtensionUninstallers('deleteVersionData');
    }

    /**
     * Delete all shared data
     *
     * Performs aggressive cleanup in correct order to avoid dependency issues:
     * 1. Extension uninstallers (may need to query data)
     * 2. CPT posts (before tables dropped)
     * 3. Scheduled tasks (before tables dropped)
     * 4. Database tables (after everything that uses them)
     * 5. Options & transients (safe after tables)
     * 6. Roles & capabilities (no dependencies)
     * 7. Clear cache (final step)
     */
    protected function deleteSharedData(): void
    {
        // STEP 1: Call extension uninstallers (may need database access)
        $this->callExtensionUninstallers('deleteSharedData');

        // STEP 2: Delete custom post types (before dropping tables)
        $this->deleteCustomPostTypes();

        // STEP 3: Delete scheduled tasks (before dropping tables)
        $this->deleteScheduledTasks();

        // STEP 4: Delete all database tables
        $this->deleteAllTables();

        // STEP 5: Delete all options and transients
        $this->deleteAllOptions();

        // STEP 6: Delete roles and capabilities
        $this->deleteRolesAndCapabilities();

        // STEP 7: Clear WordPress cache
        wp_cache_flush();
    }

    /**
     * Get list of extension uninstallers for Free edition
     *
     * @return array Array of UninstallerInterface instances
     */
    protected function getExtensionUninstallers(): array
    {
        return $this->instantiateUninstallers([
            [\BookiFlex\Extensions\Payment\Uninstaller::class],
            [\BookiFlex\Extensions\Cart\Uninstaller::class],
            [\BookiFlex\Extensions\Notification\Uninstaller::class],
            [\BookiFlex\Extensions\Onboarding\Uninstaller::class],
            [\BookiFlex\Extensions\SimpleQuota\Uninstaller::class],
            [\BookiFlex\Extensions\OfflinePayment\Uninstaller::class],
            [\BookiFlex\Extensions\StripePayment\Uninstaller::class, ['free']],
            [\BookiFlex\Extensions\Taxation\Uninstaller::class],
        ]);
    }

    /**
     * Delete custom post types and all posts
     *
     * WordPress automatically deletes post meta when posts are deleted.
     * Media files (attachments) are preserved - user may want to keep images.
     */
    private function deleteCustomPostTypes(): void
    {
        $postTypes = [
			AccommodationType::POST_TYPE,
	        RatePlan::POST_TYPE,
	        CancellationPolicy::POST_TYPE,
	        PaymentType::POST_TYPE,
        ];

        $posts = get_posts([
            'post_type' => $postTypes,
            'numberposts' => -1,
            'post_status' => 'any',
        ]);

        foreach ($posts as $post) {
            // Force delete (bypass trash)
            // Note: Post meta is automatically deleted by WordPress
            // Attached media files are NOT deleted (user may want to keep)
            wp_delete_post($post->ID, true);
        }
    }

    /**
     * Delete scheduled tasks from Action Scheduler
     *
     * Removes all BookiFlex scheduled actions without dropping
     * Action Scheduler tables (shared with other plugins).
     */
    private function deleteScheduledTasks(): void
    {
        global $wpdb;

        // Check if Action Scheduler table exists
        $table_exists = $wpdb->get_var(
            "SHOW TABLES LIKE '{$wpdb->prefix}actionscheduler_actions'"
        );

        if (!$table_exists) {
            return;
        }

        // Delete all BookiFlex scheduled actions
        $wpdb->query(
            "DELETE FROM {$wpdb->prefix}actionscheduler_actions
             WHERE hook LIKE 'bookiflex_%'"
        );

		// If WooCommerce (AS owner) is installed then do nothing otherwise remove action on 'shutdown'
	    if (!class_exists('WooCommerce')) {
		    if (class_exists(\ActionScheduler_QueueRunner::class)) {
			    \ActionScheduler_QueueRunner::instance()->unhook_dispatch_async_request();
		    }
	    }
    }

    /**
     * Delete ALL database tables matching our prefixes
     *
     * Uses pattern matching to find and drop all tables with
     * bookiflex_ or bflex_ prefix. This automatically handles
     * core tables and extension tables.
     */
    private function deleteAllTables(): void
    {
        global $wpdb;

        // Find all tables with our prefixes
        $tables = $wpdb->get_results(
            "SHOW TABLES LIKE 'bookiflex_%'",
            ARRAY_N
        );

        $bflex_tables = $wpdb->get_results(
            "SHOW TABLES LIKE 'bflex_%'",
            ARRAY_N
        );

        $all_tables = array_merge($tables, $bflex_tables);

        if (empty($all_tables)) {
            return;
        }

        // Drop all tables with foreign key check disabled
        $wpdb->query('SET FOREIGN_KEY_CHECKS = 0');

        foreach ($all_tables as $table) {
            $table_name = $table[0];
            $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`");
        }

        $wpdb->query('SET FOREIGN_KEY_CHECKS = 1');
    }

    /**
     * Delete ALL options and transients matching our prefixes
     *
     * Deletes all options starting with:
     * - bookiflex_* and _bookiflex_*
     * - bflex_* and _bflex_*
     * - _crb_* (Carbon Fields)
     * - _transient_bookiflex_* and _transient_bflex_*
     *
     * NOTE: Does NOT delete Freemius data (fs_*, _fs_*)
     * Freemius SDK handles its own cleanup.
     */
    private function deleteAllOptions(): void
    {
        global $wpdb;

        $patterns = [
            'bookiflex_%',
            '_bookiflex_%',
            'bflex_%',
            '_bflex_%',
//            '_crb_%',
            '_transient_bookiflex_%',
            '_transient_timeout_bookiflex_%',
            '_transient_bflex_%',
            '_transient_timeout_bflex_%',
        ];

        foreach ($patterns as $pattern) {
            $wpdb->query(
                $wpdb->prepare(
                    "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
                    $pattern
                )
            );
        }
    }

    /**
     * Delete WordPress roles and capabilities
     */
    private function deleteRolesAndCapabilities(): void
    {
        global $wp_roles;

        if (!isset($wp_roles)) {
            $wp_roles = new \WP_Roles();
        }

        // All capabilities to remove
        $capabilities = [
            'bookiflex_manage_reservations',
            'bookiflex_manage_configuration',
            'bookiflex_manage_customers',
            'bookiflex_manage_payments',
            'bookiflex_delete_configuration',
            'bookiflex_view_reports',
        ];

        // Remove from both administrator and hotel_manager roles
        foreach ($capabilities as $cap) {
            $wp_roles->remove_cap('administrator', $cap);
            $wp_roles->remove_cap('bookiflex_hotel_manager', $cap);
        }

        // Remove custom role
        remove_role('bookiflex_hotel_manager');
    }
}
