<?php
/**
 * import_opening_stock.php
 * Put this file in: /rooms/modules/inventory/import_opening_stock.php
 *
 * Purpose:
 * - Preserve all historical stock movements.
 * - Compare the current balance at the selected date with the imported quantity.
 * - Post only the required positive or negative correction.
 * - Items omitted from an imported location are adjusted down to zero.
 * - Matches items by Item Code first. If Item Code is blank, it can match by exact Item Name.
 * - Matches store/location by Store column, or by selected default store.
 *
 * CSV template headers:
 * Item Code, Item Name, Store, Opening Qty, Unit Cost, Notes
 */

require_once __DIR__ . '/../../includes/bootstrap.php';
require_login();

$pageTitle = 'Import Opening Stock';

if (!function_exists('h')) {
    function h($value): string { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('money_fmt')) {
    function money_fmt($amount): string { return number_format((float)$amount, 2); }
}
if (!function_exists('os_flash')) {
    function os_flash(string $type, string $message): void {
        $_SESSION['opening_stock_flash'][] = ['type' => $type, 'message' => $message];
    }
}
if (!function_exists('os_get_flash')) {
    function os_get_flash(): array {
        $items = $_SESSION['opening_stock_flash'] ?? [];
        unset($_SESSION['opening_stock_flash']);
        return $items;
    }
}
if (!function_exists('os_clean')) {
    function os_clean($value): string {
        $value = preg_replace('/^\xEF\xBB\xBF/', '', (string)$value);
        $value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $value = strip_tags($value);
        $value = preg_replace('/\s+/', ' ', $value);
        return trim((string)$value);
    }
}
if (!function_exists('os_to_number')) {
    function os_to_number($value): float {
        $value = os_clean($value);
        $value = str_replace([',', "\xc2\xa0", '$'], ['', '', ''], $value);
        if ($value === '' || $value === '-' || $value === '—') return 0.0;
        return is_numeric($value) ? (float)$value : 0.0;
    }
}
if (!function_exists('os_table_exists')) {
    function os_table_exists(PDO $pdo, string $table): bool {
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = :table_name");
        $stmt->execute([':table_name' => $table]);
        return (int)$stmt->fetchColumn() > 0;
    }
}
if (!function_exists('os_column_exists')) {
    function os_column_exists(PDO $pdo, string $table, string $column): bool {
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :table_name AND column_name = :column_name");
        $stmt->execute([':table_name' => $table, ':column_name' => $column]);
        return (int)$stmt->fetchColumn() > 0;
    }
}
if (!function_exists('os_read_csv_rows')) {
    function os_read_csv_rows(string $path): array {
        if (!is_file($path) || !is_readable($path)) {
            throw new RuntimeException('Uploaded CSV file could not be read.');
        }

        $raw = file_get_contents($path);
        if ($raw === false || trim($raw) === '') {
            throw new RuntimeException('Uploaded CSV file is empty.');
        }
        $raw = preg_replace('/^\xEF\xBB\xBF/', '', $raw);

        $firstLine = strtok($raw, "\r\n");
        $delimiter = ',';
        if (substr_count((string)$firstLine, "\t") > substr_count((string)$firstLine, ',')) $delimiter = "\t";
        if (substr_count((string)$firstLine, ';') > substr_count((string)$firstLine, $delimiter)) $delimiter = ';';

        $rows = [];
        $handle = fopen($path, 'rb');
        if (!$handle) throw new RuntimeException('Could not open uploaded CSV file.');

        while (($row = fgetcsv($handle, 0, $delimiter)) !== false) {
            $clean = array_map('os_clean', $row);
            if (!array_filter($clean, fn($v) => trim((string)$v) !== '')) continue;
            $rows[] = $clean;
        }
        fclose($handle);
        return $rows;
    }
}
if (!function_exists('os_recalc_avg_cost')) {
    function os_recalc_avg_cost(PDO $pdo, int $itemId): void {
        if (!os_table_exists($pdo, 'inventory_items')) return;
        if (!os_column_exists($pdo, 'inventory_items', 'avg_cost')) return;

        $stmt = $pdo->prepare("\n            SELECT\n                COALESCE(SUM(qty_in),0) AS qty,\n                COALESCE(SUM(qty_in * unit_cost),0) AS cost\n            FROM stock_movements\n            WHERE item_id = :item_id\n              AND qty_in > 0\n              AND movement_type IN ('OPENING','GRN','TRANSFER_IN','ADJUSTMENT_IN','RETURN')\n        ");
        $stmt->execute([':item_id' => $itemId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
        $qty = (float)($row['qty'] ?? 0);
        $cost = (float)($row['cost'] ?? 0);

        if ($qty > 0) {
            $stmt = $pdo->prepare("UPDATE inventory_items SET avg_cost = :avg_cost WHERE id = :id");
            $stmt->execute([':avg_cost' => $cost / $qty, ':id' => $itemId]);
        }
    }
}
if (!function_exists('os_normalize_header')) {
    function os_normalize_header(string $header): string {
        $h = strtolower(os_clean($header));
        $h = str_replace(['_', '-', '/', '.'], ' ', $h);
        $h = preg_replace('/\s+/', ' ', $h);
        return trim($h);
    }
}

$errors = [];
$previewRows = $_SESSION['opening_stock_import_preview'] ?? [];
unset($_SESSION['opening_stock_import_preview']);

try {
    foreach (['inventory_items', 'store_locations', 'stock_movements'] as $requiredTable) {
        if (!os_table_exists($pdo, $requiredTable)) {
            throw new RuntimeException('Missing required table: ' . $requiredTable . '. Please open Stock Take/Inventory setup first so tables are created.');
        }
    }
} catch (Throwable $e) {
    $errors[] = $e->getMessage();
}

$stores = [];
try {
    $stores = $pdo->query("SELECT id, location_code, location_name FROM store_locations WHERE is_active=1 ORDER BY location_name ASC")->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    $errors[] = 'Could not load store locations: ' . $e->getMessage();
}

function os_download_template(): void {
    $filename = 'opening_stock_import_template.csv';
    header('Content-Type: text/csv; charset=UTF-8');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Pragma: no-cache');
    header('Expires: 0');
    echo "\xEF\xBB\xBF";
    $out = fopen('php://output', 'wb');
    fputcsv($out, ['Item Code', 'Item Name', 'Store', 'Opening Qty', 'Unit Cost', 'Notes']);
    fputcsv($out, ['stk003', 'Absolut Vodka 750ml', 'Bar Bulk', '30', '0.6306', 'Opening stock import']);
    fputcsv($out, ['stk033', 'Amarula Cream 750ml', 'Bar Bulk', '125', '0.5178', 'Opening stock import']);
    fclose($out);
    exit;
}

if (($_GET['download'] ?? '') === 'template') {
    os_download_template();
}

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    try {
        if (function_exists('verify_csrf')) verify_csrf();

        $action = (string)($_POST['action'] ?? '');
        if ($action !== 'import_opening_stock') throw new RuntimeException('Invalid action.');

        if (empty($_FILES['opening_file']['tmp_name']) || !is_uploaded_file($_FILES['opening_file']['tmp_name'])) {
            throw new RuntimeException('Please choose the opening stock CSV file.');
        }

        $defaultStoreId = (int)($_POST['default_store_id'] ?? 0);
        $dryRun = !empty($_POST['dry_run']) ? 1 : 0;
        $movementDate = trim((string)($_POST['movement_date'] ?? date('Y-m-d')));
        if (strtotime($movementDate) === false) $movementDate = date('Y-m-d');
        $movementDateSql = date('Y-m-d 00:00:00', strtotime($movementDate));

        $rows = os_read_csv_rows((string)$_FILES['opening_file']['tmp_name']);
        if (!$rows) throw new RuntimeException('No rows found in the CSV file.');

        $headerIndex = null;
        $map = [];
        foreach ($rows as $idx => $row) {
            $normalized = array_map('os_normalize_header', $row);
            $possibleQty = ['opening qty', 'opening quantity', 'qty', 'quantity', 'stock on hand', 'counted qty', 'physical count'];
            $hasQty = false;
            foreach ($possibleQty as $q) {
                if (in_array($q, $normalized, true)) { $hasQty = true; break; }
            }
            if ((in_array('item code', $normalized, true) || in_array('item name', $normalized, true)) && $hasQty) {
                $headerIndex = $idx;
                foreach ($normalized as $colIdx => $name) {
                    if ($name === 'item code' || $name === 'code' || $name === 'sku') $map['item_code'] = $colIdx;
                    if ($name === 'item name' || $name === 'name' || $name === 'description') $map['item_name'] = $colIdx;
                    if ($name === 'store' || $name === 'storage' || $name === 'location' || $name === 'stockholding location') $map['store'] = $colIdx;
                    if (in_array($name, $possibleQty, true)) $map['opening_qty'] = $colIdx;
                    if ($name === 'unit cost' || $name === 'cost' || $name === 'cost price' || $name === 'avg cost') $map['unit_cost'] = $colIdx;
                    if ($name === 'notes' || $name === 'note') $map['notes'] = $colIdx;
                }
                break;
            }
        }

        if ($headerIndex === null || !isset($map['opening_qty'])) {
            throw new RuntimeException('CSV must contain headers: Item Code, Item Name, Store, Opening Qty, Unit Cost, Notes. Stock On Hand is also accepted as Opening Qty.');
        }

        $itemByCode = [];
        $itemByName = [];
        $stmt = $pdo->query("SELECT id, item_code, item_name, cost_price, avg_cost FROM inventory_items WHERE is_active=1");
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $item) {
            $code = strtoupper(trim((string)($item['item_code'] ?? '')));
            $name = strtoupper(trim((string)($item['item_name'] ?? '')));
            if ($code !== '') $itemByCode[$code] = $item;
            if ($name !== '') $itemByName[$name] = $item;
        }

        $storeByName = [];
        $storeByCode = [];
        $stmt = $pdo->query("SELECT id, location_code, location_name FROM store_locations WHERE is_active=1");
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $store) {
            $name = strtoupper(trim((string)($store['location_name'] ?? '')));
            $code = strtoupper(trim((string)($store['location_code'] ?? '')));
            if ($name !== '') $storeByName[$name] = $store;
            if ($code !== '') $storeByCode[$code] = $store;
        }

        $batchRef = 'OPENING-' . date('Ymd-His');
        $prepared = [];
        $skipped = [];

        for ($i = $headerIndex + 1; $i < count($rows); $i++) {
            $row = $rows[$i];
            if (!array_filter($row, fn($v) => trim((string)$v) !== '')) continue;

            $rowNo = $i + 1;
            $itemCode = isset($map['item_code']) ? strtoupper(trim((string)($row[$map['item_code']] ?? ''))) : '';
            $itemName = isset($map['item_name']) ? strtoupper(trim((string)($row[$map['item_name']] ?? ''))) : '';
            $storeText = isset($map['store']) ? strtoupper(trim((string)($row[$map['store']] ?? ''))) : '';
            $qty = os_to_number($row[$map['opening_qty']] ?? 0);
            $unitCost = isset($map['unit_cost']) ? os_to_number($row[$map['unit_cost']] ?? 0) : 0;
            $notes = isset($map['notes']) ? trim((string)($row[$map['notes']] ?? '')) : '';

            if ($qty < 0) {
                $skipped[] = ['row' => $rowNo, 'reason' => 'Opening Qty cannot be negative'];
                continue;
            }

            $item = null;
            if ($itemCode !== '' && isset($itemByCode[$itemCode])) $item = $itemByCode[$itemCode];
            if (!$item && $itemName !== '' && isset($itemByName[$itemName])) $item = $itemByName[$itemName];
            if (!$item) {
                $skipped[] = ['row' => $rowNo, 'reason' => 'Item not found by Item Code/Item Name'];
                continue;
            }

            $storeId = $defaultStoreId;
            $storeName = '';
            if ($storeText !== '') {
                if (isset($storeByName[$storeText])) {
                    $storeId = (int)$storeByName[$storeText]['id'];
                    $storeName = (string)$storeByName[$storeText]['location_name'];
                } elseif (isset($storeByCode[$storeText])) {
                    $storeId = (int)$storeByCode[$storeText]['id'];
                    $storeName = (string)$storeByCode[$storeText]['location_name'];
                } else {
                    $skipped[] = ['row' => $rowNo, 'reason' => 'Store/location not found: ' . $storeText];
                    continue;
                }
            } else {
                if ($storeId <= 0) {
                    $skipped[] = ['row' => $rowNo, 'reason' => 'Store is blank and no default store selected'];
                    continue;
                }
                foreach ($stores as $s) {
                    if ((int)$s['id'] === $storeId) { $storeName = (string)$s['location_name']; break; }
                }
            }

            if ($unitCost <= 0) {
                $unitCost = (float)($item['avg_cost'] ?? 0);
                if ($unitCost <= 0) $unitCost = (float)($item['cost_price'] ?? 0);
            }

            $prepared[] = [
                'row_no' => $rowNo,
                'item_id' => (int)$item['id'],
                'item_code' => (string)($item['item_code'] ?? ''),
                'item_name' => (string)($item['item_name'] ?? ''),
                'store_id' => $storeId,
                'store_name' => $storeName,
                'qty' => $qty,
                'unit_cost' => $unitCost,
                'total_cost' => $qty * $unitCost,
                'notes' => $notes,
            ];
        }

        if (!$prepared) {
            $_SESSION['opening_stock_import_preview'] = $skipped;
            throw new RuntimeException('No valid opening stock rows found. Check the skipped rows below.');
        }

        if ($dryRun) {
            $_SESSION['opening_stock_import_preview'] = array_merge(
                array_map(fn($r) => ['row' => $r['row_no'], 'reason' => 'OK: ' . $r['item_code'] . ' / ' . $r['store_name'] . ' / Qty ' . $r['qty'] . ' / Cost ' . $r['unit_cost']], $prepared),
                $skipped
            );
            os_flash('info', 'Preview complete. Valid rows: ' . count($prepared) . '. Skipped rows: ' . count($skipped) . '. Nothing was posted.');
            header('Location: import_opening_stock.php');
            exit;
        }

        /*
         * BALANCE CORRECTION MODE
         *
         * Historical movements are never deleted.
         * For each location represented in the CSV:
         *   desired balance = imported quantity, or zero when omitted
         *   current balance = SUM(qty_in - qty_out) up to the selected date
         *   correction      = desired balance - current balance
         *
         * Positive corrections are ADJUSTMENT_IN.
         * Negative corrections are ADJUSTMENT_OUT.
         */

        // The last CSV row wins when an item/store appears more than once.
        $preparedByKey = [];
        foreach ($prepared as $r) {
            $preparedByKey[$r['store_id'] . ':' . $r['item_id']] = $r;
        }
        $prepared = array_values($preparedByKey);

        $affectedStores = [];
        $desiredByStoreItem = [];
        foreach ($prepared as $r) {
            $storeId = (int)$r['store_id'];
            $itemId = (int)$r['item_id'];

            $affectedStores[$storeId] = (string)$r['store_name'];
            $desiredByStoreItem[$storeId][$itemId] = $r;
        }

        if (!$affectedStores) {
            throw new RuntimeException('No valid store/location was found in the import.');
        }

        $allItemsStmt = $pdo->query("
            SELECT id, item_code, item_name, cost_price, avg_cost
            FROM inventory_items
            WHERE is_active = 1
            ORDER BY id
        ");
        $allItems = $allItemsStmt->fetchAll(PDO::FETCH_ASSOC);

        $balanceStmt = $pdo->prepare("
            SELECT COALESCE(SUM(qty_in - qty_out), 0)
            FROM stock_movements
            WHERE item_id = :item_id
              AND store_id = :store_id
              AND movement_date <= :movement_date
        ");

        $insertCorrectionStmt = $pdo->prepare("
            INSERT INTO stock_movements
            (
                item_id, store_id, movement_type,
                qty_in, qty_out,
                unit_cost, total_cost,
                reference_type, reference_id,
                notes, movement_date
            )
            VALUES
            (
                :item_id, :store_id, :movement_type,
                :qty_in, :qty_out,
                :unit_cost, :total_cost,
                'OPENING_BALANCE_CORRECTION', NULL,
                :notes, :movement_date
            )
        ");

        $adjustmentInCount = 0;
        $adjustmentOutCount = 0;
        $unchangedCount = 0;
        $omittedZeroedCount = 0;
        $adjustmentValue = 0.0;
        $recalcItemIds = [];

        $pdo->beginTransaction();

        foreach ($affectedStores as $storeId => $storeName) {
            foreach ($allItems as $item) {
                $itemId = (int)$item['id'];

                $importedRow = $desiredByStoreItem[$storeId][$itemId] ?? null;
                $desiredQty = $importedRow !== null
                    ? (float)$importedRow['qty']
                    : 0.0;

                $balanceStmt->execute([
                    ':item_id' => $itemId,
                    ':store_id' => (int)$storeId,
                    ':movement_date' => $movementDateSql,
                ]);
                $currentQty = (float)$balanceStmt->fetchColumn();

                $difference = round($desiredQty - $currentQty, 4);

                if (abs($difference) < 0.0001) {
                    $unchangedCount++;
                    continue;
                }

                $unitCost = 0.0;
                if ($importedRow !== null) {
                    $unitCost = (float)$importedRow['unit_cost'];
                }
                if ($unitCost <= 0) {
                    $unitCost = (float)($item['avg_cost'] ?? 0);
                }
                if ($unitCost <= 0) {
                    $unitCost = (float)($item['cost_price'] ?? 0);
                }

                $movementType = $difference > 0
                    ? 'ADJUSTMENT_IN'
                    : 'ADJUSTMENT_OUT';

                $qtyIn = $difference > 0 ? $difference : 0.0;
                $qtyOut = $difference < 0 ? abs($difference) : 0.0;
                $totalCost = abs($difference) * $unitCost;

                $itemCode = trim((string)($item['item_code'] ?? ''));
                $itemName = trim((string)($item['item_name'] ?? ''));

                $noteParts = [
                    'Opening balance correction ' . $batchRef,
                    'Store: ' . $storeName,
                    'Item: ' . ($itemCode !== '' ? $itemCode . ' - ' : '') . $itemName,
                    'Previous balance: ' . number_format($currentQty, 4, '.', ''),
                    'Imported balance: ' . number_format($desiredQty, 4, '.', ''),
                    'Correction: ' . number_format($difference, 4, '.', ''),
                ];

                if ($importedRow === null) {
                    $noteParts[] = 'Item omitted from import; corrected to zero';
                    $omittedZeroedCount++;
                } elseif (trim((string)$importedRow['notes']) !== '') {
                    $noteParts[] = trim((string)$importedRow['notes']);
                }

                $insertCorrectionStmt->execute([
                    ':item_id' => $itemId,
                    ':store_id' => (int)$storeId,
                    ':movement_type' => $movementType,
                    ':qty_in' => $qtyIn,
                    ':qty_out' => $qtyOut,
                    ':unit_cost' => $unitCost,
                    ':total_cost' => $totalCost,
                    ':notes' => implode(' | ', $noteParts),
                    ':movement_date' => $movementDateSql,
                ]);

                if ($difference > 0) {
                    $adjustmentInCount++;
                } else {
                    $adjustmentOutCount++;
                }

                $adjustmentValue += $difference * $unitCost;
                $recalcItemIds[$itemId] = true;
            }
        }

        foreach (array_keys($recalcItemIds) as $itemId) {
            os_recalc_avg_cost($pdo, (int)$itemId);
        }

        $pdo->commit();

        $_SESSION['opening_stock_import_preview'] = $skipped;

        $storeLabels = array_values(array_filter(array_map('trim', array_values($affectedStores))));
        $storeSummary = $storeLabels
            ? implode(', ', $storeLabels)
            : count($affectedStores) . ' location(s)';

        os_flash(
            'success',
            'Opening balance correction completed for ' . $storeSummary . '. ' .
            'Positive corrections: ' . $adjustmentInCount . '. ' .
            'Negative corrections: ' . $adjustmentOutCount . '. ' .
            'Unchanged items: ' . $unchangedCount . '. ' .
            'Omitted items corrected to zero: ' . $omittedZeroedCount . '. ' .
            'Net correction value: ' . money_fmt($adjustmentValue) . '. ' .
            'All historical movements were preserved.' .
            (count($skipped) ? ' See skipped rows below.' : '')
        );

        header('Location: import_opening_stock.php');
        exit;

    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        os_flash('danger', $e->getMessage());
        header('Location: import_opening_stock.php');
        exit;
    }
}

$flashes = os_get_flash();

require_once __DIR__ . '/../../includes/header.php';
?>

<div class="hero-band">
    <div class="row g-4 align-items-center">
        <div class="col-lg-8">
            <div class="page-eyebrow text-white-50"><i class="bi bi-box-arrow-in-down"></i> Inventory Setup</div>
            <div class="hero-title mt-2">Import Opening Stock</div>
            <div class="hero-subtitle mt-2">Preserve history and post only the positive or negative correction required to match the imported balances.</div>
        </div>
        <div class="col-lg-4 text-lg-end">
            <a href="import_opening_stock.php?download=template" class="btn btn-light me-2">
                <i class="bi bi-download me-2"></i>CSV Template
            </a>
            <a href="stock_movements.php" class="btn btn-outline-light">
                <i class="bi bi-arrow-left-right me-2"></i>Movements
            </a>
        </div>
    </div>
</div>

<?php foreach ($flashes as $flash): ?>
    <div class="alert alert-<?php echo h($flash['type']); ?>"><?php echo h($flash['message']); ?></div>
<?php endforeach; ?>

<?php if ($errors): ?>
    <div class="alert alert-danger">
        <div class="fw-bold mb-2">Please fix the following:</div>
        <ul class="mb-0"><?php foreach ($errors as $err): ?><li><?php echo h($err); ?></li><?php endforeach; ?></ul>
    </div>
<?php endif; ?>

<div class="row g-4">
    <div class="col-xl-5">
        <div class="card panel-card">
            <div class="card-header"><h5 class="mb-0">Upload CSV</h5></div>
            <div class="card-body">
                <form method="post" enctype="multipart/form-data" onsubmit="return confirm('This will preserve history and post adjustment entries so each imported location matches the CSV. Items omitted from those locations will be adjusted to zero. Continue?');">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="import_opening_stock">

                    <div class="mb-3">
                        <label class="form-label">Opening Stock CSV</label>
                        <input type="file" name="opening_file" class="form-control" accept=".csv,.txt" required>
                        <div class="form-text">Save Excel as CSV before importing. Do not upload .xlsx here.</div>
                    </div>

                    <div class="mb-3">
                        <label class="form-label">Default Store/Location</label>
                        <select name="default_store_id" class="form-select">
                            <option value="0">Use Store column from CSV</option>
                            <?php foreach ($stores as $store): ?>
                                <option value="<?php echo (int)$store['id']; ?>">
                                    <?php echo h($store['location_name']); ?><?php echo $store['location_code'] ? ' (' . h($store['location_code']) . ')' : ''; ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">If the CSV Store column is blank, this selected store will be used.</div>
                    </div>

                    <div class="mb-3">
                        <label class="form-label">Opening Movement Date</label>
                        <input type="date" name="movement_date" class="form-control" value="<?php echo h(date('Y-m-d')); ?>">
                    </div>

                    <div class="form-check mb-2">
                        <input class="form-check-input" type="checkbox" value="1" name="dry_run" id="dry_run" checked>
                        <label class="form-check-label" for="dry_run">Preview only first, do not post</label>
                    </div>

                    <div class="alert alert-warning py-2 small">
                        <strong>Correction mode:</strong> No movements are deleted. The system compares
                        each location's balance at the selected date with the imported quantity and posts
                        an <code>ADJUSTMENT_IN</code> or <code>ADJUSTMENT_OUT</code>. Items omitted from
                        an imported location are corrected to zero.
                    </div>

                    <button class="btn btn-primary w-100">
                        <i class="bi bi-arrow-left-right me-2"></i>Post Opening Balance Corrections
                    </button>
                </form>
            </div>
        </div>
    </div>

    <div class="col-xl-7">
        <div class="card panel-card mb-4">
            <div class="card-header"><h5 class="mb-0">Required Template</h5></div>
            <div class="card-body">
                <div class="table-responsive">
                    <table class="table table-modern align-middle mb-0">
                        <thead><tr><th>Item Code</th><th>Item Name</th><th>Store</th><th>Opening Qty</th><th>Unit Cost</th><th>Notes</th></tr></thead>
                        <tbody>
                            <tr><td>stk003</td><td>Absolut Vodka 750ml</td><td>Bar Bulk</td><td class="text-end">30</td><td class="text-end">0.6306</td><td>Opening stock import</td></tr>
                            <tr><td>stk033</td><td>Amarula Cream 750ml</td><td>Bar Bulk</td><td class="text-end">125</td><td class="text-end">0.5178</td><td>Opening stock import</td></tr>
                        </tbody>
                    </table>
                </div>
                <div class="alert alert-info mt-3 mb-0">
                    <strong>Important:</strong> Historical movements are retained. For each store represented in the CSV, imported quantities become the target balances. Items omitted from that store are adjusted to zero. Item Code must already exist in inventory_items. Unit Cost can be blank; avg_cost/cost_price will be used.
                </div>
            </div>
        </div>

        <?php if ($previewRows): ?>
            <div class="card panel-card">
                <div class="card-header"><h5 class="mb-0">Import Preview / Skipped Rows</h5></div>
                <div class="card-body">
                    <div class="table-responsive" style="max-height:420px;overflow:auto;">
                        <table class="table table-sm table-striped align-middle mb-0">
                            <thead><tr><th style="width:90px;">CSV Row</th><th>Result</th></tr></thead>
                            <tbody>
                                <?php foreach ($previewRows as $r): ?>
                                    <tr>
                                        <td><?php echo h($r['row'] ?? ''); ?></td>
                                        <td><?php echo h($r['reason'] ?? ''); ?></td>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        <?php endif; ?>
    </div>
</div>

<style>
.hero-band{padding:12px 16px!important;margin-bottom:10px!important}
.hero-title{font-size:1.35rem!important;line-height:1.1!important}
.hero-subtitle{font-size:.85rem!important;line-height:1.25!important;opacity:.92}
.panel-card .card-header{padding:10px 12px!important}
.panel-card .card-body{padding:12px!important}
.form-label{font-size:.78rem!important;font-weight:700!important;margin-bottom:3px!important}
.form-control,.form-select{font-size:.85rem!important;border-radius:9px!important}
.table-modern th{background:#f8fafc!important;font-size:.78rem;text-transform:uppercase;letter-spacing:.04em;white-space:nowrap}
.table-modern td{font-size:.86rem}
</style>

<?php require_once __DIR__ . '/../../includes/footer.php'; ?>
