<?php
/**
 * arag-erp.php — اتصال فروشگاه عرقیات به ERP
 * حسابداری · CRM · حمل‌ونقل · انبار
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class Arag_Erp {

    public const GL = [
        'bank'          => 14,
        'ar'            => 21,
        'inventory'     => 13,
        'revenue_goods' => 51,
        'cogs'          => 52,
    ];

    public static function config_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'arag_erp_config';
    }

    public static function journal_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'arag_erp_journal';
    }

    public static function default_portal(): array {
        return [
            'office_code'     => 'ARAG-01',
            'office_name'     => 'فروشگاه عرقیات',
            'subsystem_label' => 'فروشگاه آنلاین عرقیات',
            'ledger_tag'      => 'SHOP',
        ];
    }

    public static function portal_settings(): array {
        $saved = get_option( 'arag_portal_office', [] );
        return array_merge( self::default_portal(), is_array( $saved ) ? $saved : [] );
    }

    public static function save_portal_settings( array $data ): bool {
        $base = self::default_portal();
        $out  = [];
        foreach ( array_keys( $base ) as $k ) {
            if ( isset( $data[ $k ] ) ) {
                $out[ $k ] = sanitize_text_field( (string) $data[ $k ] );
            }
        }
        return update_option( 'arag_portal_office', array_merge( $base, $out ), false );
    }

    public static function get_config(): array {
        global $wpdb;
        $t = self::config_table();
        $defaults = [
            'auto_post'         => false,
            'auto_ship'         => true,
            'auto_crm'          => true,
            'auto_issue_stock'  => true,
            'check_stock'       => true,
            'default_carrier'   => '',
            'default_warehouse' => 0,
            'cogs_pct'          => 55.0,
            'fulfillment_pct'   => 4.0,
            'shipping_cost_pct' => 3.0,
            'marketing_pct'     => 2.0,
            'ops_pct'           => 1.5,
        ];
        if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $t ) ) !== $t ) {
            return $defaults;
        }
        $row = $wpdb->get_var( "SELECT payload FROM {$t} ORDER BY id ASC LIMIT 1" );
        if ( $row ) {
            $defaults = array_merge( $defaults, json_decode( $row, true ) ?: [] );
        }
        return $defaults;
    }

    public static function save_config( array $payload ): bool {
        global $wpdb;
        $t    = self::config_table();
        $json = wp_json_encode( $payload, JSON_UNESCAPED_UNICODE );
        $id   = (int) $wpdb->get_var( "SELECT id FROM {$t} ORDER BY id ASC LIMIT 1" );
        if ( $id ) {
            return (bool) $wpdb->update( $t, [ 'payload' => $json, 'updated_at' => current_time( 'mysql' ) ], [ 'id' => $id ] );
        }
        return (bool) $wpdb->insert( $t, [ 'payload' => $json ] );
    }

    public static function get_order( int $order_id ): ?array {
        global $wpdb;
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}arag_orders WHERE id = %d", $order_id
        ), ARRAY_A );
        if ( ! $row ) return null;
        $row['items'] = json_decode( $row['items_json'] ?? '[]', true ) ?: [];
        return $row;
    }

    public static function default_warehouse_id(): int {
        $cfg = self::get_config();
        $wid = (int) ( $cfg['default_warehouse'] ?? 0 );
        if ( $wid > 0 ) {
            return $wid;
        }
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}inv_warehouses'" ) !== "{$pre}inv_warehouses" ) {
            return 0;
        }
        return (int) $wpdb->get_var(
            "SELECT id FROM {$pre}inv_warehouses WHERE is_active = 1 ORDER BY id ASC LIMIT 1"
        );
    }

    public static function resolve_package_product( int $package_id ): ?int {
        if ( $package_id <= 0 ) {
            return null;
        }
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( ! $wpdb->get_var( "SHOW COLUMNS FROM {$pre}arag_packages LIKE 'inv_product_id'" ) ) {
            return null;
        }
        $pid = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT inv_product_id FROM {$pre}arag_packages WHERE id = %d AND is_active = 1", $package_id
        ) );
        return $pid > 0 ? $pid : null;
    }

    public static function enrich_line_items( array $items ): array {
        foreach ( $items as &$it ) {
            $pkg_id = (int) ( $it['package_id'] ?? 0 );
            if ( $pkg_id > 0 && empty( $it['inv_product_id'] ) ) {
                $it['inv_product_id'] = self::resolve_package_product( $pkg_id );
            }
        }
        unset( $it );
        return $items;
    }

    public static function validate_order_stock( array $items ): array {
        $cfg = self::get_config();
        if ( empty( $cfg['check_stock'] ) ) {
            return [ 'success' => true, 'skipped' => true ];
        }
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}inv_stock'" ) !== "{$pre}inv_stock" ) {
            return [ 'success' => true, 'skipped' => true, 'message' => 'انبار نصب نیست' ];
        }
        $wh = self::default_warehouse_id();
        if ( $wh <= 0 ) {
            return [ 'success' => true, 'skipped' => true, 'message' => 'انبار پیش‌فرض تنظیم نشده' ];
        }

        $items = self::enrich_line_items( $items );
        $short = [];
        foreach ( $items as $it ) {
            $pid = (int) ( $it['inv_product_id'] ?? 0 );
            $qty = (float) ( $it['qty'] ?? 1 );
            if ( $pid <= 0 ) {
                continue;
            }
            $avail = (float) $wpdb->get_var( $wpdb->prepare(
                "SELECT qty FROM {$pre}inv_stock WHERE product_id = %d AND warehouse_id = %d",
                $pid, $wh
            ) );
            if ( $avail < $qty ) {
                $short[] = ( $it['label'] ?? "محصول #{$pid}" ) . " (موجودی: {$avail})";
            }
        }
        if ( $short ) {
            return [
                'success' => false,
                'message' => 'موجودی کافی نیست: ' . implode( '، ', $short ),
            ];
        }
        return [ 'success' => true ];
    }

    /** ثبت لید CRM هنگام ثبت سفارش */
    public static function on_order_placed( int $order_id ): array {
        $cfg = self::get_config();
        if ( empty( $cfg['auto_crm'] ) ) {
            return [ 'success' => true, 'skipped' => true, 'message' => 'CRM غیرفعال' ];
        }
        $order = self::get_order( $order_id );
        if ( ! $order ) {
            return [ 'success' => false, 'message' => 'سفارش یافت نشد' ];
        }
        if ( ! empty( $order['crm_lead_id'] ) ) {
            return [ 'success' => true, 'lead_id' => (int) $order['crm_lead_id'], 'skipped' => true ];
        }
        return self::sync_crm_lead( $order );
    }

    /** پس از تأیید پرداخت / پرداخت در محل — حمل‌ونقل + حسابداری */
    public static function on_order_confirmed( int $order_id ): array {
        $order = self::get_order( $order_id );
        if ( ! $order ) {
            return [ 'success' => false, 'message' => 'سفارش یافت نشد' ];
        }
        $out = [ 'order_id' => $order_id ];
        $crm = self::on_order_placed( $order_id );
        $out['crm'] = $crm;

        $cfg = self::get_config();
        if ( ! empty( $cfg['auto_ship'] ) && empty( $order['ship_shipment_id'] ) ) {
            $out['shipping'] = self::create_shipment( $order );
        }
        if ( empty( $order['acc_event_id'] ) ) {
            $out['accounting'] = self::create_accounting_event( $order );
        } else {
            $out['accounting'] = [ 'success' => true, 'event_id' => (int) $order['acc_event_id'], 'skipped' => true ];
        }

        /* بهای تمام‌شده فعالیت + گراف سهم نفر/کانال */
        if ( file_exists( ACC_PATH . 'includes/helpers/arag-activity-cost.php' ) ) {
            require_once ACC_PATH . 'includes/helpers/arag-activity-cost.php';
            $fresh = self::get_order( $order_id ) ?: $order;
            $abc = Arag_Activity_Cost::allocate( $fresh );
            Arag_Activity_Cost::persist( $order_id, $abc );
            $out['activity_cost'] = [
                'totals' => $abc['totals'],
                'person_shares' => $abc['person_shares'],
            ];
        }

        global $wpdb;
        $wpdb->update( "{$wpdb->prefix}arag_orders", [
            'erp_synced_at' => current_time( 'mysql' ),
        ], [ 'id' => $order_id ] );

        return array_merge( [ 'success' => true ], $out );
    }

    public static function sync_crm_lead( array $order ): array {
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}crm_leads'" ) !== "{$pre}crm_leads" ) {
            return [ 'success' => false, 'message' => 'جدول CRM نصب نیست — run-arag-erp-install.php را اجرا کنید' ];
        }

        $phone = preg_replace( '/\D/', '', $order['billing_phone'] ?? '' );
        $name  = $order['billing_name'] ?: 'مشتری فروشگاه';
        $items = $order['items'] ?? [];
        $summary = implode( '، ', array_map( static function ( $it ) {
            return ( $it['label'] ?? '' ) . ' ×' . ( $it['qty'] ?? 1 );
        }, array_slice( $items, 0, 5 ) ) );

        $existing = null;
        if ( ! empty( $order['crm_lead_id'] ) ) {
            $existing = (int) $order['crm_lead_id'];
        } elseif ( $phone ) {
            $existing = (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT id FROM {$pre}crm_leads WHERE arag_order_id = %d OR (phone = %s AND lead_channel = 'shop') ORDER BY id DESC LIMIT 1",
                (int) $order['id'], $phone
            ) );
        }

        $notes = "سفارش {$order['order_number']} — {$summary}\nمبلغ: " . number_format( (float) $order['subtotal'] ) . " تومان";
        $status = in_array( $order['payment_status'] ?? '', [ 'paid', 'cod' ], true ) ? 'converted' : 'negotiating';

        if ( $existing ) {
            $wpdb->update( "{$pre}crm_leads", [
                'name'             => $name,
                'phone'            => $phone ?: null,
                'address'          => $order['billing_address'] ?? '',
                'status'           => $status,
                'arag_order_id'    => (int) $order['id'],
                'lead_channel'     => 'shop',
                'last_contact_date'=> current_time( 'Y-m-d' ),
                'notes'            => $notes,
                'score'            => $status === 'converted' ? 80 : 50,
            ], [ 'id' => $existing ] );
            $lead_id = $existing;
        } else {
            $wpdb->insert( "{$pre}crm_leads", [
                'type'              => 'individual',
                'name'              => $name,
                'phone'             => $phone ?: null,
                'address'           => $order['billing_address'] ?? '',
                'source'            => 'website',
                'status'            => $status,
                'arag_order_id'     => (int) $order['id'],
                'lead_channel'      => 'shop',
                'last_contact_date' => current_time( 'Y-m-d' ),
                'score'             => $status === 'converted' ? 80 : 50,
                'notes'             => $notes,
            ] );
            $lead_id = (int) $wpdb->insert_id;
        }

        $wpdb->update( "{$pre}arag_orders", [ 'crm_lead_id' => $lead_id ], [ 'id' => (int) $order['id'] ] );

        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}crm_activities'" ) === "{$pre}crm_activities" ) {
            $wpdb->insert( "{$pre}crm_activities", [
                'lead_id'         => $lead_id,
                'type'            => 'note',
                'direction'       => 'inbound',
                'subject'         => 'سفارش فروشگاه — ' . ( $order['order_number'] ?? '' ),
                'body'            => $notes,
                'activity_date'   => current_time( 'mysql' ),
                'result'          => 'positive',
                'created_by_name' => 'سیستم فروشگاه',
            ] );
        }

        return [ 'success' => true, 'lead_id' => $lead_id ];
    }

    public static function create_shipment( array $order ): array {
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}ship_shipments'" ) !== "{$pre}ship_shipments" ) {
            return [ 'success' => false, 'message' => 'ماژول حمل‌ونقل نصب نیست' ];
        }
        if ( ! empty( $order['ship_shipment_id'] ) ) {
            return [ 'success' => true, 'shipment_id' => (int) $order['ship_shipment_id'], 'skipped' => true ];
        }

        $method_code = $order['shipping_method'] ?? 'post';
        $method_id   = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM {$pre}ship_methods WHERE code = %s AND is_active = 1 LIMIT 1", $method_code
        ) );
        if ( ! $method_id ) {
            $method_id = (int) $wpdb->get_var( "SELECT id FROM {$pre}ship_methods WHERE is_active = 1 ORDER BY id ASC LIMIT 1" );
        }

        $cfg = self::get_config();
        $carrier_id = ! empty( $cfg['default_carrier'] ) ? (int) $cfg['default_carrier'] : null;

        $year = date( 'Y' );
        $last = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM {$pre}ship_shipments WHERE shipment_no LIKE %s", "OUT-{$year}-%"
        ) );
        $shipment_no = sprintf( 'OUT-%s-%04d', $year, $last + 1 );

        $addr = trim( ( $order['billing_address'] ?? '' ) . ( $order['billing_city'] ? ' — ' . $order['billing_city'] : '' ) );
        $wh_id = self::default_warehouse_id();
        $items = self::enrich_line_items( $order['items'] ?? [] );

        $wpdb->insert( "{$pre}ship_shipments", [
            'shipment_no'           => $shipment_no,
            'direction'             => 'outbound',
            'status'                => 'pending',
            'method_id'             => $method_id ?: null,
            'carrier_id'            => $carrier_id,
            'ref_type'              => 'arag_order',
            'ref_id'                => (int) $order['id'],
            'ref_no'                => $order['order_number'] ?? '',
            'from_warehouse_id'     => $wh_id ?: null,
            'recipient_name'        => $order['billing_name'] ?? '',
            'recipient_phone'       => $order['billing_phone'] ?? '',
            'destination_address'   => $addr,
            'notes'                 => $order['customer_note'] ?? '',
            'total_packages'        => count( $items ),
        ] );
        $sid = (int) $wpdb->insert_id;

        foreach ( $items as $it ) {
            $wpdb->insert( "{$pre}ship_items", [
                'shipment_id'  => $sid,
                'ref_item_id'  => (int) ( $it['package_id'] ?? 0 ) ?: null,
                'product_id'   => (int) ( $it['inv_product_id'] ?? 0 ) ?: null,
                'product_name' => $it['label'] ?? '',
                'qty_planned'  => (float) ( $it['qty'] ?? 1 ),
                'unit'         => $it['volume'] ?? 'عدد',
            ] );
        }

        if ( class_exists( 'Shipping_Controller' ) ) {
            self::_log_ship_stage( $sid, 'pending', "محموله از سفارش فروشگاه {$order['order_number']} ایجاد شد" );
        } else {
            $wpdb->insert( "{$pre}ship_stages", [
                'shipment_id' => $sid,
                'status'      => 'pending',
                'notes'       => "محموله از سفارش فروشگاه {$order['order_number']} ایجاد شد",
                'created_at'  => current_time( 'mysql' ),
            ] );
        }

        $wpdb->update( "{$pre}arag_orders", [ 'ship_shipment_id' => $sid ], [ 'id' => (int) $order['id'] ] );

        return [ 'success' => true, 'shipment_id' => $sid, 'shipment_no' => $shipment_no ];
    }

    private static function _log_ship_stage( int $sid, string $status, string $note ): void {
        global $wpdb;
        $wpdb->insert( $wpdb->prefix . 'ship_stages', [
            'shipment_id' => $sid,
            'status'      => $status,
            'notes'       => $note,
            'created_at'  => current_time( 'mysql' ),
        ] );
    }

    public static function create_accounting_event( array $order ): array {
        global $wpdb;
        if ( ! empty( $order['acc_event_id'] ) ) {
            return [ 'success' => true, 'event_id' => (int) $order['acc_event_id'], 'skipped' => true ];
        }

        $total = (float) ( $order['total'] ?? 0 );
        if ( $total <= 0 ) {
            $total = (float) ( $order['subtotal'] ?? 0 );
        }
        if ( $total <= 0 ) {
            return [ 'success' => false, 'message' => 'مبلغ سفارش نامعتبر' ];
        }

        $portal = self::portal_settings();
        $paid   = ( $order['payment_status'] ?? '' ) === 'paid';
        $dr_gl  = $paid ? self::GL['bank'] : self::GL['ar'];
        $cfg    = self::get_config();
        $cogs_pct = (float) ( $cfg['cogs_pct'] ?? 0 );
        $cogs_amount = $cogs_pct > 0 ? round( $total * $cogs_pct / 100, 2 ) : 0;

        $pairs = [
            [
                'dr_gl_id'     => $dr_gl,
                'cr_gl_id'     => self::GL['revenue_goods'],
                'source_field' => 'total_amount',
                'desc'         => '[' . $portal['ledger_tag'] . '|' . $portal['office_name'] . '] فروش عرقیات ' . ( $order['order_number'] ?? '' ),
            ],
        ];
        if ( $cogs_amount > 0 ) {
            $pairs[] = [
                'dr_gl_id'     => self::GL['cogs'],
                'cr_gl_id'     => self::GL['inventory'],
                'source_field' => 'cogs_amount',
                'desc'         => '[' . $portal['ledger_tag'] . '] بهای تمام‌شده فروش ' . ( $order['order_number'] ?? '' ),
            ];
        }

        $payload = [
            'source_module'    => 'arag_shop',
            'shop_office_code' => $portal['office_code'],
            'shop_office_name' => $portal['office_name'],
            'ledger_tag'       => $portal['ledger_tag'],
            'order_id'         => (int) $order['id'],
            'order_number'     => $order['order_number'] ?? '',
            'customer_name'    => $order['billing_name'] ?? '',
            'customer_phone'   => $order['billing_phone'] ?? '',
            'payment_status'   => $order['payment_status'] ?? '',
            'payment_method'   => $order['payment_method'] ?? '',
            'total_amount'     => $total,
            'cogs_amount'      => $cogs_amount,
            'manual_entries'   => [ 'pairs' => $pairs ],
        ];

        if ( ! class_exists( 'Acc_Event_Engine' ) ) {
            require_once ACC_PATH . 'includes/helpers/acc-event-engine.php';
        }

        $created = Acc_Event_Engine::create_event( [
            'event_type'      => 'SHOP_SALE',
            'amount'          => $total,
            'payload'         => $payload,
            'reference_type'  => 'arag_order',
            'reference_id'    => (int) $order['id'],
            'idempotency_key' => 'arag_sale_' . (int) $order['id'],
            'source_module'   => 'arag_shop',
            'description'     => '[' . $portal['ledger_tag'] . '|' . $portal['office_name'] . '] فروش ' . ( $order['order_number'] ?? '' ),
        ] );

        if ( empty( $created['success'] ) ) {
            return $created;
        }

        $event_id = (int) ( $created['event_id'] ?? 0 );
        $wpdb->update( "{$wpdb->prefix}arag_orders", [ 'acc_event_id' => $event_id ], [ 'id' => (int) $order['id'] ] );

        self::_journal_log( (int) $order['id'], 'SHOP_SALE', $event_id, $total, 'pending' );

        $cfg = self::get_config();
        if ( ! empty( $cfg['auto_post'] ) && $event_id ) {
            return self::post_order_by_accountant( (int) $order['id'] );
        }

        return [
            'success'  => true,
            'pending'  => true,
            'event_id' => $event_id,
            'message'  => 'رویداد #' . $event_id . ' در صف صدور حسابدار',
        ];
    }

    public static function post_order_by_accountant( int $order_id, int $user_id = 0 ): array {
        global $wpdb;
        $order = self::get_order( $order_id );
        if ( ! $order ) {
            return [ 'success' => false, 'message' => 'سفارش یافت نشد' ];
        }

        if ( empty( $order['acc_event_id'] ) ) {
            $prep = self::create_accounting_event( $order );
            if ( empty( $prep['event_id'] ) ) {
                $order = self::get_order( $order_id );
            }
        }

        $event_id = (int) ( $order['acc_event_id'] ?? 0 );
        if ( ! $event_id ) {
            return [ 'success' => false, 'message' => 'رویداد حسابداری یافت نشد' ];
        }

        if ( ! class_exists( 'Acc_Event_Engine' ) ) {
            require_once ACC_PATH . 'includes/helpers/acc-event-engine.php';
        }

        $state = (string) $wpdb->get_var( $wpdb->prepare(
            "SELECT workflow_state FROM {$wpdb->prefix}ai_acc_events WHERE id = %d", $event_id
        ) );
        if ( ! class_exists( 'Arag_Shop_Accounting' ) ) {
            require_once ACC_PATH . 'includes/helpers/arag-shop-accounting.php';
        }

        if ( $state === 'posted' ) {
            $confirm = Arag_Shop_Accounting::confirm_event( $event_id );
            return [
                'success'   => ! empty( $confirm['success'] ),
                'message'   => ! empty( $confirm['already'] ) ? 'قبلاً ثبت و تأیید شده' : 'سند تأیید شد',
                'event_id'  => $event_id,
                'confirmed' => true,
            ];
        }
        if ( $state === 'confirmed' ) {
            return [ 'success' => true, 'message' => 'قبلاً ثبت و تأیید شده', 'event_id' => $event_id ];
        }

        $posted = Acc_Event_Engine::post_event( $event_id, $user_id ?: (int) get_current_user_id() );
        if ( empty( $posted['success'] ) ) {
            return $posted;
        }

        Arag_Shop_Accounting::confirm_event( $event_id );

        self::_journal_log( $order_id, 'SHOP_SALE', $event_id, (float) $order['subtotal'], 'confirmed', $user_id );

        return [
            'success'   => true,
            'event_id'  => $event_id,
            'confirmed' => true,
            'message'   => 'سند فروشگاه #' . $event_id . ' صادر و در دفتر کل ثبت شد',
        ];
    }

    public static function pending_accounting_queue( int $limit = 50 ): array {
        global $wpdb;
        $pre = $wpdb->prefix;
        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT o.id, o.order_number, o.subtotal, o.payment_status, o.billing_name, o.billing_phone,
                    o.acc_event_id, o.created_at, e.workflow_state
             FROM {$pre}arag_orders o
             INNER JOIN {$pre}ai_acc_events e ON e.id = o.acc_event_id
             WHERE e.workflow_state IN ('pending','failed')
             ORDER BY o.id DESC
             LIMIT %d",
            $limit
        ), ARRAY_A ) ?: [];
        return $rows;
    }

    private static function _journal_log( int $order_id, string $type, int $event_id, float $amount, string $status, int $user_id = 0 ): void {
        global $wpdb;
        $t = self::journal_table();
        if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $t ) ) !== $t ) {
            return;
        }
        $wpdb->insert( $t, [
            'order_id'     => $order_id,
            'event_type'   => $type,
            'acc_event_id' => $event_id,
            'amount'       => $amount,
            'status'       => $status,
            'posted_by'    => $user_id ?: null,
            'created_at'   => current_time( 'mysql' ),
        ] );
    }

    public static function erp_jwt_user_id(): int {
        if ( function_exists( '_acc_jwt_user_id_from_request' ) ) {
            return _acc_jwt_user_id_from_request();
        }
        return 0;
    }

    public static function erp_can_view(): bool {
        $uid = self::erp_jwt_user_id();
        if ( $uid <= 0 ) {
            return false;
        }
        if ( function_exists( 'acl_user_is_super_admin' ) && acl_user_is_super_admin( $uid ) ) {
            return true;
        }
        foreach ( [ 'shop.erp', 'shop.accounting', 'shop.manage', 'acc.view', 'crm.view', 'ship.view' ] as $pk ) {
            if ( function_exists( 'acl_user_can' ) && acl_user_can( $uid, $pk ) ) {
                return true;
            }
        }
        return false;
    }

    public static function erp_can_post(): bool {
        $uid = self::erp_jwt_user_id();
        if ( $uid <= 0 ) {
            return false;
        }
        if ( function_exists( 'acl_user_is_super_admin' ) && acl_user_is_super_admin( $uid ) ) {
            return true;
        }
        foreach ( [ 'shop.accounting.post', 'shop.erp', 'acc.post' ] as $pk ) {
            if ( function_exists( 'acl_user_can' ) && acl_user_can( $uid, $pk ) ) {
                return true;
            }
        }
        return false;
    }

    /** صدور سند خروج انبار از محموله فروشگاه */
    public static function issue_stock_for_shipment( int $shipment_id, string $trigger = 'delivered' ): array {
        global $wpdb;
        $pre = $wpdb->prefix;
        $cfg = self::get_config();
        if ( empty( $cfg['auto_issue_stock'] ) ) {
            return [ 'success' => true, 'skipped' => true, 'message' => 'صدور خودکار انبار غیرفعال' ];
        }
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}inv_vouchers'" ) !== "{$pre}inv_vouchers" ) {
            return [ 'success' => false, 'message' => 'ماژول انبار نصب نیست' ];
        }

        $shipment = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$pre}ship_shipments WHERE id = %d AND ref_type = 'arag_order'", $shipment_id
        ), ARRAY_A );
        if ( ! $shipment ) {
            return [ 'success' => false, 'message' => 'محموله یافت نشد' ];
        }
        if ( ! $shipment['from_warehouse_id'] ) {
            return [ 'success' => false, 'message' => 'انبار مبدأ تنظیم نشده' ];
        }

        $exists = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM {$pre}inv_vouchers WHERE ref_type = 'shipment' AND ref_id = %d AND type = 'sale_issue'",
            $shipment_id
        ) );
        if ( $exists ) {
            return [ 'success' => true, 'voucher_id' => $exists, 'skipped' => true ];
        }

        $items = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM {$pre}ship_items WHERE shipment_id = %d AND product_id IS NOT NULL",
            $shipment_id
        ), ARRAY_A );
        if ( empty( $items ) ) {
            return [ 'success' => false, 'message' => 'آیتم محموله به محصول انبار وصل نیست' ];
        }

        $last = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$pre}inv_vouchers WHERE type = 'sale_issue'" );
        $voucher_no = 'SAL-' . str_pad( (string) ( $last + 1 ), 5, '0', STR_PAD_LEFT );

        $wpdb->insert( "{$pre}inv_vouchers", [
            'voucher_no'   => $voucher_no,
            'type'         => 'sale_issue',
            'status'       => 'confirmed',
            'ref_id'       => $shipment_id,
            'ref_type'     => 'shipment',
            'ref_no'       => $shipment['shipment_no'],
            'date'         => date( 'Y-m-d' ),
            'description'  => "خروج انبار فروشگاه — محموله {$shipment['shipment_no']} ({$trigger})",
            'confirmed_at' => current_time( 'mysql' ),
        ] );
        $vid = (int) $wpdb->insert_id;

        foreach ( $items as $it ) {
            $qty = (float) $it['qty_planned'];
            $pid = (int) $it['product_id'];
            $wh  = (int) $shipment['from_warehouse_id'];
            $wpdb->insert( "{$pre}inv_voucher_items", [
                'voucher_id'        => $vid,
                'product_id'        => $pid,
                'from_warehouse_id' => $wh,
                'qty'               => $qty,
            ] );
            $wpdb->query( $wpdb->prepare(
                "UPDATE {$pre}inv_stock SET qty = qty - %f WHERE product_id = %d AND warehouse_id = %d",
                $qty, $pid, $wh
            ) );
        }

        if ( ! empty( $shipment['ref_id'] ) && $wpdb->get_var( "SHOW COLUMNS FROM {$pre}arag_orders LIKE 'inv_voucher_id'" ) ) {
            $wpdb->update( "{$pre}arag_orders", [ 'inv_voucher_id' => $vid ], [ 'id' => (int) $shipment['ref_id'] ] );
        }

        self::_journal_log( (int) $shipment['ref_id'], 'INV_SALE_ISSUE', $vid, 0, 'posted' );

        return [
            'success'    => true,
            'voucher_id' => $vid,
            'voucher_no' => $voucher_no,
            'message'    => "سند خروج انبار {$voucher_no} صادر شد",
        ];
    }

    public static function advance_shop_shipment( int $shipment_id, string $status, string $note = '' ): array {
        global $wpdb;
        $pre = $wpdb->prefix;

        $ship = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$pre}ship_shipments WHERE id = %d AND ref_type = 'arag_order'", $shipment_id
        ), ARRAY_A );
        if ( ! $ship ) {
            return [ 'success' => false, 'message' => 'محموله یافت نشد' ];
        }

        $flow = [
            'pending' => 'در انتظار', 'preparing' => 'آماده‌سازی', 'packed' => 'بسته‌بندی',
            'picked_up' => 'تحویل پیک', 'in_transit' => 'در حال حمل',
            'out_for_delivery' => 'ارسال نهایی', 'delivered' => 'تحویل شد',
        ];
        if ( ! isset( $flow[ $status ] ) ) {
            return [ 'success' => false, 'message' => 'وضعیت نامعتبر' ];
        }

        $update = [ 'status' => $status, 'updated_at' => current_time( 'mysql' ) ];
        if ( $status === 'picked_up' && empty( $ship['actual_pickup_date'] ) ) {
            $update['actual_pickup_date'] = current_time( 'mysql' );
        }
        if ( $status === 'delivered' ) {
            $update['actual_delivery_date'] = current_time( 'mysql' );
        }
        $wpdb->update( "{$pre}ship_shipments", $update, [ 'id' => $shipment_id ] );

        $wpdb->insert( "{$pre}ship_stages", [
            'shipment_id' => $shipment_id,
            'status'      => $status,
            'notes'       => $note ?: ( 'وضعیت به ' . $flow[ $status ] . ' تغییر کرد' ),
            'created_at'  => current_time( 'mysql' ),
        ] );

        $inv = null;
        if ( $status === 'delivered' ) {
            $inv = self::issue_stock_for_shipment( $shipment_id, 'delivered' );
            if ( ! empty( $ship['ref_id'] ) ) {
                $wpdb->update( "{$pre}arag_orders", [
                    'order_status' => 'completed',
                ], [ 'id' => (int) $ship['ref_id'] ] );
            }
        }

        return [
            'success'   => true,
            'status'    => $status,
            'inventory' => $inv,
        ];
    }

    public static function inventory_stock_summary( int $limit = 30 ): array {
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}inv_stock'" ) !== "{$pre}inv_stock" ) {
            return [];
        }
        $wh = self::default_warehouse_id();
        $where = $wh > 0 ? $wpdb->prepare( 'WHERE s.warehouse_id = %d', $wh ) : '';
        return $wpdb->get_results(
            "SELECT p.id AS product_id, p.code, p.name, p.unit,
                    s.warehouse_id, w.name AS warehouse_name, s.qty, s.avg_cost
             FROM {$pre}inv_stock s
             INNER JOIN {$pre}inv_products p ON p.id = s.product_id
             LEFT JOIN {$pre}inv_warehouses w ON w.id = s.warehouse_id
             {$where}
             ORDER BY p.name ASC
             LIMIT {$limit}",
            ARRAY_A
        ) ?: [];
    }

    public static function shop_inventory_vouchers( int $limit = 20 ): array {
        global $wpdb;
        $pre = $wpdb->prefix;
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}inv_vouchers'" ) !== "{$pre}inv_vouchers" ) {
            return [];
        }
        return $wpdb->get_results(
            "SELECT v.*, o.order_number, o.billing_name
             FROM {$pre}inv_vouchers v
             INNER JOIN {$pre}ship_shipments sh ON sh.id = v.ref_id AND v.ref_type = 'shipment'
             LEFT JOIN {$pre}arag_orders o ON o.id = sh.ref_id AND sh.ref_type = 'arag_order'
             WHERE v.type = 'sale_issue' AND sh.ref_type = 'arag_order'
             ORDER BY v.id DESC
             LIMIT {$limit}",
            ARRAY_A
        ) ?: [];
    }
}
