<?php
namespace ARCHM\Helpers;

/**
 * Wc_Storage_Handler Trait
 * Includes helper functions for the plugin
 *
 * @since 1.3.8
 * @package ArchiveMaster
 */

trait WcStorageHandler {


    /**
     * Check if HPOS is enabled
     *
     * @return bool
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.boolFound
    private function is_hpos_enabled(): bool {
        return class_exists('\Automattic\WooCommerce\Utilities\OrderUtil') &&
        \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
    }

    /**
     * Get the appropriate query for order counting based on storage method
     *
     * @param string $scheduleDate
     * @param array $batch_ids
     * @return string
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.stringFound, PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.stringFound ,
    private function get_count_query( string $schedule_date, array $batch_ids = [] ): string {
        $ids_in_clause = ! empty($batch_ids) ? implode(',', array_map('intval', $batch_ids)) : '';

        // Get archive statuses from wp_options
        $archive_statuses = get_option('archm_archive_statuses', []);

        if ( ! empty($archive_statuses) ) {
            $sanitized_statuses = array_map(function ( $status ) {
                return $this->wpdb->prepare('%s', $status);
            }, $archive_statuses);
        }

        if ( $this->is_hpos_enabled() ) {
            // Logger::logMessage('HPOS enabled - Getting count for schedule');
            $query = "
                SELECT COUNT(*) AS post_count
                FROM %i
                WHERE type = 'shop_order'
                AND date_created_gmt <= %s
                AND status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            if ( ! empty($ids_in_clause) ) {
                $query .= " AND ID NOT IN ({$ids_in_clause})";
            }

            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'wc_orders', $schedule_date); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        } else {
            // Logger::logMessage('HPOS disabled - Getting count from posts table for schedule');
            $query = "
                SELECT COUNT(*) AS post_count
                FROM %i p
                WHERE p.post_type = 'shop_order'
                AND p.post_date_gmt <= %s
                AND p.post_status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND p.post_status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            if ( ! empty($ids_in_clause) ) {
                $query .= " AND p.ID NOT IN ({$ids_in_clause})";
            }

            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'posts', $schedule_date); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        }
    }

    /**
     * Get the appropriate query for total order counting based on storage method
     *
     * @return string
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.stringFound, PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.stringFound
    private function get_total_count_query(): string {
        if ( $this->is_hpos_enabled() ) {
            // Logger::logMessage('HPOS enabled - Getting total count');
            $query = "
                SELECT COUNT(*) AS post_count
                FROM %i
                WHERE type = 'shop_order'
                AND status != 'trash'
            ";

            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'wc_orders'); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        } else {
            // Logger::logMessage('HPOS disabled - Getting total count from posts table');
            $query = "
                SELECT COUNT(*) AS post_count
                FROM %i p
                WHERE p.post_type = 'shop_order'
                AND p.post_status != 'trash'
            ";

            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'posts'); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        }
    }

    /**
     * Get order IDs for counting (without limit, for filtering purposes)
     *
     * @param string $schedule_date
     * @return array Array of order IDs
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.stringFound, PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.arrayFound
    private function get_order_ids_for_count( string $schedule_date ): array {
        // Get archive statuses from wp_options
        $archive_statuses = get_option('archm_archive_statuses', []);

        if ( ! empty($archive_statuses) ) {
            $sanitized_statuses = array_map(function ( $status ) {
                return $this->wpdb->prepare('%s', $status);
            }, $archive_statuses);
        }

        if ( $this->is_hpos_enabled() ) {
            $query = "
                SELECT ID
                FROM %i
                WHERE type = 'shop_order'
                AND date_created_gmt <= %s
                AND status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            $query = $this->wpdb->prepare($query, $this->wpdb->prefix . 'wc_orders', $schedule_date); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        } else {
            $query = "
                SELECT p.ID
                FROM %i p
                WHERE p.post_type = 'shop_order'
                AND p.post_date_gmt <= %s
                AND p.post_status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND p.post_status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            $query = $this->wpdb->prepare($query, $this->wpdb->prefix . 'posts', $schedule_date); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        }

        $results = $this->wpdb->get_col($query); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        return $results ? array_map('intval', $results) : [];
    }

    /**
     * Get the appropriate query for fetching orders based on storage method
     *
     * @param string $scheduleDate
     * @param array $ids
     * @param array $batch_ids
     * @return string
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.stringFound, PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.stringFound
    private function get_orders_query( string $schedule_date, array $ids, array $batch_ids ): string {
        $ids_in_clause = ! empty($ids) ? implode(',', array_map('intval', $ids)) : implode(',', array_map('intval', $batch_ids));

        // Get archive statuses from wp_options
        $archive_statuses = get_option('archm_archive_statuses', []);

        if ( ! empty($archive_statuses) ) {
            $sanitized_statuses = array_map(function ( $status ) {
                return $this->wpdb->prepare('%s', $status);
            }, $archive_statuses);
        }

        if ( $this->is_hpos_enabled() ) {
            // Logger::logMessage('HPOS enabled - Fetching orders');
            $query = "
                SELECT ID
                FROM %i
                WHERE type = 'shop_order'
                AND date_created_gmt <= %s
                AND status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            if ( ! empty($ids_in_clause) ) {
                $query .= " AND ID NOT IN ({$ids_in_clause})";
            }

            // Apply filter to exclude specific order types
            $exclude_conditions = apply_filters('archm_exclude_order_types_from_query', '', $schedule_date);
            if ( ! empty($exclude_conditions) ) {
                $query .= " AND ({$exclude_conditions})";
            }

            $query .= ' ORDER BY date_created_gmt ASC LIMIT %d';
            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'wc_orders', $schedule_date, ARCHM_CHUNK_SIZE); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        } else {
            // Logger::logMessage('HPOS disabled - Fetching orders from posts table');
            $query = "
                SELECT p.ID
                FROM %i p
                WHERE p.post_type = 'shop_order'
                AND p.post_date_gmt <= %s
                AND p.post_status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND p.post_status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            if ( ! empty($ids_in_clause) ) {
                $query .= " AND p.ID NOT IN ({$ids_in_clause})";
            }

            // Apply filter to exclude specific order types
            $exclude_conditions = apply_filters('archm_exclude_order_types_from_query', '', $schedule_date);
            if ( ! empty($exclude_conditions) ) {
                $query .= " AND ({$exclude_conditions})";
            }

            $query .= ' ORDER BY p.post_date_gmt ASC LIMIT %d';
            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'posts', $schedule_date, ARCHM_CHUNK_SIZE); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        }
    }

    /**
     * Get the appropriate query for fetching orders with custom batch size
     *
     * @param string $scheduleDate
     * @param array $ids
     * @param array $batch_ids
     * @param int $limit Custom batch size limit
     * @return string
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.stringFound, PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.intFound, PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.stringFound
    private function get_orders_query_with_limit( string $schedule_date, array $ids, array $batch_ids, int $limit ): string {
        $ids_in_clause = ! empty($ids) ? implode(',', array_map('intval', $ids)) : implode(',', array_map('intval', $batch_ids));

        // Get archive statuses from wp_options
        $archive_statuses = get_option('archm_archive_statuses', []);

        if ( ! empty($archive_statuses) ) {
            $sanitized_statuses = array_map(function ( $status ) {
                return $this->wpdb->prepare('%s', $status);
            }, $archive_statuses);
        }

        if ( $this->is_hpos_enabled() ) {
            $query = "
                SELECT ID
                FROM %i
                WHERE type = 'shop_order'
                AND date_created_gmt <= %s
                AND status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            if ( ! empty($ids_in_clause) ) {
                $query .= " AND ID NOT IN ({$ids_in_clause})";
            }

            // Apply filter to exclude specific order types
            $exclude_conditions = apply_filters('archm_exclude_order_types_from_query', '', $schedule_date);
            if ( ! empty($exclude_conditions) ) {
                $query .= " AND ({$exclude_conditions})";
            }

            $query .= ' ORDER BY date_created_gmt ASC LIMIT %d';
            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'wc_orders', $schedule_date, $limit); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        } else {
            $query = "
                SELECT p.ID
                FROM %i p
                WHERE p.post_type = 'shop_order'
                AND p.post_date_gmt <= %s
                AND p.post_status != 'trash'
            ";

            if ( ! empty($archive_statuses) ) {
                $query .= ' AND p.post_status IN (' . implode(',', $sanitized_statuses) . ')';
            }

            if ( ! empty($ids_in_clause) ) {
                $query .= " AND p.ID NOT IN ({$ids_in_clause})";
            }

            // Apply filter to exclude specific order types
            $exclude_conditions = apply_filters('archm_exclude_order_types_from_query', '', $schedule_date);
            if ( ! empty($exclude_conditions) ) {
                $query .= " AND ({$exclude_conditions})";
            }

            $query .= ' ORDER BY p.post_date_gmt ASC LIMIT %d';
            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'posts', $schedule_date, $limit); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        }
    }

    /**
     * Get the duplicate order berfore unarchiving order
     *
     * @param array $ids
     */
    private function count_total_bulicate_order( array $ids = [] ) {
        // Logger::logMessage($ids);

        $dubpicate_ids = implode(',', array_map('intval', $ids));

        // Logger::logMessage($dubpicate_ids);

        if ( $this->is_hpos_enabled() ) {
            $query = "
                SELECT ID 
                FROM %i
                WHERE type = 'shop_order'
                AND ID IN ({$dubpicate_ids})
                AND status != 'trash'
            ";
            // Logger::logMessage($this->wpdb);
            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'wc_orders'); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        } else {
            $query = "
                SELECT ID
                FROM %i
                WHERE post_type = 'shop_order'
                AND ID IN ({$dubpicate_ids})
                AND post_status != 'trash'
            ";
            return $this->wpdb->prepare($query, $this->wpdb->prefix . 'posts'); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        }
    }
}
