<?php

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

class AIEO_Fulfillment_Bulk {

    
    public static function raise_limits($seconds = 300) {
        @set_time_limit((int) $seconds);
        @ini_set('memory_limit', '1024M');
    }

    
    public static function bulk_generate_documents(array $order_ids, $type) {
        
        
        
        self::raise_limits(600);

        $module = self::module();
        if (!$module) { return array('ok' => false, 'error' => 'module_unavailable'); }
        $docs = $module->documents();
        if (!isset($docs[$type])) { return array('ok' => false, 'error' => 'unknown_doc_type'); }
        $doc = $docs[$type];

        $document_ids = array();
        $errors = array();
        foreach ($order_ids as $oid) {
            $oid = (int) $oid;
            $order = wc_get_order($oid);
            if (!$order) { $errors[] = array('order_id' => $oid, 'error' => 'order_not_found'); continue; }
            $r = $doc->generate($order, array());
            if (empty($r['ok'])) {
                $errors[] = array('order_id' => $oid, 'error' => isset($r['error']) ? $r['error'] : 'generate_failed');
                continue;
            }
            $document_ids[] = (int) $r['document_id'];
            
            unset($order, $r);
            if (function_exists('wp_cache_flush_runtime')) {
                wp_cache_flush_runtime();
            }
        }
        return array('ok' => true, 'document_ids' => $document_ids, 'errors' => $errors, 'processed' => count($order_ids));
    }

    
    public static function merge_documents(array $order_ids, $type) {
        
        
        
        
        
        self::raise_limits(600);

        $module = self::module();
        if (!$module) { return array('ok' => false, 'error' => 'module_unavailable'); }
        $docs = $module->documents();
        if (!isset($docs[$type])) { return array('ok' => false, 'error' => 'unknown_doc_type'); }
        $doc = $docs[$type];

        if (empty($order_ids)) { return array('ok' => false, 'error' => 'no_orders'); }

        
        
        $shared_style = '';
        $body_fragments = array();
        $first_html = '';
        $errors = array();

        foreach ($order_ids as $oid) {
            $oid = (int) $oid;
            $order = wc_get_order($oid);
            if (!$order) { $errors[] = array('order_id' => $oid, 'error' => 'order_not_found'); continue; }
            $existing = AIEO_Fulfillment_Documents::get_for_order_by_type($oid, $type);
            $document_id = $existing ? (int) $existing['id'] : 0;
            if (!$document_id) {
                $r = $doc->generate($order, array());
                if (empty($r['ok'])) { $errors[] = array('order_id' => $oid, 'error' => $r['error'] ?? 'generate_failed'); continue; }
                $document_id = (int) $r['document_id'];
            }
            $html = $doc->get_html($document_id);
            if (is_wp_error($html)) { $errors[] = array('order_id' => $oid, 'error' => $html->get_error_message()); continue; }
            if ($first_html === '') { $first_html = $html; }

            
            if ($shared_style === '' && preg_match('#<style[^>]*>(.*?)</style>#is', $html, $sm)) {
                $shared_style = (string) $sm[1];
            }
            
            if (preg_match('#<body[^>]*>(.*)</body>#is', $html, $bm)) {
                $body_fragments[] = (string) $bm[1];
            } else {
                
                $body_fragments[] = $html;
            }
            
            
            
            unset($order, $html);
            if (function_exists('wp_cache_flush_runtime')) {
                wp_cache_flush_runtime();
            }
        }
        if (empty($body_fragments)) { return array('ok' => false, 'error' => 'no_body_fragments', 'errors' => $errors); }

        
        
        $body = '';
        $count = count($body_fragments);
        foreach ($body_fragments as $i => $frag) {
            $break = ($i < $count - 1) ? 'page-break-after:always;' : '';
            $body .= '<div style="' . $break . '">' . $frag . '</div>';
        }

        $merged_html =
              '<!DOCTYPE html><html><head>'
            . '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>'
            
            . '<title>' . esc_html(sprintf( __('Bulk %s', 'ai-eshop-optimizer'), $type)) . '</title>'
            . '<style type="text/css">' . $shared_style . '</style>'
            . '</head><body>' . $body . '</body></html>';

        $pdf = AIEO_Fulfillment_PDF_Engine::render($merged_html, array('paper' => 'a4', 'orientation' => 'portrait'));
        if (is_wp_error($pdf)) { return array('ok' => false, 'error' => $pdf->get_error_message()); }

        
        $upload = wp_upload_dir(null, false);
        $base   = $upload['basedir'] . '/aieo-dmm/fulfillment/bulk/' . gmdate('Y/m');
        if (!wp_mkdir_p($base)) { return array('ok' => false, 'error' => 'mkdir_failed'); }
        $stamp = gmdate('Ymd-His');
        $name  = sanitize_file_name(sprintf('bulk-%s-%s-x%d.pdf', $type, $stamp, count($body_fragments)));
        $abs   = $base . '/' . $name;
        if (file_put_contents($abs, $pdf) === false) { return array('ok' => false, 'error' => 'write_failed'); }

        return array(
            'ok'       => true,
            'pdf_path' => 'aieo-dmm/fulfillment/bulk/' . gmdate('Y/m') . '/' . $name,
            'pdf_url'  => $upload['baseurl'] . '/aieo-dmm/fulfillment/bulk/' . gmdate('Y/m') . '/' . $name,
            'merged'   => count($body_fragments),
            'errors'   => $errors,
        );
    }

    
    public static function zip_documents(array $order_ids, $type) {
        if (!class_exists('ZipArchive')) {
            return array('ok' => false, 'error' => 'ziparchive_missing');
        }
        $bulk = self::bulk_generate_documents($order_ids, $type);
        if (empty($bulk['ok'])) { return $bulk; }

        $document_ids = $bulk['document_ids'];
        $errors       = $bulk['errors'];

        $upload = wp_upload_dir(null, false);
        $base   = $upload['basedir'] . '/aieo-dmm/fulfillment/bulk/' . gmdate('Y/m');
        if (!wp_mkdir_p($base)) { return array('ok' => false, 'error' => 'mkdir_failed'); }
        $stamp = gmdate('Ymd-His');
        $zip_name = sanitize_file_name(sprintf('zip-%s-%s-x%d.zip', $type, $stamp, count($document_ids)));
        $zip_abs  = $base . '/' . $zip_name;

        $zip = new ZipArchive();
        if ($zip->open($zip_abs, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
            return array('ok' => false, 'error' => 'zip_open_failed');
        }
        $added = 0;
        foreach ($document_ids as $did) {
            $row = AIEO_Fulfillment_Documents::get($did);
            if (!$row || empty($row['pdf_path'])) { continue; }
            $abs = WP_CONTENT_DIR . '/uploads/' . ltrim((string) $row['pdf_path'], '/');
            if (!file_exists($abs)) { continue; }
            $entry = sprintf('%s-%s.pdf', $row['type'], $row['number']);
            $zip->addFile($abs, $entry);
            $added++;
        }
        $zip->close();

        if ($added === 0) {
            @wp_delete_file($zip_abs);
            return array('ok' => false, 'error' => 'no_pdfs_to_zip', 'errors' => $errors);
        }
        return array(
            'ok'      => true,
            'zip_url' => $upload['baseurl'] . '/aieo-dmm/fulfillment/bulk/' . gmdate('Y/m') . '/' . $zip_name,
            'count'   => $added,
            'errors'  => $errors,
        );
    }

    
    public static function zip_voucher_labels(array $voucher_ids) {
        
        
        
        
        
        self::raise_limits(300);

        if (!class_exists('ZipArchive')) {
            return array('ok' => false, 'error' => 'ziparchive_missing');
        }
        if (empty($voucher_ids)) { return array('ok' => false, 'error' => 'no_vouchers'); }

        $upload = wp_upload_dir(null, false);
        $base   = $upload['basedir'] . '/aieo-dmm/fulfillment/bulk/' . gmdate('Y/m');
        if (!wp_mkdir_p($base)) { return array('ok' => false, 'error' => 'mkdir_failed'); }

        $stamp    = gmdate('Ymd-His');
        $zip_name = sanitize_file_name(sprintf('labels-%s-x%d.zip', $stamp, count($voucher_ids)));
        $zip_abs  = $base . '/' . $zip_name;

        $zip = new ZipArchive();
        if ($zip->open($zip_abs, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
            return array('ok' => false, 'error' => 'zip_open_failed');
        }
        $added = 0;
        foreach ($voucher_ids as $vid) {
            $v = AIEO_Fulfillment_Vouchers::get((int) $vid);
            if (!$v || empty($v['label_pdf_path'])) { continue; }
            $abs = WP_CONTENT_DIR . '/uploads/' . ltrim((string) $v['label_pdf_path'], '/');
            if (!file_exists($abs)) { continue; }
            $entry = sprintf('%s-%s.pdf', $v['carrier'], $v['voucher_no']);
            $zip->addFile($abs, $entry);
            $added++;
        }
        $zip->close();

        if ($added === 0) {
            @wp_delete_file($zip_abs);
            return array('ok' => false, 'error' => 'no_labels_cached');
        }
        return array(
            'ok'      => true,
            'zip_url' => $upload['baseurl'] . '/aieo-dmm/fulfillment/bulk/' . gmdate('Y/m') . '/' . $zip_name,
            'count'   => $added,
        );
    }

    
    public static function order_ids_in_range($date_from, $date_to, array $statuses = array('wc-completed','wc-processing'), $limit = 1000) {
        global $wpdb;
        $from = self::sql_date($date_from, ' 00:00:00');
        $to   = self::sql_date($date_to,   ' 23:59:59');
        if ($from === '' || $to === '') { return array(); }

        $statuses = array_map('sanitize_key', $statuses);
        $placeholders = implode(',', array_fill(0, count($statuses), '%s'));
        $sql = $wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}wc_orders
             WHERE date_created_gmt BETWEEN %s AND %s
               AND status IN ({$placeholders})
             ORDER BY id ASC LIMIT %d",
            array_merge(array($from, $to), $statuses, array((int) $limit))
        );
        $rows = $wpdb->get_col($sql);
        return is_array($rows) ? array_map('intval', $rows) : array();
    }

    
    public static function voucher_ids_with_labels_in_range($date_from, $date_to, $carrier = '') {
        global $wpdb;
        $from = self::sql_date($date_from, ' 00:00:00');
        $to   = self::sql_date($date_to,   ' 23:59:59');
        if ($from === '' || $to === '') { return array(); }

        $where = array('label_pdf_path != \'\'', 'created_at BETWEEN %s AND %s');
        $args  = array($from, $to);
        if ($carrier !== '') {
            $where[] = 'carrier = %s';
            $args[]  = sanitize_key($carrier);
        }
        $sql = $wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}aieo_dmm_fulfillment_vouchers
             WHERE " . implode(' AND ', $where) . "
             ORDER BY id ASC",
            $args
        );
        $rows = $wpdb->get_col($sql);
        return is_array($rows) ? array_map('intval', $rows) : array();
    }

    private static function sql_date($maybe_date, $time_suffix) {
        $maybe_date = trim((string) $maybe_date);
        if ($maybe_date === '') { return ''; }
        
        if (preg_match('#^\d{4}-\d{2}-\d{2}$#', $maybe_date)) {
            return $maybe_date . $time_suffix;
        }
        $ts = strtotime($maybe_date . ' UTC');
        return $ts ? gmdate('Y-m-d H:i:s', $ts) : '';
    }

    private static function module() {
        if (class_exists('AIEO_DMM') && method_exists('AIEO_DMM', 'instance')) {
            $dmm = AIEO_DMM::instance();
            $m = method_exists($dmm, 'get_module') ? $dmm->get_module('fulfillment') : null;
            if ($m instanceof AIEO_DMM_Fulfillment) { return $m; }
        }
        return class_exists('AIEO_DMM_Fulfillment') ? new AIEO_DMM_Fulfillment() : null;
    }
}
