<?php
/**
 * Bulk actions for invoice generation and export.
 *
 * Adds bulk actions to the WooCommerce orders list:
 * - Generate invoices for selected orders
 * - Export invoices as ZIP
 * - Retroactive generation for past orders without invoices
 *
 * @package FacturX_For_WooCommerce
 */

defined( 'ABSPATH' ) || exit;

class GOFACTOX_Bulk {

    public static function init(): void {
        // Bulk generation and ZIP export are Pro features.
        if ( ! GOFACTOX_License::is_pro() ) {
            return;
        }

        // HPOS bulk actions.
        add_filter( 'bulk_actions-woocommerce_page_wc-orders', [ __CLASS__, 'add_bulk_actions' ] );
        add_filter( 'handle_bulk_actions-woocommerce_page_wc-orders', [ __CLASS__, 'handle_bulk_actions' ], 10, 3 );

        // Legacy CPT bulk actions.
        add_filter( 'bulk_actions-edit-shop_order', [ __CLASS__, 'add_bulk_actions' ] );
        add_filter( 'handle_bulk_actions-edit-shop_order', [ __CLASS__, 'handle_bulk_actions' ], 10, 3 );

        // Admin notices for bulk action results.
        add_action( 'admin_notices', [ __CLASS__, 'show_bulk_notices' ] );

        // AJAX endpoint for retroactive generation.
        add_action( 'wp_ajax_gofactox_retroactive_generate', [ __CLASS__, 'ajax_retroactive_generate' ] );
    }

    /**
     * Add bulk actions to orders list dropdown.
     */
    public static function add_bulk_actions( array $actions ): array {
        $actions['gofactox_generate_invoices'] = __( 'Generate Factur-X Invoices', 'gofactox-e-invoicing-for-woocommerce' );
        $actions['gofactox_export_invoices']   = __( 'Export Invoices (ZIP)', 'gofactox-e-invoicing-for-woocommerce' );
        return $actions;
    }

    /**
     * Handle bulk actions.
     */
    public static function handle_bulk_actions( string $redirect_to, string $action, array $order_ids ): string {
        if ( $action === 'gofactox_generate_invoices' ) {
            $generated = 0;
            $skipped   = 0;

            foreach ( $order_ids as $order_id ) {
                $order = wc_get_order( $order_id );
                if ( ! $order ) {
                    continue;
                }

                // Skip if already has invoice.
                if ( $order->get_meta( '_gofactox_invoice_id' ) ) {
                    $skipped++;
                    continue;
                }

                $result = GOFACTOX_Order_Hooks::generate_invoice_for_order( $order );
                if ( $result ) {
                    $generated++;
                } else {
                    $skipped++;
                }
            }

            $redirect_to = add_query_arg( [
                'gofactox_generated' => $generated,
                'gofactox_skipped'   => $skipped,
            ], $redirect_to );
        }

        if ( $action === 'gofactox_export_invoices' ) {
            self::export_zip( $order_ids );
        }

        return $redirect_to;
    }

    /**
     * Show admin notices after bulk actions.
     */
    public static function show_bulk_notices(): void {
        if ( ! isset( $_GET['gofactox_generated'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            return;
        }

        $generated = (int) sanitize_text_field( wp_unslash( $_GET['gofactox_generated'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $skipped   = isset( $_GET['gofactox_skipped'] ) ? (int) sanitize_text_field( wp_unslash( $_GET['gofactox_skipped'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

        echo '<div class="notice notice-success is-dismissible"><p>';
        echo esc_html( sprintf(
            /* translators: 1: number of invoices generated, 2: number skipped */
            __( 'Factur-X: %1$d invoice(s) generated, %2$d skipped (already existed or failed).', 'gofactox-e-invoicing-for-woocommerce' ),
            $generated,
            $skipped
        ) );
        echo '</p></div>';
    }

    /**
     * Export selected orders' invoices as a ZIP file.
     */
    private static function export_zip( array $order_ids ): void {
        if ( ! class_exists( 'ZipArchive' ) ) {
            wp_die( esc_html__( 'ZIP extension is not available on this server.', 'gofactox-e-invoicing-for-woocommerce' ) );
        }

        $upload_dir = wp_upload_dir();
        $tmp_dir    = $upload_dir['basedir'] . '/wfx-invoices/tmp';
        wp_mkdir_p( $tmp_dir );

        $zip_path = $tmp_dir . '/invoices-' . current_time( 'Y-m-d-His' ) . '.zip';
        $zip      = new \ZipArchive();

        if ( $zip->open( $zip_path, \ZipArchive::CREATE ) !== true ) {
            wp_die( esc_html__( 'Could not create ZIP file.', 'gofactox-e-invoicing-for-woocommerce' ) );
        }

        $added = 0;
        foreach ( $order_ids as $order_id ) {
            $order = wc_get_order( $order_id );
            if ( ! $order ) {
                continue;
            }

            $invoice_id = $order->get_meta( '_gofactox_invoice_id' );
            if ( ! $invoice_id ) {
                // Generate if missing.
                GOFACTOX_Order_Hooks::generate_invoice_for_order( $order );
                $invoice_id = $order->get_meta( '_gofactox_invoice_id' );
            }

            if ( ! $invoice_id ) {
                continue;
            }

            $pdf_path = GOFACTOX_Invoice::get_pdf_path( (int) $invoice_id );
            if ( $pdf_path && file_exists( $pdf_path ) ) {
                $invoice_number = $order->get_meta( '_gofactox_invoice_number' );
                $zip->addFile( $pdf_path, sanitize_file_name( $invoice_number ) . '.pdf' );
                $added++;
            }
        }

        $zip->close();

        if ( $added === 0 ) {
            wp_delete_file( $zip_path );
            wp_die( esc_html__( 'No invoices to export.', 'gofactox-e-invoicing-for-woocommerce' ) );
        }

        // Serve the ZIP.
        header( 'Content-Type: application/zip' );
        header( 'Content-Disposition: attachment; filename="invoices-' . current_time( 'Y-m-d' ) . '.zip"' );
        header( 'Content-Length: ' . filesize( $zip_path ) );

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile -- Direct file serving for performance.
        readfile( $zip_path );
        wp_delete_file( $zip_path );
        exit;
    }

    /**
     * AJAX handler for retroactive generation.
     */
    public static function ajax_retroactive_generate(): void {
        check_ajax_referer( 'gofactox_retroactive_generate' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( __( 'Permission denied.', 'gofactox-e-invoicing-for-woocommerce' ) );
        }

        $batch_size = 20;
        $offset     = isset( $_POST['offset'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['offset'] ) ) : 0;

        // Find orders without invoices.
        $orders = wc_get_orders( [
            'limit'      => $batch_size,
            'offset'     => $offset,
            'status'     => [ 'completed', 'processing' ],
            'orderby'    => 'date',
            'order'      => 'ASC',
            'meta_query' => [
                [
                    'key'     => '_gofactox_invoice_id',
                    'compare' => 'NOT EXISTS',
                ],
            ],
        ] );

        $generated = 0;
        foreach ( $orders as $order ) {
            $result = GOFACTOX_Order_Hooks::generate_invoice_for_order( $order );
            if ( $result ) {
                $generated++;
            }
        }

        $has_more = count( $orders ) === $batch_size;

        wp_send_json_success( [
            'generated' => $generated,
            'has_more'  => $has_more,
            'offset'    => $offset + $batch_size,
        ] );
    }
}
