<?php
/*
  cPanel path: /home/jewellersbd/public_html/erp.jewellersbd.com/api/new_stock/add_stock.php
  Purpose: New Stock / Old Purchase Stock add API
  Data change: YES

  Safety:
  - NO ALTER / CREATE / DROP
  - transaction ব্যবহার
  - stock insert + optional cash OUT entry একসাথে
  - cash entry fail হলে stock insert rollback
  - active location validation
  - supplier/cash account validation
  - audit_log থাকলে entry করবে
*/

ini_set('display_errors', 0);
ini_set('precision', '14');
ini_set('serialize_precision', '-1');
error_reporting(E_ALL);
header('Content-Type: application/json; charset=utf-8');

require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/db.php';

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

function nsa_out($code, $ok, $msg, $data = null) {
    http_response_code($code);
    echo json_encode([
        'success' => (bool)$ok,
        'status'  => (bool)$ok,
        'message' => $msg,
        'data'    => $data
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if (function_exists('require_login')) {
    require_login();
} elseif (function_exists('is_logged_in') && !is_logged_in()) {
    nsa_out(401, false, 'লগইন প্রয়োজন');
} elseif (empty($_SESSION['user_id']) && empty($_SESSION['user']['id'])) {
    nsa_out(401, false, 'লগইন প্রয়োজন');
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    nsa_out(405, false, 'শুধু POST অনুমোদিত');
}

if (!isset($pdo) || !($pdo instanceof PDO)) {
    nsa_out(500, false, 'PDO DB connection পাওয়া যায়নি');
}

try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->exec("SET NAMES utf8mb4");
} catch (Throwable $e) {
    nsa_out(500, false, 'ডাটাবেজ কানেকশন সমস্যা');
}

function nsa_clean($name) {
    return preg_replace('/[^a-zA-Z0-9_]/', '', (string)$name);
}

function nsa_qi($name) {
    return '`' . str_replace('`', '', nsa_clean($name)) . '`';
}

function nsa_table_exists(PDO $pdo, $table) {
    $table = nsa_clean($table);
    if ($table === '') return false;

    $st = $pdo->query("SHOW TABLES LIKE " . $pdo->quote($table));
    return (bool)$st->fetchColumn();
}

function nsa_get_columns(PDO $pdo, $table) {
    $table = nsa_clean($table);
    if ($table === '' || !nsa_table_exists($pdo, $table)) return [];

    $rows = $pdo->query("SHOW COLUMNS FROM " . nsa_qi($table))->fetchAll(PDO::FETCH_ASSOC);
    $cols = [];

    foreach ($rows as $r) {
        if (isset($r['Field'])) {
            $cols[$r['Field']] = true;
        }
    }

    return $cols;
}

function nsa_pick_col($cols, $names) {
    foreach ($names as $n) {
        if (isset($cols[$n])) return $n;
    }
    return null;
}

function nsa_first_value($arr, $keys, $default = '') {
    foreach ($keys as $k) {
        if (array_key_exists($k, $arr) && $arr[$k] !== null && $arr[$k] !== '') {
            return $arr[$k];
        }
    }
    return $default;
}

function nsa_first_float($arr, $keys, $default = 0) {
    foreach ($keys as $k) {
        if (array_key_exists($k, $arr) && $arr[$k] !== null && $arr[$k] !== '') {
            return (float)$arr[$k];
        }
    }
    return (float)$default;
}

function nsa_first_int($arr, $keys, $default = 0) {
    foreach ($keys as $k) {
        if (array_key_exists($k, $arr) && $arr[$k] !== null && $arr[$k] !== '') {
            return (int)$arr[$k];
        }
    }
    return (int)$default;
}

function nsa_user_id() {
    foreach (['user_id', 'id', 'auth_user_id'] as $k) {
        if (isset($_SESSION[$k]) && (int)$_SESSION[$k] > 0) {
            return (int)$_SESSION[$k];
        }
    }

    if (isset($_SESSION['user']) && is_array($_SESSION['user'])) {
        foreach (['id', 'user_id'] as $k) {
            if (isset($_SESSION['user'][$k]) && (int)$_SESSION['user'][$k] > 0) {
                return (int)$_SESSION['user'][$k];
            }
        }
    }

    return 0;
}

function nsa_client_ip() {
    foreach (['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'] as $k) {
        if (!empty($_SERVER[$k])) {
            $v = trim((string)$_SERVER[$k]);
            if ($k === 'HTTP_X_FORWARDED_FOR') {
                $parts = explode(',', $v);
                return trim($parts[0]);
            }
            return $v;
        }
    }
    return '';
}

function nsa_valid_date($d) {
    return is_string($d) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $d);
}

function nsa_gram_from_parts($vori, $ana, $roti, $point) {
    $VORI = 11.664;

    return round(
        ((float)$vori * $VORI) +
        ((float)$ana * ($VORI / 16)) +
        ((float)$roti * ($VORI / 96)) +
        ((float)$point * ($VORI / 960)),
        3
    );
}

function nsa_gram_to_parts($gram) {
    $VORI = 11.664;
    $totalPoint = (int)round(((float)$gram / $VORI) * 960);

    $vori = intdiv($totalPoint, 960);
    $totalPoint %= 960;

    $ana = intdiv($totalPoint, 60);
    $totalPoint %= 60;

    $roti = intdiv($totalPoint, 10);
    $point = $totalPoint % 10;

    return [
        'vori'  => $vori,
        'ana'   => $ana,
        'roti'  => $roti,
        'rati'  => $roti,
        'point' => $point
    ];
}

function nsa_purity_percent($karat, $fallback = 91.667) {
    $k = strtoupper(trim((string)$karat));

    $map = [
        '24K' => 100,
        '22K' => 91.667,
        '21K' => 87.5,
        '18K' => 75
    ];

    return $map[$k] ?? $fallback;
}

function nsa_json_text($value) {
    return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}

function nsa_audit(PDO $pdo, $tableName, $recordId, $action, $userId, $oldValues, $newValues, $note) {
    try {
        if (!nsa_table_exists($pdo, 'audit_log')) return;

        $cols = nsa_get_columns($pdo, 'audit_log');
        if (empty($cols)) return;

        $fields = [];
        $marks = [];
        $params = [];

        $add = function($col, $val) use (&$fields, &$marks, &$params, $cols) {
            if (isset($cols[$col])) {
                $fields[] = nsa_qi($col);
                $marks[] = '?';
                $params[] = $val;
            }
        };

        $add('table_name', $tableName);
        $add('record_id', (int)$recordId);
        $add('action', strtoupper((string)$action));

        if (isset($cols['changed_by'])) {
            $add('changed_by', (int)$userId);
        } elseif (isset($cols['user_id'])) {
            $add('user_id', (int)$userId);
        }

        if (isset($cols['old_values'])) {
            $add('old_values', nsa_json_text($oldValues));
        }

        if (isset($cols['new_values'])) {
            $add('new_values', nsa_json_text($newValues));
        }

        $add('ip_address', nsa_client_ip());
        $add('note', $note);

        if (isset($cols['changed_at'])) {
            $fields[] = nsa_qi('changed_at');
            $marks[] = 'NOW()';
        } elseif (isset($cols['created_at'])) {
            $fields[] = nsa_qi('created_at');
            $marks[] = 'NOW()';
        }

        if (empty($fields)) return;

        $sql = "INSERT INTO `audit_log` (" . implode(',', $fields) . ") VALUES (" . implode(',', $marks) . ")";
        $st = $pdo->prepare($sql);
        $st->execute($params);

    } catch (Throwable $e) {
        // audit fail হলেও main operation fail হবে না
    }
}

function nsa_find_cash_category_id(PDO $pdo) {
    if (!nsa_table_exists($pdo, 'cash_categories')) return 0;

    $cols = nsa_get_columns($pdo, 'cash_categories');
    if (!isset($cols['id'])) return 0;

    $whereParts = [];
    $params = [];

    if (isset($cols['category_code'])) {
        $whereParts[] = "`category_code` = ?";
        $params[] = 'PURCHASE_PAYMENT';
    }

    if (isset($cols['code'])) {
        $whereParts[] = "`code` = ?";
        $params[] = 'PURCHASE_PAYMENT';
    }

    if (isset($cols['name'])) {
        $whereParts[] = "`name` LIKE ?";
        $params[] = '%purchase%';
    }

    if (empty($whereParts)) return 0;

    $sql = "SELECT `id` FROM `cash_categories` WHERE " . implode(" OR ", $whereParts) . " LIMIT 1";
    $st = $pdo->prepare($sql);
    $st->execute($params);

    return (int)$st->fetchColumn();
}

function nsa_insert_cash_out(PDO $pdo, $cashAccountId, $amount, $date, $note, $referenceId, $userId) {
    if ($cashAccountId <= 0 || $amount <= 0) {
        return ['cash_recorded' => false, 'cash_transaction_id' => 0];
    }

    if (!nsa_table_exists($pdo, 'cash_accounts')) {
        throw new RuntimeException('cash_accounts table পাওয়া যায়নি');
    }

    if (!nsa_table_exists($pdo, 'cash_transactions')) {
        throw new RuntimeException('cash_transactions table পাওয়া যায়নি');
    }

    $accCols = nsa_get_columns($pdo, 'cash_accounts');
    if (!isset($accCols['id'])) {
        throw new RuntimeException('cash_accounts.id column পাওয়া যায়নি');
    }

    $accWhere = "`id` = ?";
    if (isset($accCols['is_active'])) {
        $accWhere .= " AND (`is_active` IS NULL OR `is_active` = 1)";
    }
    if (isset($accCols['deleted_at'])) {
        $accWhere .= " AND `deleted_at` IS NULL";
    }

    $accQ = $pdo->prepare("SELECT COUNT(*) FROM `cash_accounts` WHERE {$accWhere}");
    $accQ->execute([$cashAccountId]);
    if ((int)$accQ->fetchColumn() !== 1) {
        throw new RuntimeException('সঠিক active cash account বাছাই করুন');
    }

    $catId = nsa_find_cash_category_id($pdo);

    if (function_exists('gs_insert_cash_transaction')) {
        gs_insert_cash_transaction($pdo, [
            'category_id'      => $catId > 0 ? $catId : null,
            'cash_account_id'  => $cashAccountId,
            'amount'           => $amount,
            'transaction_date' => $date,
            'note'             => $note,
            'reference_type'   => 'new_stock',
            'reference_id'     => $referenceId,
            'created_by'       => $userId
        ]);

        if (function_exists('gs_recalc_cash_account')) {
            gs_recalc_cash_account($pdo, $cashAccountId);
        }

        return ['cash_recorded' => true, 'cash_transaction_id' => 0];
    }

    $ctCols = nsa_get_columns($pdo, 'cash_transactions');

    $fields = [];
    $marks = [];
    $params = [];

    $add = function($col, $val) use (&$fields, &$marks, &$params, $ctCols) {
        if (isset($ctCols[$col])) {
            $fields[] = nsa_qi($col);
            $marks[] = '?';
            $params[] = $val;
        }
    };

    $addRaw = function($col, $expr) use (&$fields, &$marks, $ctCols) {
        if (isset($ctCols[$col])) {
            $fields[] = nsa_qi($col);
            $marks[] = $expr;
        }
    };

    if (isset($ctCols['cash_account_id'])) {
        $add('cash_account_id', $cashAccountId);
    } elseif (isset($ctCols['account_id'])) {
        $add('account_id', $cashAccountId);
    }

    if (isset($ctCols['category_id'])) {
        if ($catId <= 0) {
            throw new RuntimeException('PURCHASE_PAYMENT cash category পাওয়া যায়নি');
        }
        $add('category_id', $catId);
    }

    $add('direction', 'OUT');
    $add('transaction_type', 'OUT');
    $add('type', 'OUT');

    $add('amount', $amount);

    if (isset($ctCols['transaction_date'])) {
        $add('transaction_date', $date);
    } elseif (isset($ctCols['date'])) {
        $add('date', $date);
    }

    $add('note', $note);
    $add('description', $note);
    $add('remarks', $note);

    $add('reference_type', 'new_stock');
    $add('ref_type', 'new_stock');
    $add('source_type', 'new_stock');

    $add('reference_id', $referenceId);
    $add('ref_id', $referenceId);
    $add('source_id', $referenceId);

    $add('created_by', $userId);
    $add('user_id', $userId);

    if (isset($ctCols['is_deleted'])) {
        $add('is_deleted', 0);
    }

    $addRaw('created_at', 'NOW()');
    $addRaw('updated_at', 'NOW()');

    if (empty($fields)) {
        throw new RuntimeException('cash_transactions insert করার মতো column পাওয়া যায়নি');
    }

    $sql = "INSERT INTO `cash_transactions` (" . implode(',', $fields) . ") VALUES (" . implode(',', $marks) . ")";
    $st = $pdo->prepare($sql);
    $st->execute($params);

    $cashTransactionId = (int)$pdo->lastInsertId();

    $balanceCol = nsa_pick_col($accCols, ['current_balance', 'balance']);
    if ($balanceCol) {
        $upd = $pdo->prepare("
            UPDATE `cash_accounts`
            SET " . nsa_qi($balanceCol) . " = COALESCE(" . nsa_qi($balanceCol) . ",0) - ?
            WHERE `id` = ?
        ");
        $upd->execute([$amount, $cashAccountId]);
    }

    nsa_audit(
        $pdo,
        'cash_transactions',
        $cashTransactionId,
        'INSERT',
        $userId,
        null,
        [
            'cash_account_id' => $cashAccountId,
            'amount' => $amount,
            'direction' => 'OUT',
            'reference_type' => 'new_stock',
            'reference_id' => $referenceId
        ],
        'New stock purchase payment cash OUT'
    );

    return ['cash_recorded' => true, 'cash_transaction_id' => $cashTransactionId];
}

try {
    $raw = json_decode(file_get_contents('php://input'), true);
    if (!is_array($raw)) {
        $raw = $_POST;
    }

    if (!is_array($raw)) {
        nsa_out(400, false, 'ভুল JSON data');
    }

    $userId = nsa_user_id();
    if ($userId <= 0) {
        nsa_out(401, false, 'Login session পাওয়া যায়নি');
    }

    if (!nsa_table_exists($pdo, 'new_stock')) {
        nsa_out(500, false, 'new_stock table পাওয়া যায়নি');
    }

    $cols = nsa_get_columns($pdo, 'new_stock');

    $stockDate = trim((string)nsa_first_value($raw, ['stock_date', 'purchase_date', 'date'], date('Y-m-d')));
    if (!nsa_valid_date($stockDate)) {
        nsa_out(400, false, 'সঠিক তারিখ দিন');
    }

    $itemName = trim((string)nsa_first_value($raw, ['item_name', 'product_name', 'name', 'category'], ''));
    if ($itemName === '') {
        nsa_out(400, false, 'আইটেমের নাম দিন');
    }
    if (mb_strlen($itemName, 'UTF-8') > 255) {
        nsa_out(400, false, 'আইটেমের নাম 255 অক্ষরের বেশি হতে পারবে না');
    }

    $category = trim((string)nsa_first_value($raw, ['category'], $itemName));
    if ($category === '') $category = $itemName;

    $invoiceNo = trim((string)nsa_first_value($raw, ['invoice_no', 'invoice', 'voucher_no'], ''));

    $supplierId = nsa_first_int($raw, ['supplier_id', 'party_id'], 0);
    $karat = trim((string)nsa_first_value($raw, ['karat', 'purity'], '22K'));

    $totalPcs = nsa_first_int($raw, ['total_pcs', 'total_pieces', 'pcs', 'quantity', 'qty'], 1);
    if ($totalPcs <= 0) $totalPcs = 1;
    if ($totalPcs > 100000) {
        nsa_out(400, false, 'পিস সংখ্যা অস্বাভাবিক বড়');
    }

    $vori  = nsa_first_float($raw, ['vori', 'bhori'], 0);
    $ana   = nsa_first_float($raw, ['ana', 'aana'], 0);
    $roti  = nsa_first_float($raw, ['roti', 'rati'], 0);
    $point = nsa_first_float($raw, ['point', 'points'], 0);

    $totalWeight = nsa_first_float($raw, [
        'total_weight_gram',
        'gross_weight_gram',
        'weight_gram',
        'weight'
    ], 0);

    if ($totalWeight <= 0) {
        $totalWeight = nsa_gram_from_parts($vori, $ana, $roti, $point);
    }

    if ($totalWeight <= 0) {
        nsa_out(400, false, 'ওজন দিন');
    }

    if ($totalWeight > 100000) {
        nsa_out(400, false, 'ওজন অস্বাভাবিক বড়, আবার চেক করুন');
    }

    if ($vori <= 0 && $ana <= 0 && $roti <= 0 && $point <= 0) {
        $parts = nsa_gram_to_parts($totalWeight);
        $vori  = $parts['vori'];
        $ana   = $parts['ana'];
        $roti  = $parts['roti'];
        $point = $parts['point'];
    }

    $purityPercent = nsa_first_float($raw, ['purity_percent', 'actual_purity', 'system_purity'], nsa_purity_percent($karat));
    if ($purityPercent <= 0) {
        $purityPercent = nsa_purity_percent($karat);
    }
    if ($purityPercent > 100) {
        nsa_out(400, false, 'Purity 100% এর বেশি হতে পারবে না');
    }

    $pureWeight = nsa_first_float($raw, ['pure_weight_gram', 'pure_weight', 'pure_gold_gram'], 0);
    if ($pureWeight <= 0) {
        $pureWeight = round($totalWeight * ($purityPercent / 100), 3);
    }

    $locationId = nsa_first_int($raw, ['location_id', 'stock_location_id'], 1);
    if ($locationId <= 0) $locationId = 1;

    $ratePerVori = nsa_first_float($raw, ['rate_per_vori'], 0);
    $totalAmount = nsa_first_float($raw, ['total_amount', 'amount'], 0);

    $paymentMethodId = nsa_first_int($raw, ['payment_method_id', 'payment_id'], 0);
    $cashAccountId   = nsa_first_int($raw, ['cash_account_id', 'account_id'], 0);

    $note = trim((string)nsa_first_value($raw, ['note', 'remarks'], ''));
    if (mb_strlen($note, 'UTF-8') > 2000) {
        nsa_out(400, false, 'নোট 2000 অক্ষরের বেশি হতে পারবে না');
    }

    if ($supplierId > 0 && nsa_table_exists($pdo, 'parties')) {
        $partyCols = nsa_get_columns($pdo, 'parties');
        if (isset($partyCols['id'])) {
            $pq = $pdo->prepare("SELECT COUNT(*) FROM `parties` WHERE `id` = ?");
            $pq->execute([$supplierId]);
            if ((int)$pq->fetchColumn() !== 1) {
                nsa_out(400, false, 'Supplier/Party পাওয়া যায়নি');
            }
        }
    }

    if ($locationId > 0 && nsa_table_exists($pdo, 'stock_locations')) {
        $locCols = nsa_get_columns($pdo, 'stock_locations');
        if (isset($locCols['id'])) {
            $locWhere = "`id` = ?";
            if (isset($locCols['is_active'])) {
                $locWhere .= " AND (`is_active` IS NULL OR `is_active` = 1)";
            }
            $lq = $pdo->prepare("SELECT COUNT(*) FROM `stock_locations` WHERE {$locWhere}");
            $lq->execute([$locationId]);
            if ((int)$lq->fetchColumn() !== 1) {
                nsa_out(400, false, 'সঠিক active location বাছাই করুন');
            }
        }
    }

    $pdo->beginTransaction();

    $fields = [];
    $marks = [];
    $params = [];

    $add = function($col, $val) use (&$fields, &$marks, &$params, $cols) {
        if (isset($cols[$col])) {
            $fields[] = nsa_qi($col);
            $marks[] = '?';
            $params[] = $val;
        }
    };

    $addRaw = function($col, $expr) use (&$fields, &$marks, $cols) {
        if (isset($cols[$col])) {
            $fields[] = nsa_qi($col);
            $marks[] = $expr;
        }
    };

    $add('stock_date', $stockDate);
    $add('purchase_date', $stockDate);
    $add('date', $stockDate);

    $add('supplier_id', $supplierId > 0 ? $supplierId : null);
    $add('party_id', $supplierId > 0 ? $supplierId : null);

    $add('invoice_no', $invoiceNo !== '' ? $invoiceNo : null);
    $add('invoice', $invoiceNo !== '' ? $invoiceNo : null);
    $add('voucher_no', $invoiceNo !== '' ? $invoiceNo : null);

    $add('category', $category);
    $add('stock_type', $category);

    $add('product_name', $itemName);
    $add('item_name', $itemName);
    $add('name', $itemName);

    $add('karat', $karat);
    $add('purity', $karat);
    $add('purity_percent', round($purityPercent, 3));

    $add('total_pcs', $totalPcs);
    $add('total_pieces', $totalPcs);
    $add('pcs', $totalPcs);
    $add('quantity', $totalPcs);
    $add('qty', $totalPcs);

    $add('available_pcs', $totalPcs);
    $add('balance_pcs', $totalPcs);

    $add('vori', $vori);
    $add('bhori', $vori);
    $add('ana', $ana);
    $add('aana', $ana);
    $add('roti', $roti);
    $add('rati', $roti);
    $add('point', $point);
    $add('points', $point);

    $add('total_weight_gram', round($totalWeight, 3));
    $add('gross_weight_gram', round($totalWeight, 3));
    $add('weight_gram', round($totalWeight, 3));
    $add('weight', round($totalWeight, 3));

    $add('available_weight_gram', round($totalWeight, 3));
    $add('balance_weight_gram', round($totalWeight, 3));

    $add('pure_weight_gram', round($pureWeight, 3));
    $add('pure_weight', round($pureWeight, 3));
    $add('pure_gold_gram', round($pureWeight, 3));

    $add('rate_per_vori', $ratePerVori > 0 ? $ratePerVori : null);
    $add('total_amount', $totalAmount > 0 ? $totalAmount : null);

    $add('payment_method_id', $paymentMethodId > 0 ? $paymentMethodId : null);
    $add('payment_id', $paymentMethodId > 0 ? $paymentMethodId : null);

    $add('cash_account_id', $cashAccountId > 0 ? $cashAccountId : null);
    $add('account_id', $cashAccountId > 0 ? $cashAccountId : null);

    $add('location_id', $locationId);
    $add('stock_location_id', $locationId);

    $add('note', $note !== '' ? $note : null);
    $add('remarks', $note !== '' ? $note : null);

    $add('created_by', $userId);
    $add('user_id', $userId);

    $addRaw('created_at', 'NOW()');
    $addRaw('updated_at', 'NOW()');

    if (empty($fields)) {
        throw new RuntimeException('new_stock insert করার মতো column পাওয়া যায়নি');
    }

    $sql = "INSERT INTO `new_stock` (" . implode(',', $fields) . ") VALUES (" . implode(',', $marks) . ")";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);

    $stockId = (int)$pdo->lastInsertId();

    $cashResult = ['cash_recorded' => false, 'cash_transaction_id' => 0];

    if ($cashAccountId > 0 && $totalAmount > 0) {
        $cashResult = nsa_insert_cash_out(
            $pdo,
            $cashAccountId,
            $totalAmount,
            $stockDate,
            'নতুন স্টক ক্রয়: ' . $itemName,
            $stockId,
            $userId
        );
    }

    nsa_audit(
        $pdo,
        'new_stock',
        $stockId,
        'INSERT',
        $userId,
        null,
        [
            'id' => $stockId,
            'stock_date' => $stockDate,
            'item_name' => $itemName,
            'category' => $category,
            'karat' => $karat,
            'total_pcs' => $totalPcs,
            'total_weight_gram' => round($totalWeight, 3),
            'available_pcs' => $totalPcs,
            'available_weight_gram' => round($totalWeight, 3),
            'location_id' => $locationId,
            'supplier_id' => $supplierId,
            'total_amount' => $totalAmount
        ],
        'New stock created | ' . $itemName
    );

    $pdo->commit();

    nsa_out(200, true, '✅ স্টক সফলভাবে সেভ হয়েছে', [
        'id' => $stockId,
        'stock_id' => $stockId,
        'stock_date' => $stockDate,
        'item_name' => $itemName,
        'product_name' => $itemName,
        'category' => $category,
        'karat' => $karat,
        'total_pcs' => $totalPcs,
        'total_weight_gram' => round($totalWeight, 3),
        'pure_weight_gram' => round($pureWeight, 3),
        'available_pcs' => $totalPcs,
        'available_weight_gram' => round($totalWeight, 3),
        'location_id' => $locationId,
        'supplier_id' => $supplierId > 0 ? $supplierId : null,
        'rate_per_vori' => $ratePerVori > 0 ? $ratePerVori : null,
        'total_amount' => $totalAmount > 0 ? $totalAmount : null,
        'cash_recorded' => $cashResult['cash_recorded'],
        'cash_transaction_id' => $cashResult['cash_transaction_id']
    ]);

} catch (Throwable $e) {
    if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
        $pdo->rollBack();
    }

    nsa_out(500, false, 'সার্ভার সমস্যা: ' . $e->getMessage());
}