<?php
/**
 * InventoryIntegration.php — ادغام انبار با خرید و فروش
 * این کلاس helper فقط برای ثبت خودکار سند انبار هنگام نهایی‌سازی فاکتور استفاده می‌شود
 */

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

class InventoryIntegration {

    /**
     * هنگام نهایی‌سازی فاکتور خرید:
     * ورود کالا به انبار → سند purchase_receipt
     */
    public static function on_purchase_finalized( int $invoice_id ): void {
        global $wpdb;
        $pre = $wpdb->prefix;

        $invoice = $wpdb->get_row( $wpdb->prepare(
            "SELECT invoice_no, invoice_date, warehouse_id FROM {$pre}ai_purchase_invoices WHERE id=%d", $invoice_id
        ), ARRAY_A );

        if ( ! $invoice || ! $invoice['warehouse_id'] ) return;

        $items = $wpdb->get_results( $wpdb->prepare(
            "SELECT ii.quantity, ii.unit_price, ii.description,
                    sp.inv_product_id,
                    ip.costing_method, ip.tracking
             FROM {$pre}ai_purchase_invoice_items ii
             LEFT JOIN {$pre}ai_sale_products   sp ON sp.id = ii.product_id
             LEFT JOIN {$pre}inv_products        ip ON ip.id = sp.inv_product_id
             WHERE ii.invoice_id = %d
               AND sp.inv_product_id IS NOT NULL
               AND ip.id IS NOT NULL",
            $invoice_id
        ), ARRAY_A );

        if ( empty( $items ) ) return;

        self::_create_voucher_and_update_stock(
            'purchase_receipt',
            'purchase_invoice',
            $invoice_id,
            $invoice['invoice_no'],
            $invoice['invoice_date'],
            "ورود از خرید — فاکتور {$invoice['invoice_no']}",
            null,
            (int)$invoice['warehouse_id'],
            $items
        );
    }

    /**
     * هنگام نهایی‌سازی فاکتور فروش:
     * خروج کالا از انبار → سند sale_issue
     */
    public static function on_sale_finalized( int $invoice_id ): void {
        global $wpdb;
        $pre = $wpdb->prefix;

        $invoice = $wpdb->get_row( $wpdb->prepare(
            "SELECT invoice_no, invoice_date, warehouse_id FROM {$pre}ai_sale_invoices WHERE id=%d", $invoice_id
        ), ARRAY_A );

        if ( ! $invoice || ! $invoice['warehouse_id'] ) return;

        $items = $wpdb->get_results( $wpdb->prepare(
            "SELECT ii.quantity, ii.unit_price, ii.description,
                    sp.inv_product_id,
                    ip.costing_method, ip.tracking
             FROM {$pre}ai_sale_invoice_items ii
             LEFT JOIN {$pre}ai_sale_products  sp ON sp.id = ii.product_id
             LEFT JOIN {$pre}inv_products       ip ON ip.id = sp.inv_product_id
             WHERE ii.invoice_id = %d
               AND sp.inv_product_id IS NOT NULL
               AND ip.id IS NOT NULL",
            $invoice_id
        ), ARRAY_A );

        if ( empty( $items ) ) return;

        // اعتبارسنجی موجودی قبل از خروج
        foreach ( $items as $item ) {
            $pid   = (int)$item['inv_product_id'];
            $qty   = (float)$item['quantity'];
            $stock = (float)( $wpdb->get_var( $wpdb->prepare(
                "SELECT COALESCE(qty,0) FROM {$pre}inv_stock WHERE product_id=%d AND warehouse_id=%d",
                $pid, (int)$invoice['warehouse_id']
            ) ) ?? 0 );

            if ( $stock < $qty ) {
                $pname = $wpdb->get_var( $wpdb->prepare( "SELECT name FROM {$pre}inv_products WHERE id=%d", $pid ) );
                // ثبت لاگ — بدون متوقف کردن عملیات حسابداری
                error_log( "InventoryIntegration: موجودی «{$pname}» کافی نیست (موجود: {$stock} | لازم: {$qty})" );
            }
        }

        self::_create_voucher_and_update_stock(
            'sale_issue',
            'sale_invoice',
            $invoice_id,
            $invoice['invoice_no'],
            $invoice['invoice_date'],
            "خروج برای فروش — فاکتور {$invoice['invoice_no']}",
            (int)$invoice['warehouse_id'],
            null,
            $items
        );
    }

    /* ── ایجاد سند انبار + به‌روزرسانی موجودی ────────────────── */
    private static function _create_voucher_and_update_stock(
        string $type,
        string $ref_type,
        int    $ref_id,
        string $ref_no,
        string $date,
        string $description,
        ?int   $from_wh,
        ?int   $to_wh,
        array  $items
    ): void {
        global $wpdb;
        $pre = $wpdb->prefix;

        // جلوگیری از ثبت تکراری
        $exists = $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM {$pre}inv_vouchers WHERE ref_type=%s AND ref_id=%d AND type=%s",
            $ref_type, $ref_id, $type
        ) );
        if ( $exists ) return;

        // شماره‌گذاری خودکار
        $prefix   = strtoupper( substr( $type, 0, 3 ) );
        $last_no  = $wpdb->get_var( $wpdb->prepare(
            "SELECT voucher_no FROM {$pre}inv_vouchers WHERE type=%s ORDER BY id DESC LIMIT 1", $type
        ) );
        $next_num   = $last_no ? ( intval( substr( $last_no, -5 ) ) + 1 ) : 1;
        $voucher_no = $prefix . '-' . str_pad( $next_num, 5, '0', STR_PAD_LEFT );

        $wpdb->insert( "{$pre}inv_vouchers", [
            'voucher_no'   => $voucher_no,
            'type'         => $type,
            'status'       => 'confirmed',
            'ref_id'       => $ref_id,
            'ref_type'     => $ref_type,
            'ref_no'       => $ref_no,
            'date'         => $date,
            'description'  => $description,
            'confirmed_at' => current_time( 'mysql' ),
        ] );
        $voucher_id = (int) $wpdb->insert_id;

        foreach ( $items as $item ) {
            $pid        = (int)$item['inv_product_id'];
            $qty        = (float)$item['quantity'];
            $unit_price = (float)$item['unit_price'];
            $costing    = $item['costing_method'] ?? 'avg';

            $wpdb->insert( "{$pre}inv_voucher_items", [
                'voucher_id'        => $voucher_id,
                'product_id'        => $pid,
                'from_warehouse_id' => $from_wh,
                'to_warehouse_id'   => $to_wh,
                'qty'               => $qty,
                'unit_price'        => $unit_price,
                'total_price'       => $qty * $unit_price,
                'notes'             => sanitize_text_field( $item['description'] ?? '' ),
            ] );
            $item_id = (int) $wpdb->insert_id;

            // به‌روزرسانی موجودی
            if ( $to_wh ) {
                // ورود — افزایش موجودی
                $cost = $unit_price > 0 ? $unit_price : self::_get_avg_cost( $pid );
                self::_increase_stock( $pid, $to_wh, $qty, $cost, $costing, $item_id );
            }
            if ( $from_wh ) {
                // خروج — کاهش موجودی
                self::_decrease_stock( $pid, $from_wh, $qty, $costing, $item_id );
            }
        }
    }

    /**
     * هنگام نهایی‌سازی گزارش خدمات: خروج قطعات از انبار
     */
    public static function on_service_report_finalized( int $report_id, int $warehouse_id ): void {
        global $wpdb;
        $pre = $wpdb->prefix;

        $report = $wpdb->get_row( $wpdb->prepare(
            "SELECT report_no, report_date, part_lines FROM {$pre}svc_reports WHERE id=%d", $report_id
        ), ARRAY_A );
        if ( ! $report || ! $report['part_lines'] ) return;

        $lines = json_decode( $report['part_lines'], true ) ?: [];
        $items = [];
        foreach ( $lines as $line ) {
            $pid = (int) ( $line['product_id'] ?? 0 );
            $qty = (float) ( $line['qty'] ?? 0 );
            if ( $pid <= 0 || $qty <= 0 ) continue;
            $items[] = [
                'inv_product_id' => $pid,
                'quantity'       => $qty,
                'unit_price'     => (float) ( $line['unit_price'] ?? 0 ),
                'description'    => $line['name'] ?? '',
                'costing_method' => 'avg',
                'tracking'       => 'none',
            ];
        }
        if ( empty( $items ) ) return;

        self::_create_voucher_and_update_stock(
            'sale_issue',
            'service_report',
            $report_id,
            $report['report_no'],
            $report['report_date'] ?: current_time( 'Y-m-d' ),
            "خروج قطعات — گزارش {$report['report_no']}",
            $warehouse_id,
            null,
            $items
        );
    }

    /* ── توابع موجودی (کپی از Inventory_Controller) ──────────── */

    private static function _increase_stock( int $pid, int $wid, float $qty, float $cost, string $method, int $item_id ): void {
        global $wpdb;
        $pre = $wpdb->prefix;

        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT qty, avg_cost FROM {$pre}inv_stock WHERE product_id=%d AND warehouse_id=%d", $pid, $wid
        ), ARRAY_A );

        if ( $row ) {
            if ( $method === 'avg' ) {
                $new_qty  = (float)$row['qty'] + $qty;
                $new_cost = $new_qty > 0
                    ? ( (float)$row['qty'] * (float)$row['avg_cost'] + $qty * $cost ) / $new_qty
                    : $cost;
                $wpdb->update( "{$pre}inv_stock", ['qty' => $new_qty, 'avg_cost' => $new_cost], ['product_id' => $pid, 'warehouse_id' => $wid] );
            } else {
                $wpdb->update( "{$pre}inv_stock", ['qty' => (float)$row['qty'] + $qty], ['product_id' => $pid, 'warehouse_id' => $wid] );
            }
        } else {
            $wpdb->insert( "{$pre}inv_stock", ['product_id' => $pid, 'warehouse_id' => $wid, 'qty' => $qty, 'avg_cost' => $cost] );
        }

        if ( $method === 'fifo' ) {
            $wpdb->insert( "{$pre}inv_fifo_layers", [
                'product_id'      => $pid,
                'warehouse_id'    => $wid,
                'voucher_item_id' => $item_id,
                'qty_original'    => $qty,
                'qty_remaining'   => $qty,
                'unit_cost'       => $cost,
            ] );
        }
    }

    private static function _decrease_stock( int $pid, int $wid, float $qty, string $method, int $item_id ): void {
        global $wpdb;
        $pre = $wpdb->prefix;

        $wpdb->query( $wpdb->prepare(
            "UPDATE {$pre}inv_stock SET qty = qty - %f WHERE product_id=%d AND warehouse_id=%d",
            $qty, $pid, $wid
        ) );

        if ( $method === 'fifo' ) {
            $remaining = $qty;
            $layers = $wpdb->get_results( $wpdb->prepare(
                "SELECT id, qty_remaining FROM {$pre}inv_fifo_layers
                 WHERE product_id=%d AND warehouse_id=%d AND qty_remaining > 0
                 ORDER BY id ASC", $pid, $wid
            ), ARRAY_A );
            foreach ( $layers as $layer ) {
                if ( $remaining <= 0 ) break;
                $consume = min( $remaining, (float)$layer['qty_remaining'] );
                $wpdb->update( "{$pre}inv_fifo_layers",
                    ['qty_remaining' => (float)$layer['qty_remaining'] - $consume],
                    ['id' => $layer['id']]
                );
                $remaining -= $consume;
            }
        }
    }

    private static function _get_avg_cost( int $pid ): float {
        global $wpdb;
        return (float)( $wpdb->get_var( $wpdb->prepare(
            "SELECT avg_cost FROM {$wpdb->prefix}inv_stock WHERE product_id=%d AND qty>0 ORDER BY qty DESC LIMIT 1", $pid
        ) ) ?? 0 );
    }
}
