<?php
/* =====================================================
   File: /home/jewellersbd/public_html/erp.jewellersbd.com/api/barcode/delete_barcode_item.php
   Purpose: Barcode item safe delete / void
   Data change: YES
   Safety:
   - NO ALTER / CREATE / DROP
   - status enum touch করবে না
   - is_deleted=1 soft delete করবে
   - sold + valid weight barcode delete block
   - 0g problem barcode void allow
   - pending/in_transit transfer item delete block
   - 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';

function out_json($code, $success, $message, $data = null) {
    http_response_code($code);
    echo json_encode([
        'success' => (bool)$success,
        'status'  => (bool)$success,
        'message' => $message,
        '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()) {
    out_json(401, false, 'লগইন প্রয়োজন');
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    out_json(405, false, 'শুধু POST অনুরোধ গ্রহণযোগ্য');
}

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

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

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

function qi($name) {
    return '`' . str_replace('`', '', clean_name($name)) . '`';
}

function table_exists(PDO $pdo, $table) {
    $table = clean_name($table);
    if ($table === '') return false;

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

function get_columns(PDO $pdo, $table) {
    $table = clean_name($table);
    if ($table === '' || !table_exists($pdo, $table)) return [];

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

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

    return $cols;
}

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

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

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

function current_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 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 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 barcode_weight($row) {
    $w = first_float($row, [
        'gross_weight_gram',
        'gross_weight',
        'weight_gram',
        'total_weight_gram',
        'net_weight',
        'weight'
    ], 0);

    if ($w <= 0) {
        $w = gram_from_parts(
            first_float($row, ['vori', 'bhori'], 0),
            first_float($row, ['ana', 'aana'], 0),
            first_float($row, ['roti', 'rati'], 0),
            first_float($row, ['point', 'points'], 0)
        );
    }

    return round((float)$w, 3);
}

function is_sold_status($status) {
    $s = mb_strtolower(trim((string)$status), 'UTF-8');

    return in_array($s, [
        'sold',
        'sell',
        'sold_out',
        'sale_done',
        'বিক্রি',
        'বিক্রিত',
        'বিক্রি হয়েছে',
        'বিক্রি হয়েছে'
    ], true);
}

function is_transfer_busy($status) {
    $s = mb_strtolower(trim((string)$status), 'UTF-8');

    return in_array($s, [
        'pending',
        'in_transit',
        'transfer',
        'transferring'
    ], true);
}

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

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

        $cols = 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[] = 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', json_text($oldValues));
        }

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

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

        if (isset($cols['changed_at'])) {
            $fields[] = qi('changed_at');
            $marks[] = 'NOW()';
        } elseif (isset($cols['created_at'])) {
            $fields[] = 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 হলেও delete operation fail করা হবে না
    }
}

function find_barcode_for_update(PDO $pdo, $data, $cols, $idCol) {
    $id = (int)first_value($data, ['id', 'barcode_id', 'barcode_stock_id', 'item_id'], 0);

    if ($id > 0) {
        $st = $pdo->prepare("SELECT * FROM `barcode_stock` WHERE " . qi($idCol) . " = ? LIMIT 1 FOR UPDATE");
        $st->execute([$id]);
        $r = $st->fetch(PDO::FETCH_ASSOC);
        if ($r) return $r;
    }

    $code = trim((string)first_value($data, ['barcode_no', 'barcode', 'barcode_code', 'code'], ''));

    if ($code !== '') {
        foreach (['barcode_no', 'barcode', 'barcode_code'] as $c) {
            if (isset($cols[$c])) {
                $st = $pdo->prepare("SELECT * FROM `barcode_stock` WHERE " . qi($c) . " = ? LIMIT 1 FOR UPDATE");
                $st->execute([$code]);
                $r = $st->fetch(PDO::FETCH_ASSOC);
                if ($r) return $r;
            }
        }
    }

    return null;
}

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

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

    $userId = current_user_id();

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

    if (!table_exists($pdo, 'barcode_stock')) {
        out_json(500, false, 'barcode_stock table পাওয়া যায়নি');
    }

    $cols = get_columns($pdo, 'barcode_stock');
    $idCol = pick_col($cols, ['id', 'barcode_stock_id', 'barcode_id']);

    if (!$idCol) {
        out_json(500, false, 'barcode_stock ID column পাওয়া যায়নি');
    }

    if (!isset($cols['is_deleted'])) {
        out_json(500, false, 'barcode_stock.is_deleted column পাওয়া যায়নি — live DB structure check দরকার');
    }

    $pdo->beginTransaction();

    $barcode = find_barcode_for_update($pdo, $raw, $cols, $idCol);

    if (!$barcode) {
        $pdo->rollBack();
        out_json(404, false, 'বারকোড আইটেম পাওয়া যায়নি');
    }

    $id = (int)$barcode[$idCol];

    $barcodeNo = trim((string)first_value($barcode, ['barcode_no', 'barcode', 'barcode_code'], ''));
    $status = (string)first_value($barcode, ['status'], 'in_stock');
    $weight = barcode_weight($barcode);

    if ((int)($barcode['is_deleted'] ?? 0) === 1) {
        $pdo->rollBack();
        out_json(200, true, 'বারকোড আগে থেকেই delete/void করা আছে', [
            'id' => $id,
            'barcode_no' => $barcodeNo,
            'is_deleted' => 1
        ]);
    }

    if (isset($cols['transfer_status']) && is_transfer_busy($barcode['transfer_status'] ?? '')) {
        $pdo->rollBack();
        out_json(400, false, 'এই বারকোড transfer pending/in_transit আছে, delete করা যাবে না', [
            'id' => $id,
            'barcode_no' => $barcodeNo,
            'transfer_status' => $barcode['transfer_status'] ?? ''
        ]);
    }

    $soldByFlag = false;

    if (is_sold_status($status)) {
        $soldByFlag = true;
    }

    if (isset($cols['sale_id']) && (int)($barcode['sale_id'] ?? 0) > 0) {
        $soldByFlag = true;
    }

    if (isset($cols['sold_at']) && !empty($barcode['sold_at']) && $barcode['sold_at'] !== '0000-00-00 00:00:00') {
        $soldByFlag = true;
    }

    if (isset($cols['sold_invoice_no']) && trim((string)($barcode['sold_invoice_no'] ?? '')) !== '') {
        $soldByFlag = true;
    }

    /*
       Rule:
       - Sold + valid weight barcode delete block
       - Sold + 0g problem barcode void allow
       - Unsold barcode soft delete allow
    */
    if ($soldByFlag && $weight > 0) {
        $pdo->rollBack();
        out_json(400, false, 'বিক্রি হওয়া সঠিক বারকোড delete করা যাবে না', [
            'id' => $id,
            'barcode_no' => $barcodeNo,
            'weight' => $weight,
            'status' => $status
        ]);
    }

    $reason = trim((string)first_value($raw, ['reason', 'note', 'delete_note'], ''));
    if ($reason === '') {
        $reason = 'Deleted/Void from barcode stock';
    }

    if (mb_strlen($reason, 'UTF-8') > 500) {
        $pdo->rollBack();
        out_json(400, false, 'Delete note 500 অক্ষরের বেশি হতে পারবে না');
    }

    $set = [];
    $params = [];

    $set[] = "`is_deleted` = ?";
    $params[] = 1;

    if (isset($cols['deleted_at'])) {
        $set[] = "`deleted_at` = NOW()";
    }

    if (isset($cols['deleted_by'])) {
        $set[] = "`deleted_by` = ?";
        $params[] = $userId;
    }

    if (isset($cols['delete_note'])) {
        $set[] = "`delete_note` = ?";
        $params[] = $reason;
    }

    if (isset($cols['updated_at'])) {
        $set[] = "`updated_at` = NOW()";
    }

    if (isset($cols['note'])) {
        $oldNote = trim((string)($barcode['note'] ?? ''));
        $newNote = trim($oldNote . "\nDeleted/Void: " . date('Y-m-d H:i:s') . " | " . $reason);
        $set[] = "`note` = ?";
        $params[] = $newNote;
    }

    $params[] = $id;

    $updSql = "
        UPDATE `barcode_stock`
        SET " . implode(', ', $set) . "
        WHERE " . qi($idCol) . " = ?
          AND (`is_deleted` IS NULL OR `is_deleted` = 0)
    ";

    $upd = $pdo->prepare($updSql);
    $upd->execute($params);

    if ($upd->rowCount() !== 1) {
        throw new Exception('Barcode delete update failed');
    }

    add_audit_log(
        $pdo,
        'barcode_stock',
        $id,
        'DELETE_VOID',
        $userId,
        [
            'id' => $id,
            'barcode_no' => $barcodeNo,
            'status' => $status,
            'weight' => $weight,
            'is_deleted' => 0
        ],
        [
            'id' => $id,
            'barcode_no' => $barcodeNo,
            'is_deleted' => 1,
            'reason' => $reason
        ],
        'Barcode stock soft deleted/voided | ' . $barcodeNo
    );

    $pdo->commit();

    out_json(200, true, 'বারকোড delete/void হয়েছে', [
        'id' => $id,
        'barcode_no' => $barcodeNo,
        'is_deleted' => 1,
        'weight' => $weight
    ]);

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

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