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

$pageTitle = 'Stock Take';

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('qty_fmt')) {
    function qty_fmt($quantity): string { return number_format((float)$quantity, 4, '.', ''); }
}
if (!function_exists('st_table_exists')) {
    function st_table_exists(PDO $pdo, string $tableName): bool {
        $stmt = $pdo->prepare("
            SELECT COUNT(*)
            FROM information_schema.tables
            WHERE table_schema = DATABASE()
              AND table_name = :table_name
        ");
        $stmt->execute([':table_name' => $tableName]);
        return (int)$stmt->fetchColumn() > 0;
    }
}
if (!function_exists('st_column_exists')) {
    function st_column_exists(PDO $pdo, string $tableName, string $columnName): 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' => $tableName, ':column_name' => $columnName]);
        return (int)$stmt->fetchColumn() > 0;
    }
}
if (!function_exists('st_flash')) {
    function st_flash(string $type, string $message): void {
        $_SESSION['stock_take_flash'][] = ['type' => $type, 'message' => $message];
    }
}
if (!function_exists('st_get_flash')) {
    function st_get_flash(): array {
        $items = $_SESSION['stock_take_flash'] ?? [];
        unset($_SESSION['stock_take_flash']);
        return $items;
    }
}
if (!function_exists('st_stock_balance')) {
    function st_stock_balance(PDO $pdo, int $itemId, int $storeId): float {
        $stmt = $pdo->prepare("
            SELECT COALESCE(SUM(qty_in - qty_out),0)
            FROM stock_movements
            WHERE item_id = :item_id
              AND store_id = :store_id
        ");
        $stmt->execute([':item_id' => $itemId, ':store_id' => $storeId]);
        return (float)$stmt->fetchColumn();
    }
}
if (!function_exists('st_recalc_avg_cost')) {
    function st_recalc_avg_cost(PDO $pdo, int $itemId): void {
        if (!st_table_exists($pdo, 'inventory_items')) return;
        if (!st_column_exists($pdo, 'inventory_items', 'avg_cost')) return;

        $stmt = $pdo->prepare("
            SELECT
                COALESCE(SUM(qty_in),0) AS qty,
                COALESCE(SUM(qty_in * unit_cost),0) AS cost
            FROM stock_movements
            WHERE item_id = :item_id
              AND qty_in > 0
              AND movement_type IN ('OPENING','GRN','TRANSFER_IN','ADJUSTMENT_IN','RETURN')
        ");
        $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]);
        }
    }
}

$errors = [];

try {
    $pdo->exec("CREATE TABLE IF NOT EXISTS store_locations (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        location_code VARCHAR(50) NULL,
        location_name VARCHAR(150) NOT NULL,
        location_type ENUM('main_store','bar','restaurant','curio','kitchen','housekeeping','maintenance','other') NOT NULL DEFAULT 'main_store',
        is_pos_location TINYINT(1) NOT NULL DEFAULT 0,
        allow_room_charge TINYINT(1) NOT NULL DEFAULT 1,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        notes TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_store_location_code (location_code)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $colCheck = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name='store_locations' AND column_name=:col");
    foreach ([
        'allow_room_charge' => "ALTER TABLE store_locations ADD COLUMN allow_room_charge TINYINT(1) NOT NULL DEFAULT 1 AFTER is_pos_location",
        'notes' => "ALTER TABLE store_locations ADD COLUMN notes TEXT NULL AFTER is_active"
    ] as $col => $sql) {
        $colCheck->execute([':col' => $col]);
        if ((int)$colCheck->fetchColumn() === 0) $pdo->exec($sql);
    }

    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_item_categories (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        category_name VARCHAR(120) NOT NULL,
        category_type ENUM('stock','food','bar','curio','consumable','service','other') NOT NULL DEFAULT 'stock',
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_category_name (category_name)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_units (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        unit_code VARCHAR(30) NOT NULL,
        unit_name VARCHAR(80) NOT NULL,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_unit_code (unit_code)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_items (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        item_code VARCHAR(60) NULL,
        item_name VARCHAR(180) NOT NULL,
        category_id INT UNSIGNED NULL,
        unit_id INT UNSIGNED NULL,
        item_type ENUM('stock','food','bar','curio','consumable','service','recipe','other') NOT NULL DEFAULT 'stock',
        barcode VARCHAR(100) NULL,
        description TEXT NULL,
        cost_price DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        avg_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        selling_price DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        tax_rate DECIMAL(7,4) NOT NULL DEFAULT 0.0000,
        reorder_level DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        reorder_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        is_stock_item TINYINT(1) NOT NULL DEFAULT 1,
        is_pos_item TINYINT(1) NOT NULL DEFAULT 0,
        allow_room_charge TINYINT(1) NOT NULL DEFAULT 1,
        track_expiry TINYINT(1) NOT NULL DEFAULT 0,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_item_code (item_code),
        INDEX idx_inventory_item_name (item_name)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS stock_movements (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        item_id INT UNSIGNED NOT NULL,
        store_id INT UNSIGNED NOT NULL,
        movement_type ENUM('OPENING','GRN','ISSUE','SALE','TRANSFER_IN','TRANSFER_OUT','ADJUSTMENT_IN','ADJUSTMENT_OUT','WASTAGE','RETURN') NOT NULL,
        qty_in DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        qty_out DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        unit_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        total_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        reference_type VARCHAR(60) NULL,
        reference_id BIGINT UNSIGNED NULL,
        notes TEXT NULL,
        movement_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX idx_stock_item_store (item_id, store_id),
        INDEX idx_stock_movement_date (movement_date),
        INDEX idx_stock_reference (reference_type, reference_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS stock_take_sessions (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        stock_take_no VARCHAR(60) NOT NULL,
        store_id INT UNSIGNED NOT NULL,
        status ENUM('draft','posted','cancelled') NOT NULL DEFAULT 'draft',
        stock_take_date DATE NOT NULL,
        notes TEXT NULL,
        created_by INT UNSIGNED NULL,
        posted_by INT UNSIGNED NULL,
        posted_at DATETIME NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_stock_take_no (stock_take_no),
        INDEX idx_stock_take_store (store_id),
        INDEX idx_stock_take_status (status),
        INDEX idx_stock_take_date (stock_take_date)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS stock_take_lines (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        stock_take_id BIGINT UNSIGNED NOT NULL,
        item_id INT UNSIGNED NOT NULL,
        system_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        counted_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        variance_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        unit_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        variance_value DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        notes TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX idx_stock_take_line_session (stock_take_id),
        INDEX idx_stock_take_line_item (item_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

} catch (Throwable $e) {
    $errors[] = 'Could not prepare stock take tables: ' . $e->getMessage();
}

function stock_take_no(PDO $pdo): string {
    $prefix = 'ST-' . date('ymd') . '-';
    $stmt = $pdo->prepare("SELECT COUNT(*) FROM stock_take_sessions WHERE stock_take_no LIKE :p");
    $stmt->execute([':p' => $prefix . '%']);
    return $prefix . str_pad((string)((int)$stmt->fetchColumn() + 1), 4, '0', STR_PAD_LEFT);
}

if (!function_exists('st_to_number')) {
    function st_to_number($value): float {
        $value = trim((string)$value);
        $value = str_replace([",", "\xc2\xa0"], ['', ''], $value);
        if ($value === '' || $value === '—') return 0.0;
        return is_numeric($value) ? (float)$value : 0.0;
    }
}
if (!function_exists('st_clean_cell')) {
    function st_clean_cell($value): string {
        $value = html_entity_decode((string)$value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $value = strip_tags($value);
        $value = preg_replace('/\s+/', ' ', $value);
        return trim((string)$value);
    }
}

if (!function_exists('st_normalize_header')) {
    function st_normalize_header($value): string {
        $value = st_clean_cell($value);
        $value = strtolower($value);
        $value = str_replace(['&', '/', '\\', '-', '_', '.', ':'], ' ', $value);
        $value = preg_replace('/[^a-z0-9]+/', ' ', $value);
        return trim(preg_replace('/\s+/', ' ', (string)$value));
    }
}
if (!function_exists('st_header_aliases')) {
    function st_header_aliases(): array {
        return [
            'line_id' => ['line id','lineid','stock take line id','stocktake line id','count line id','row id'],
            'item_id' => ['item id','itemid','inventory item id','inventory id','product id'],
            'item_code' => ['item code','itemcode','inventory code','product code','stock code','sku','code'],
            'counted_qty' => ['counted qty','counted quantity','physical count','physical qty','physical quantity','actual count','actual qty','actual quantity','stock count','count qty','count quantity','quantity counted','qty counted','closing count','closing qty'],
            'notes' => ['notes','note','count notes','count note','remarks','comment','comments','reason'],
        ];
    }
}
if (!function_exists('st_find_count_header_map')) {
    function st_find_count_header_map(array $rows): array {
        $aliases = st_header_aliases();
        $best = null;
        foreach ($rows as $idx => $row) {
            $map = ['header_index' => $idx];
            foreach ($row as $colIdx => $value) {
                $header = st_normalize_header($value);
                if ($header === '') continue;
                foreach ($aliases as $key => $names) {
                    foreach ($names as $alias) {
                        if ($header === st_normalize_header($alias)) {
                            if (!isset($map[$key])) $map[$key] = $colIdx;
                            break 2;
                        }
                    }
                }
            }
            $identifierCount = (isset($map['line_id']) ? 1 : 0) + (isset($map['item_id']) ? 1 : 0) + (isset($map['item_code']) ? 1 : 0);
            $score = ($identifierCount * 10) + (isset($map['counted_qty']) ? 20 : 0) + (isset($map['notes']) ? 1 : 0);
            if (isset($map['counted_qty']) && $identifierCount > 0 && ($best === null || $score > $best['score'])) {
                $best = ['score' => $score, 'map' => $map];
            }
        }
        if ($best !== null) return $best['map'];
        throw new RuntimeException('Could not identify the stock-count header row. Include a count column such as Counted Qty, Physical Count or Actual Qty, plus at least one identifier: Line ID, Item ID or Item Code.');
    }
}
if (!function_exists('st_read_import_rows')) {
    function st_read_import_rows(string $path): array {
        if (!is_file($path) || !is_readable($path)) {
            throw new RuntimeException('Uploaded file could not be read.');
        }

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

        $rows = [];
        if (stripos($raw, '<table') !== false && preg_match_all('/<tr\b[^>]*>(.*?)<\/tr>/is', $raw, $trMatches)) {
            foreach ($trMatches[1] as $tr) {
                if (preg_match_all('/<t[dh]\b[^>]*>(.*?)<\/t[dh]>/is', $tr, $tdMatches)) {
                    $rows[] = array_map('st_clean_cell', $tdMatches[1]);
                }
            }
            return $rows;
        }

        $lines = preg_split('/\r\n|\n|\r/', $raw);
        foreach ($lines as $line) {
            if (trim($line) === '') continue;
            $delimiter = substr_count($line, "\t") > substr_count($line, ',') ? "\t" : ',';
            $rows[] = array_map('st_clean_cell', str_getcsv($line, $delimiter));
        }
        return $rows;
    }
}


if (!function_exists('st_xlsx_col_to_index')) {
    function st_xlsx_col_to_index(string $letters): int {
        $letters = strtoupper($letters);
        $num = 0;
        for ($i = 0; $i < strlen($letters); $i++) {
            $num = ($num * 26) + (ord($letters[$i]) - 64);
        }
        return max(0, $num - 1);
    }
}
if (!function_exists('st_read_xlsx_rows')) {
    function st_read_xlsx_rows(string $path): array {
        if (!class_exists('ZipArchive')) {
            throw new RuntimeException('XLSX import requires the PHP ZipArchive extension. Please upload CSV/XLS exported from Excel if ZipArchive is not enabled.');
        }
        $zip = new ZipArchive();
        if ($zip->open($path) !== true) {
            throw new RuntimeException('Could not open XLSX file.');
        }

        $shared = [];
        $sharedXml = $zip->getFromName('xl/sharedStrings.xml');
        if ($sharedXml !== false) {
            $sx = @simplexml_load_string($sharedXml);
            if ($sx) {
                foreach ($sx->si as $si) {
                    $text = '';
                    if (isset($si->t)) {
                        $text = (string)$si->t;
                    } elseif (isset($si->r)) {
                        foreach ($si->r as $r) $text .= (string)$r->t;
                    }
                    $shared[] = $text;
                }
            }
        }

        $sheetName = 'xl/worksheets/sheet1.xml';
        $workbookXml = $zip->getFromName('xl/workbook.xml');
        $relsXml = $zip->getFromName('xl/_rels/workbook.xml.rels');
        if ($workbookXml !== false && $relsXml !== false) {
            $wb = @simplexml_load_string($workbookXml);
            $rels = @simplexml_load_string($relsXml);
            if ($wb && $rels && isset($wb->sheets->sheet[0])) {
                $attrs = $wb->sheets->sheet[0]->attributes('r', true);
                $rid = (string)$attrs['id'];
                foreach ($rels->Relationship as $rel) {
                    $ra = $rel->attributes();
                    if ((string)$ra['Id'] === $rid) {
                        $target = (string)$ra['Target'];
                        $sheetName = 'xl/' . ltrim($target, '/');
                        break;
                    }
                }
            }
        }

        $sheetXml = $zip->getFromName($sheetName);
        $zip->close();
        if ($sheetXml === false) {
            throw new RuntimeException('Could not read the first worksheet in the XLSX file.');
        }
        $sheet = @simplexml_load_string($sheetXml);
        if (!$sheet || !isset($sheet->sheetData->row)) {
            throw new RuntimeException('No worksheet rows were found in the XLSX file.');
        }

        $rows = [];
        foreach ($sheet->sheetData->row as $row) {
            $out = [];
            foreach ($row->c as $cell) {
                $attrs = $cell->attributes();
                $ref = (string)$attrs['r'];
                $type = (string)$attrs['t'];
                $colLetters = preg_replace('/[^A-Z]/i', '', $ref);
                $colIndex = st_xlsx_col_to_index($colLetters);
                while (count($out) < $colIndex) $out[] = '';

                $val = '';
                if ($type === 'inlineStr' && isset($cell->is->t)) {
                    $val = (string)$cell->is->t;
                } elseif (isset($cell->v)) {
                    $raw = (string)$cell->v;
                    if ($type === 's') {
                        $idx = (int)$raw;
                        $val = $shared[$idx] ?? '';
                    } else {
                        $val = $raw;
                    }
                }
                $out[$colIndex] = st_clean_cell($val);
            }
            $rows[] = $out;
        }
        return $rows;
    }
}
if (!function_exists('st_read_any_import_rows')) {
    function st_read_any_import_rows(string $path): array {
        $fh = fopen($path, 'rb');
        $magic = $fh ? fread($fh, 4) : '';
        if ($fh) fclose($fh);
        if ($magic === "PK\x03\x04") {
            return st_read_xlsx_rows($path);
        }
        return st_read_import_rows($path);
    }
}
if (!function_exists('st_unit_id_for_name')) {
    function st_unit_id_for_name(PDO $pdo, string $unitName): ?int {
        $unitName = trim($unitName);
        if ($unitName === '') return null;
        $code = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $unitName));
        if ($code === '') $code = 'UNIT';
        $code = substr($code, 0, 30);
        $stmt = $pdo->prepare("SELECT id FROM inventory_units WHERE unit_code = :code LIMIT 1");
        $stmt->execute([':code' => $code]);
        $id = (int)$stmt->fetchColumn();
        if ($id > 0) return $id;
        $stmt = $pdo->prepare("INSERT INTO inventory_units (unit_code, unit_name, is_active) VALUES (:code, :name, 1)");
        $stmt->execute([':code' => $code, ':name' => substr($unitName, 0, 80)]);
        return (int)$pdo->lastInsertId();
    }
}
if (!function_exists('st_get_or_create_store')) {
    function st_get_or_create_store(PDO $pdo, string $locationName): int {
        $locationName = trim($locationName);
        if ($locationName === '') throw new RuntimeException('Missing storage area/location name in import file.');
        $stmt = $pdo->prepare("SELECT id FROM store_locations WHERE location_name = :name LIMIT 1");
        $stmt->execute([':name' => $locationName]);
        $id = (int)$stmt->fetchColumn();
        if ($id > 0) return $id;
        $code = strtoupper(substr(preg_replace('/[^A-Za-z0-9]/', '', $locationName), 0, 50));
        if ($code === '') $code = 'LOC' . date('His');
        $base = $code;
        $n = 1;
        while (true) {
            $chk = $pdo->prepare("SELECT COUNT(*) FROM store_locations WHERE location_code = :code");
            $chk->execute([':code' => $code]);
            if ((int)$chk->fetchColumn() === 0) break;
            $suffix = (string)$n++;
            $code = substr($base, 0, 50 - strlen($suffix)) . $suffix;
        }
        $stmt = $pdo->prepare("INSERT INTO store_locations (location_code, location_name, location_type, is_active, notes) VALUES (:code, :name, 'main_store', 1, 'Auto-created from opening stock import')");
        $stmt->execute([':code' => $code, ':name' => $locationName]);
        return (int)$pdo->lastInsertId();
    }
}
if (!function_exists('st_get_or_create_inventory_item')) {
    function st_get_or_create_inventory_item(PDO $pdo, string $product, string $description, ?int $unitId, float $unitCost): int {
        $name = trim($description !== '' ? $description : $product);
        if ($name === '') throw new RuntimeException('Import row has no product/item name.');
        $rawCode = trim($product);
        $code = strtoupper(substr(preg_replace('/[^A-Za-z0-9_-]/', '', $rawCode), 0, 60));
        if ($code !== '') {
            $stmt = $pdo->prepare("SELECT id FROM inventory_items WHERE item_code = :code LIMIT 1");
            $stmt->execute([':code' => $code]);
            $id = (int)$stmt->fetchColumn();
            if ($id > 0) return $id;
        }
        $stmt = $pdo->prepare("SELECT id FROM inventory_items WHERE item_name = :name LIMIT 1");
        $stmt->execute([':name' => $name]);
        $id = (int)$stmt->fetchColumn();
        if ($id > 0) return $id;

        if ($code === '') {
            $code = strtoupper(substr(preg_replace('/[^A-Za-z0-9]/', '', $name), 0, 50));
            if ($code === '') $code = 'ITEM' . date('His');
        }
        $base = $code;
        $n = 1;
        while (true) {
            $chk = $pdo->prepare("SELECT COUNT(*) FROM inventory_items WHERE item_code = :code");
            $chk->execute([':code' => $code]);
            if ((int)$chk->fetchColumn() === 0) break;
            $suffix = (string)$n++;
            $code = substr($base, 0, 60 - strlen($suffix)) . $suffix;
        }
        $stmt = $pdo->prepare("INSERT INTO inventory_items
            (item_code, item_name, category_id, unit_id, item_type, cost_price, avg_cost, selling_price, is_stock_item, is_pos_item, is_active)
            VALUES
            (:code, :name, NULL, :unit_id, 'stock', :cost_price, :avg_cost, 0, 1, 0, 1)");
        $stmt->execute([
            ':code' => $code,
            ':name' => $name,
            ':unit_id' => $unitId,
            ':cost_price' => $unitCost,
            ':avg_cost' => $unitCost,
        ]);
        return (int)$pdo->lastInsertId();
    }
}
if (!function_exists('st_find_header_map')) {
    function st_find_header_map(array $rows): array {
        foreach ($rows as $idx => $row) {
            $lower = [];
            foreach ($row as $v) $lower[] = strtolower(trim((string)$v));
            if (in_array('product', $lower, true) && in_array('storage area', $lower, true)) {
                $map = ['header_index' => $idx];
                foreach ($lower as $i => $name) {
                    if ($name === 'product') $map['product'] = $i;
                    if ($name === 'product description') $map['description'] = $i;
                    if ($name === 'storage area') $map['storage_area'] = $i;
                    if ($name === 'full master units') $map['full_master_units'] = $i;
                    if ($name === 'total smaller units (smaller + full)') $map['total_smaller_units'] = $i;
                    if ($name === 'average cost price (excl.)') $map['avg_cost'] = $i;
                    if ($name === 'last cost price (excl.)') $map['last_cost'] = $i;
                    if ($name === 'total cost value (excl.)') $map['total_cost'] = $i;
                }
                // Measurement appears multiple times. Use E for master unit and I for total smaller unit based on report layout.
                $map['master_measurement'] = 4;
                $map['smaller_measurement'] = 8;
                return $map;
            }
        }
        throw new RuntimeException('Could not find Stock On Hand headers. Expected Product and Storage Area columns.');
    }
}

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    try {
        $action = (string)($_POST['action'] ?? '');

        /*
         * AJAX item search:
         * This is read-only and is called by fetch() while typing.
         * Handle it before CSRF verification so the browser does not receive an HTML redirect
         * instead of JSON. Also use unique placeholders (:q_name / :q_code) for PDO drivers
         * that do not allow reusing the same named placeholder twice.
         */
        if ($action === 'search_items') {
            header('Content-Type: application/json; charset=utf-8');
            $term = trim((string)($_POST['q'] ?? ''));
            $sessionId = (int)($_POST['session_id'] ?? 0);

            if ($sessionId <= 0 || strlen($term) < 1) {
                echo json_encode([]);
                exit;
            }

            $qName = '%' . $term . '%';
            $qCode = '%' . $term . '%';

            $stmt = $pdo->prepare("
                SELECT
                    ii.id,
                    ii.item_code,
                    ii.item_name,
                    COALESCE(c.category_name,'') AS category_name
                FROM inventory_items ii
                LEFT JOIN inventory_item_categories c ON c.id = ii.category_id
                WHERE COALESCE(ii.is_active,1) = 1
                  AND COALESCE(ii.is_stock_item,1) = 1
                  AND (
                        ii.item_name LIKE :q_name
                        OR ii.item_code LIKE :q_code
                        OR COALESCE(ii.barcode,'') LIKE :q_barcode
                  )
                  AND NOT EXISTS (
                      SELECT 1
                      FROM stock_take_lines stl
                      WHERE stl.stock_take_id = :sid
                        AND stl.item_id = ii.id
                  )
                ORDER BY ii.item_name ASC
                LIMIT 30
            ");
            $stmt->execute([
                ':q_name' => $qName,
                ':q_code' => $qCode,
                ':q_barcode' => $qCode,
                ':sid' => $sessionId,
            ]);
            echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
            exit;
        }

        if (function_exists('verify_csrf')) verify_csrf();


        if ($action === 'import_opening_stock') {
            if (empty($_FILES['opening_file']['tmp_name']) || !is_uploaded_file($_FILES['opening_file']['tmp_name'])) {
                throw new RuntimeException('Please choose the Stock On Hand file to import.');
            }
            $replaceExisting = isset($_POST['replace_existing_opening']) ? 1 : 0;
            $importDate = trim((string)($_POST['opening_date'] ?? date('Y-m-d')));
            if (strtotime($importDate) === false) $importDate = date('Y-m-d');
            $importDateSql = date('Y-m-d 00:00:00', strtotime($importDate));
            $batchNo = 'OPEN-' . date('Ymd-His') . '-' . strtoupper(substr(bin2hex(random_bytes(3)), 0, 6));

            $rows = st_read_any_import_rows((string)$_FILES['opening_file']['tmp_name']);
            if (!$rows) throw new RuntimeException('No rows were found in the opening stock file.');
            $map = st_find_header_map($rows);

            $prepared = [];
            $storeIds = [];
            for ($i = ((int)$map['header_index']) + 1; $i < count($rows); $i++) {
                $row = $rows[$i];
                $product = st_clean_cell($row[$map['product']] ?? '');
                $description = st_clean_cell($row[$map['description']] ?? '');
                $storageArea = st_clean_cell($row[$map['storage_area']] ?? '');
                if ($product === '' || $storageArea === '') continue;
                if (strtolower($product) === 'non-bulk products' || strtolower($product) === 'bulk products') continue;

                $fullQty = st_to_number($row[$map['full_master_units']] ?? 0);
                $smallerRaw = $row[$map['total_smaller_units']] ?? '';
                $smallerQty = st_to_number($smallerRaw);
                $useSmaller = trim((string)$smallerRaw) !== '' && $smallerQty > 0;
                $qty = $useSmaller ? $smallerQty : $fullQty;
                if (abs($qty) <= 0.0001) continue;

                $unitName = st_clean_cell($row[$useSmaller ? $map['smaller_measurement'] : $map['master_measurement']] ?? 'Units');
                if ($unitName === '') $unitName = 'Units';
                $avgCost = st_to_number($row[$map['avg_cost']] ?? 0);
                $lastCost = st_to_number($row[$map['last_cost']] ?? 0);
                $totalCost = st_to_number($row[$map['total_cost']] ?? 0);
                $unitCost = $avgCost > 0 ? $avgCost : ($lastCost > 0 ? $lastCost : ($qty > 0 && $totalCost > 0 ? $totalCost / $qty : 0));
                if ($useSmaller && $totalCost > 0 && $qty > 0) {
                    // Stock On Hand report average cost is often per master item. For smaller-unit rows, total cost / total smaller units gives safer unit cost.
                    $unitCost = $totalCost / $qty;
                }

                $storeId = st_get_or_create_store($pdo, $storageArea);
                $unitId = st_unit_id_for_name($pdo, $unitName);
                $itemId = st_get_or_create_inventory_item($pdo, $product, $description, $unitId, $unitCost);
                $storeIds[$storeId] = true;
                $prepared[] = [
                    'item_id' => $itemId,
                    'store_id' => $storeId,
                    'qty' => $qty,
                    'unit_cost' => $unitCost,
                    'total_cost' => $qty * $unitCost,
                    'product' => $product,
                    'storage_area' => $storageArea,
                    'unit_name' => $unitName,
                ];
            }
            if (!$prepared) throw new RuntimeException('No importable opening stock rows were found.');

            $pdo->beginTransaction();
            if ($replaceExisting && $storeIds) {
                $ids = array_keys($storeIds);
                $placeholders = implode(',', array_fill(0, count($ids), '?'));
                $del = $pdo->prepare("DELETE FROM stock_movements WHERE reference_type = 'OPENING_IMPORT' AND store_id IN ($placeholders)");
                $del->execute($ids);
            }

            $movementStmt = $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, 'OPENING', :qty_in, 0, :unit_cost, :total_cost, 'OPENING_IMPORT', NULL, :notes, :movement_date)");
            foreach ($prepared as $line) {
                $movementStmt->execute([
                    ':item_id' => (int)$line['item_id'],
                    ':store_id' => (int)$line['store_id'],
                    ':qty_in' => (float)$line['qty'],
                    ':unit_cost' => (float)$line['unit_cost'],
                    ':total_cost' => (float)$line['total_cost'],
                    ':notes' => 'Opening stock import ' . $batchNo . ' | ' . $line['product'] . ' | ' . $line['storage_area'] . ' | Unit: ' . $line['unit_name'],
                    ':movement_date' => $importDateSql,
                ]);
                st_recalc_avg_cost($pdo, (int)$line['item_id']);
            }
            $pdo->commit();

            st_flash('success', 'Opening stock import completed. Posted ' . count($prepared) . ' opening movement(s) across ' . count($storeIds) . ' location(s). Batch: ' . $batchNo);
            header('Location: stock_movements.php?q=' . urlencode($batchNo));
            exit;
        }

        if ($action === 'create_session') {
            $storeId = (int)($_POST['store_id'] ?? 0);
            $stockTakeDate = trim((string)($_POST['stock_take_date'] ?? date('Y-m-d')));
            $notes = trim((string)($_POST['notes'] ?? ''));
            $stockScope = strtolower(trim((string)($_POST['stock_scope'] ?? 'location_only')));
            if (!in_array($stockScope, ['location_only', 'all_active'], true)) {
                $stockScope = 'location_only';
            }

            if ($storeId <= 0) throw new RuntimeException('Please select a stockholding location.');
            if (strtotime($stockTakeDate) === false) $stockTakeDate = date('Y-m-d');

            $stmt = $pdo->prepare("SELECT * FROM store_locations WHERE id=:id LIMIT 1");
            $stmt->execute([':id' => $storeId]);
            $store = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$store) throw new RuntimeException('Selected store location was not found.');

            /*
               Warn if there is already an OPEN DRAFT stock take for this same
               location. Two draft sheets counting the same shelves at once
               produce baselines that invalidate each other: whichever posts
               first shifts the ledger, leaving the other's frozen system_qty
               stale before it is even posted. This is a warning, not a block -
               the user can legitimately proceed (e.g. a stale abandoned draft),
               so we offer "Create anyway".
            */
            $overrideOpenDraft = !empty($_POST['override_open_draft']);
            if (!$overrideOpenDraft) {
                $dchk = $pdo->prepare("
                    SELECT stock_take_no, created_at
                    FROM stock_take_sessions
                    WHERE store_id = :store_id AND status = 'draft'
                    ORDER BY created_at DESC
                ");
                $dchk->execute([':store_id' => $storeId]);
                $openDrafts = $dchk->fetchAll(PDO::FETCH_ASSOC);

                if ($openDrafts) {
                    $_SESSION['stock_take_open_drafts'] = array(
                        'store_id'   => $storeId,
                        'store_name' => (string)($store['location_name'] ?? ('Location #' . $storeId)),
                        'drafts'     => $openDrafts,
                        // Preserve what the user was about to submit, so "Create
                        // anyway" recreates the same sheet without re-entry.
                        'form'       => array(
                            'stock_take_date' => $stockTakeDate,
                            'notes'           => $notes,
                            'stock_scope'     => $stockScope,
                        ),
                    );
                    $names = array();
                    foreach ($openDrafts as $od) {
                        $names[] = $od['stock_take_no']
                            . ' (' . date('d M Y H:i', strtotime((string)$od['created_at'])) . ')';
                    }
                    st_flash(
                        'warning',
                        'There is already an open draft stock take for ' . (string)($store['location_name'] ?? 'this location') . ': '
                        . implode(', ', $names) . '. '
                        . 'Counting two sheets against the same location at once can produce conflicting baselines. '
                        . 'Finish or cancel the existing count first, or choose "Create anyway" below.'
                    );
                    header('Location: stock_take.php?open_draft_warning=1');
                    exit;
                }
            }

            $pdo->beginTransaction();

            $stockTakeNo = stock_take_no($pdo);
            $stmt = $pdo->prepare("
                INSERT INTO stock_take_sessions
                (stock_take_no, store_id, status, stock_take_date, notes, created_by)
                VALUES
                (:no, :store_id, 'draft', :stock_take_date, :notes, :created_by)
            ");
            $stmt->execute([
                ':no' => $stockTakeNo,
                ':store_id' => $storeId,
                ':stock_take_date' => date('Y-m-d', strtotime($stockTakeDate)),
                ':notes' => $notes ?: null,
                ':created_by' => $_SESSION['user_id'] ?? null,
            ]);
            $sessionId = (int)$pdo->lastInsertId();

            /*
             * Stock count by stockholding location:
             * - location_only: include only items that have ever moved in this store/location.
             *   This prevents Bar Bulk, Kitchen, Curio, etc. count sheets from showing every item in the system.
             * - all_active: old behaviour; include all active stock items, with this location's system balance.
             */
            if ($stockScope === 'location_only') {
                $stmt = $pdo->prepare("
                    SELECT
                        ii.id,
                        COALESCE(SUM(sm.qty_in - sm.qty_out),0) AS balance_qty,
                        COALESCE(ii.avg_cost, ii.cost_price, 0) AS unit_cost,
                        COUNT(sm.id) AS movement_count
                    FROM inventory_items ii
                    INNER JOIN stock_movements sm
                        ON sm.item_id = ii.id
                       AND sm.store_id = :store_id
                    WHERE ii.is_active = 1
                      AND ii.is_stock_item = 1
                    GROUP BY ii.id
                    ORDER BY ii.item_name ASC
                ");
            } else {
                $stmt = $pdo->prepare("
                    SELECT
                        ii.id,
                        COALESCE(SUM(sm.qty_in - sm.qty_out),0) AS balance_qty,
                        COALESCE(ii.avg_cost, ii.cost_price, 0) AS unit_cost,
                        COUNT(sm.id) AS movement_count
                    FROM inventory_items ii
                    LEFT JOIN stock_movements sm
                        ON sm.item_id = ii.id
                       AND sm.store_id = :store_id
                    WHERE ii.is_active = 1
                      AND ii.is_stock_item = 1
                    GROUP BY ii.id
                    ORDER BY ii.item_name ASC
                ");
            }

            $stmt->execute([':store_id' => $storeId]);
            $items = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (!$items) {
                throw new RuntimeException('No stock items were found for the selected stockholding location. Choose "All active stock items" if this is a new location with no movements yet.');
            }

            $lineStmt = $pdo->prepare("
                INSERT INTO stock_take_lines
                (stock_take_id, item_id, system_qty, counted_qty, variance_qty, unit_cost, variance_value)
                VALUES
                (:stock_take_id, :item_id, :system_qty, :counted_qty, 0, :unit_cost, 0)
            ");
            foreach ($items as $item) {
                $systemQty = (float)$item['balance_qty'];
                $unitCost = (float)$item['unit_cost'];
                $lineStmt->execute([
                    ':stock_take_id' => $sessionId,
                    ':item_id' => (int)$item['id'],
                    ':system_qty' => $systemQty,
                    ':counted_qty' => $systemQty,
                    ':unit_cost' => $unitCost,
                ]);
            }

            $pdo->commit();

            st_flash('success', 'Stock take created. Count quantities and post adjustments when ready.');
            header('Location: stock_take.php?session_id=' . $sessionId);
            exit;
        }

        if ($action === 'save_counts') {
            $sessionId = (int)($_POST['session_id'] ?? 0);
            if ($sessionId <= 0) throw new RuntimeException('Invalid stock take session.');

            $stmt = $pdo->prepare("SELECT * FROM stock_take_sessions WHERE id=:id LIMIT 1");
            $stmt->execute([':id' => $sessionId]);
            $session = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$session) throw new RuntimeException('Stock take session not found.');
            if ($session['status'] !== 'draft') throw new RuntimeException('Only draft stock takes can be edited.');

            $counts = $_POST['counted_qty'] ?? [];
            $notes = $_POST['line_notes'] ?? [];

            $stmt = $pdo->prepare("
                UPDATE stock_take_lines
                SET counted_qty = :counted_qty,
                    variance_qty = :variance_qty,
                    variance_value = :variance_value,
                    notes = :notes
                WHERE id = :id
                  AND stock_take_id = :stock_take_id
            ");

            foreach ($counts as $lineId => $countedQty) {
                $lineId = (int)$lineId;
                $countedQty = round(st_to_number($countedQty), 4);

                $lineStmt = $pdo->prepare("SELECT * FROM stock_take_lines WHERE id=:id AND stock_take_id=:stock_take_id LIMIT 1");
                $lineStmt->execute([':id' => $lineId, ':stock_take_id' => $sessionId]);
                $line = $lineStmt->fetch(PDO::FETCH_ASSOC);
                if (!$line) continue;

                $variance = $countedQty - (float)$line['system_qty'];
                $varianceValue = $variance * (float)$line['unit_cost'];

                $stmt->execute([
                    ':counted_qty' => $countedQty,
                    ':variance_qty' => $variance,
                    ':variance_value' => $varianceValue,
                    ':notes' => trim((string)($notes[$lineId] ?? '')) ?: null,
                    ':id' => $lineId,
                    ':stock_take_id' => $sessionId,
                ]);
            }

            st_flash('success', 'Stock take counts saved.');
            header('Location: stock_take.php?session_id=' . $sessionId);
            exit;
        }

        if ($action === 'import_counts') {
            $sessionId = (int)($_POST['session_id'] ?? 0);
            if ($sessionId <= 0) throw new RuntimeException('Invalid stock take session.');

            $stmt = $pdo->prepare("SELECT * FROM stock_take_sessions WHERE id=:id LIMIT 1");
            $stmt->execute([':id' => $sessionId]);
            $session = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$session) throw new RuntimeException('Stock take session not found.');
            if ($session['status'] !== 'draft') throw new RuntimeException('Only draft stock takes can receive imported counts.');

            if (empty($_FILES['count_file']['tmp_name']) || !is_uploaded_file($_FILES['count_file']['tmp_name'])) {
                throw new RuntimeException('Please choose the completed count file to import.');
            }

            $rows = st_read_any_import_rows((string)$_FILES['count_file']['tmp_name']);
            if (!$rows) throw new RuntimeException('No rows were found in the import file.');

            /* Find the true header row anywhere in the worksheet. */
            $map = st_find_count_header_map($rows);
            $headerIndex = (int)$map['header_index'];

            $lineLookup = [];
            $stmt = $pdo->prepare("SELECT stl.*, ii.item_code FROM stock_take_lines stl INNER JOIN inventory_items ii ON ii.id = stl.item_id WHERE stl.stock_take_id = :id");
            $stmt->execute([':id' => $sessionId]);
            foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $line) {
                $lineLookup['line:' . (int)$line['id']] = $line;
                $lineLookup['item:' . (int)$line['item_id']] = $line;
                if (trim((string)$line['item_code']) !== '') {
                    $lineLookup['code:' . strtoupper(trim((string)$line['item_code']))] = $line;
                }
            }

            $updateStmt = $pdo->prepare("\n                UPDATE stock_take_lines\n                SET counted_qty = :counted_qty,\n                    variance_qty = :variance_qty,\n                    variance_value = :variance_value,\n                    notes = :notes\n                WHERE id = :id\n                  AND stock_take_id = :stock_take_id\n            ");

            $updated = 0;
            $skipped = 0;
            $pdo->beginTransaction();
            for ($i = $headerIndex + 1; $i < count($rows); $i++) {
                $row = $rows[$i];
                if (!array_filter($row, function($v) { return trim((string)$v) !== ''; })) continue;

                $countRaw = $row[$map['counted_qty']] ?? '';
                if (trim((string)$countRaw) === '') { $skipped++; continue; }

                $line = null;
                if (isset($map['line_id'])) {
                    $lineId = (int)st_to_number($row[$map['line_id']] ?? 0);
                    if ($lineId > 0 && isset($lineLookup['line:' . $lineId])) $line = $lineLookup['line:' . $lineId];
                }
                if (!$line && isset($map['item_id'])) {
                    $itemId = (int)st_to_number($row[$map['item_id']] ?? 0);
                    if ($itemId > 0 && isset($lineLookup['item:' . $itemId])) $line = $lineLookup['item:' . $itemId];
                }
                if (!$line && isset($map['item_code'])) {
                    $code = strtoupper(trim((string)($row[$map['item_code']] ?? '')));
                    if ($code !== '' && isset($lineLookup['code:' . $code])) $line = $lineLookup['code:' . $code];
                }
                if (!$line) { $skipped++; continue; }

                $countedQty = round(st_to_number($countRaw), 4);
                $variance = $countedQty - (float)$line['system_qty'];
                $varianceValue = $variance * (float)$line['unit_cost'];
                $notes = isset($map['notes']) ? trim((string)($row[$map['notes']] ?? '')) : (string)($line['notes'] ?? '');

                $updateStmt->execute([
                    ':counted_qty' => $countedQty,
                    ':variance_qty' => $variance,
                    ':variance_value' => $varianceValue,
                    ':notes' => $notes !== '' ? $notes : null,
                    ':id' => (int)$line['id'],
                    ':stock_take_id' => $sessionId,
                ]);
                $updated++;
            }
            $pdo->commit();

            st_flash('success', 'Physical count import completed. Updated ' . $updated . ' line(s).' . ($skipped ? ' Skipped ' . $skipped . ' unmatched/blank row(s).' : ''));
            header('Location: stock_take.php?session_id=' . $sessionId);
            exit;
        }

        if ($action === 'post_adjustments') {
            $sessionId = (int)($_POST['session_id'] ?? 0);
            if ($sessionId <= 0) throw new RuntimeException('Invalid stock take session.');

            // When set, the user has reviewed the drift warning and chosen to
            // post anyway, adjusting each item TO the counted figure against its
            // CURRENT live balance.
            $overrideDrift = !empty($_POST['override_drift']);

            $stmt = $pdo->prepare("SELECT * FROM stock_take_sessions WHERE id=:id LIMIT 1");
            $stmt->execute([':id' => $sessionId]);
            $session = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$session) throw new RuntimeException('Stock take session not found.');
            if ($session['status'] !== 'draft') throw new RuntimeException('This stock take has already been posted or cancelled.');

            $storeId = (int)$session['store_id'];

            /*
               Load ALL counted lines (not just those with a stored variance).
               The stored variance_qty was computed as (counted - frozen
               system_qty) at sheet-creation time. In a live bar, real stock
               moves between creating the sheet and posting it, so the frozen
               system_qty is stale and posting that stored variance drives the
               balance to the wrong number (e.g. counted 0 but balance ends at
               -1 because a sale landed after the sheet was made).

               Correct approach: at POST time, recompute each item's variance
               against its CURRENT live ledger balance, so the closing balance
               lands exactly on the counted figure. And DETECT drift: if the
               live balance no longer matches the frozen system_qty, something
               moved since the count - block and show the user, unless they
               explicitly override.
            */
            $stmt = $pdo->prepare("
                SELECT stl.*, COALESCE(ii.item_name, CONCAT('Item #', stl.item_id)) AS item_name
                FROM stock_take_lines stl
                LEFT JOIN inventory_items ii ON ii.id = stl.item_id
                WHERE stl.stock_take_id = :id
            ");
            $stmt->execute([':id' => $sessionId]);
            $allLines = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // First pass: compute live balance + detect drift, without writing.
            $toPost = array();   // lines that need an adjustment movement
            $drifted = array();  // lines where live balance != frozen system_qty
            foreach ($allLines as $line) {
                $itemId       = (int)$line['item_id'];
                $frozenSystem = round((float)$line['system_qty'], 4);
                $counted      = round((float)$line['counted_qty'], 4);
                $liveBalance  = round(st_stock_balance($pdo, $itemId, $storeId), 4);

                // Variance to apply = counted - LIVE balance (not frozen).
                $liveVariance = round($counted - $liveBalance, 4);

                // Drift = the ledger moved since the sheet froze system_qty.
                if (abs($liveBalance - $frozenSystem) > 0.0001) {
                    $drifted[] = array(
                        'item_id'      => $itemId,
                        'name'         => (string)($line['item_name'] ?? ('Item #' . $itemId)),
                        'frozen'       => $frozenSystem,
                        'live'         => $liveBalance,
                        'counted'      => $counted,
                    );
                }

                if (abs($liveVariance) > 0.0001) {
                    $toPost[] = array(
                        'line'         => $line,
                        'item_id'      => $itemId,
                        'frozen'       => $frozenSystem,
                        'live'         => $liveBalance,
                        'counted'      => $counted,
                        'variance'     => $liveVariance,
                    );
                }
            }

            // If anything drifted and the user hasn't overridden, STOP and
            // report exactly what moved so they can recount or post anyway.
            if ($drifted && !$overrideDrift) {
                $msgLines = array();
                foreach ($drifted as $d) {
                    $msgLines[] = $d['name']
                        . ': sheet showed ' . rtrim(rtrim(number_format($d['frozen'], 4), '0'), '.')
                        . ', live is now ' . rtrim(rtrim(number_format($d['live'], 4), '0'), '.')
                        . ' (you counted ' . rtrim(rtrim(number_format($d['counted'], 4), '0'), '.') . ')';
                }
                $_SESSION['stock_take_drift'][$sessionId] = $drifted;
                st_flash(
                    'warning',
                    'Stock moved since this count sheet was created, so posting now would adjust against out-of-date figures. '
                    . 'Review these ' . count($drifted) . ' item(s), then recount or choose "Post anyway (adjust to counted)": '
                    . implode('  •  ', $msgLines)
                );
                header('Location: stock_take.php?session_id=' . $sessionId . '&drift=1');
                exit;
            }

            $pdo->beginTransaction();

            $movementStmt = $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, 'STOCK_TAKE', :reference_id, :notes, NOW())
            ");

            foreach ($toPost as $p) {
                $line     = $p['line'];
                $variance = $p['variance']; // counted - live balance
                $qtyIn    = $variance > 0 ? abs($variance) : 0;
                $qtyOut   = $variance < 0 ? abs($variance) : 0;
                $movementType = $variance > 0 ? 'ADJUSTMENT_IN' : 'ADJUSTMENT_OUT';
                $unitCost = (float)$line['unit_cost'];
                $totalCost = abs($variance) * $unitCost;

                // Full audit trail: what the sheet froze, what the ledger held
                // at posting, what was counted, and the variance actually applied.
                $auditNote = 'Stock take adjustment ' . $session['stock_take_no']
                    . ' | sheet system_qty=' . rtrim(rtrim(number_format($p['frozen'], 4), '0'), '.')
                    . ' | live balance=' . rtrim(rtrim(number_format($p['live'], 4), '0'), '.')
                    . ' | counted=' . rtrim(rtrim(number_format($p['counted'], 4), '0'), '.')
                    . ' | applied=' . rtrim(rtrim(number_format($variance, 4), '0'), '.')
                    . ($overrideDrift && $drifted ? ' | posted with drift override' : '')
                    . ($line['notes'] ? ' | ' . $line['notes'] : '');

                $movementStmt->execute([
                    ':item_id' => (int)$line['item_id'],
                    ':store_id' => $storeId,
                    ':movement_type' => $movementType,
                    ':qty_in' => $qtyIn,
                    ':qty_out' => $qtyOut,
                    ':unit_cost' => $unitCost,
                    ':total_cost' => $totalCost,
                    ':reference_id' => $sessionId,
                    ':notes' => $auditNote,
                ]);

                // Keep the stored line variance in step with what was actually
                // applied, so reports reflect the real adjustment.
                try {
                    $pdo->prepare("
                        UPDATE stock_take_lines
                        SET variance_qty = :vq, variance_value = :vv
                        WHERE id = :id AND stock_take_id = :sid
                    ")->execute([
                        ':vq' => $variance,
                        ':vv' => $variance * $unitCost,
                        ':id' => (int)$line['id'],
                        ':sid' => $sessionId,
                    ]);
                } catch (Throwable $e) { /* non-fatal */ }

                st_recalc_avg_cost($pdo, (int)$line['item_id']);
            }

            $stmt = $pdo->prepare("
                UPDATE stock_take_sessions
                SET status = 'posted',
                    posted_by = :posted_by,
                    posted_at = NOW()
                WHERE id = :id
            ");
            $stmt->execute([
                ':posted_by' => $_SESSION['user_id'] ?? null,
                ':id' => $sessionId,
            ]);

            $pdo->commit();
            unset($_SESSION['stock_take_drift'][$sessionId]);

            $postedCount = count($toPost);
            st_flash('success',
                $overrideDrift && $drifted
                    ? ('Stock take posted with drift override. ' . $postedCount . ' adjustment(s) applied to reconcile each item to its counted quantity.')
                    : ('Stock take posted. ' . $postedCount . ' variance adjustment(s) created; each item now matches its counted quantity.')
            );
            header('Location: stock_take.php?session_id=' . $sessionId);
            exit;
        }

        if ($action === 'cancel_session') {
            $sessionId = (int)($_POST['session_id'] ?? 0);
            if ($sessionId <= 0) throw new RuntimeException('Invalid stock take session.');

            $stmt = $pdo->prepare("
                UPDATE stock_take_sessions
                SET status = 'cancelled'
                WHERE id = :id
                  AND status = 'draft'
            ");
            $stmt->execute([':id' => $sessionId]);

            st_flash('success', 'Stock take cancelled.');
            header('Location: stock_take.php');
            exit;
        }

        if ($action === 'add_line') {
            $sessionId = (int)($_POST['session_id'] ?? 0);
            if ($sessionId <= 0) throw new RuntimeException('Invalid stock take session.');

            $stmt = $pdo->prepare("SELECT * FROM stock_take_sessions WHERE id=:id LIMIT 1");
            $stmt->execute([':id' => $sessionId]);
            $session = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$session) throw new RuntimeException('Stock take session not found.');
            if ($session['status'] !== 'draft') throw new RuntimeException('Only draft stock takes can have lines added.');

            $itemId = (int)($_POST['add_item_id'] ?? 0);
            if ($itemId <= 0) throw new RuntimeException('Please select an item to add.');

            $chk = $pdo->prepare("SELECT id FROM stock_take_lines WHERE stock_take_id=:sid AND item_id=:iid LIMIT 1");
            $chk->execute([':sid' => $sessionId, ':iid' => $itemId]);
            if ($chk->fetchColumn()) {
                st_flash('warning', 'That item is already on this count sheet.');
                header('Location: stock_take.php?session_id=' . $sessionId);
                exit;
            }

            $systemQty = st_stock_balance($pdo, $itemId, (int)$session['store_id']);

            $itemStmt = $pdo->prepare("SELECT COALESCE(avg_cost, cost_price, 0) AS unit_cost FROM inventory_items WHERE id=:id LIMIT 1");
            $itemStmt->execute([':id' => $itemId]);
            $itemRow = $itemStmt->fetch(PDO::FETCH_ASSOC);
            $unitCost = (float)($itemRow['unit_cost'] ?? 0);

            $pdo->prepare("
                INSERT INTO stock_take_lines
                (stock_take_id, item_id, system_qty, counted_qty, variance_qty, unit_cost, variance_value, notes)
                VALUES (:sid, :iid, :system_qty, :counted_qty, 0, :unit_cost, 0, :notes)
            ")->execute([
                ':sid'         => $sessionId,
                ':iid'         => $itemId,
                ':system_qty'  => $systemQty,
                ':counted_qty' => $systemQty,
                ':unit_cost'   => $unitCost,
                ':notes'       => 'Manually added - not in location movements',
            ]);

            st_flash('success', 'Item added to count sheet. System balance is ' . number_format($systemQty, 4) . ' (may be 0 if never moved in this location).');
            header('Location: stock_take.php?session_id=' . $sessionId);
            exit;
        }

    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        st_flash('danger', $e->getMessage());
        header('Location: stock_take.php' . (!empty($_POST['session_id']) ? '?session_id=' . (int)$_POST['session_id'] : ''));
        exit;
    }
}

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

$sessionId = (int)($_GET['session_id'] ?? 0);
$session = null;
$lines = [];

if ($sessionId > 0) {
    try {
        $stmt = $pdo->prepare("
            SELECT sts.*, sl.location_name, sl.location_code
            FROM stock_take_sessions sts
            INNER JOIN store_locations sl ON sl.id = sts.store_id
            WHERE sts.id = :id
            LIMIT 1
        ");
        $stmt->execute([':id' => $sessionId]);
        $session = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;

        if ($session) {
            $stmt = $pdo->prepare("
                SELECT
                    stl.*,
                    ii.item_name,
                    ii.item_code,
                    c.category_name,
                    u.unit_code
                FROM stock_take_lines stl
                INNER JOIN inventory_items ii ON ii.id = stl.item_id
                LEFT JOIN inventory_item_categories c ON c.id = ii.category_id
                LEFT JOIN inventory_units u ON u.id = ii.unit_id
                WHERE stl.stock_take_id = :id
                ORDER BY c.category_name ASC, ii.item_name ASC
            ");
            $stmt->execute([':id' => $sessionId]);
            $lines = $stmt->fetchAll(PDO::FETCH_ASSOC);
        }
    } catch (Throwable $e) {
        $errors[] = 'Could not load stock take session: ' . $e->getMessage();
    }
}

$dateFrom = trim((string)($_GET['date_from'] ?? date('Y-m-01')));
$dateTo = trim((string)($_GET['date_to'] ?? date('Y-m-d')));
$status = trim((string)($_GET['status'] ?? ''));
$storeFilter = (int)($_GET['store_id'] ?? 0);

if (strtotime($dateFrom) === false) $dateFrom = date('Y-m-01');
if (strtotime($dateTo) === false) $dateTo = date('Y-m-d');

$where = "sts.stock_take_date BETWEEN :date_from AND :date_to";
$params = [':date_from' => $dateFrom, ':date_to' => $dateTo];

if ($status !== '') {
    $where .= " AND sts.status = :status";
    $params[':status'] = $status;
}
if ($storeFilter > 0) {
    $where .= " AND sts.store_id = :store_id";
    $params[':store_id'] = $storeFilter;
}

$sessions = [];
try {
    $stmt = $pdo->prepare("
        SELECT
            sts.*,
            sl.location_name,
            COUNT(stl.id) AS line_count,
            COALESCE(SUM(CASE WHEN ABS(stl.variance_qty) > 0.0001 THEN 1 ELSE 0 END),0) AS variance_lines,
            COALESCE(SUM(stl.variance_value),0) AS variance_value
        FROM stock_take_sessions sts
        INNER JOIN store_locations sl ON sl.id = sts.store_id
        LEFT JOIN stock_take_lines stl ON stl.stock_take_id = sts.id
        WHERE $where
        GROUP BY sts.id
        ORDER BY sts.created_at DESC, sts.id DESC
        LIMIT 200
    ");
    $stmt->execute($params);
    $sessions = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    $errors[] = 'Could not load stock take list: ' . $e->getMessage();
}

$summary = [
    'line_count' => count($lines),
    'variance_lines' => 0,
    'positive_qty' => 0,
    'negative_qty' => 0,
    'variance_value' => 0,
];
foreach ($lines as $line) {
    $var = (float)$line['variance_qty'];
    if (abs($var) > 0.0001) $summary['variance_lines']++;
    if ($var > 0) $summary['positive_qty'] += $var;
    if ($var < 0) $summary['negative_qty'] += abs($var);
    $summary['variance_value'] += (float)$line['variance_value'];
}

if (($_GET['export'] ?? '') === 'excel' && $session && $lines) {
    $exportMode = strtolower(trim((string)($_GET['export_mode'] ?? 'system')));
    if (!in_array($exportMode, ['blank', 'system', 'results'], true)) {
        $exportMode = 'system';
    }

    /*
       Results export scope:
       - all: export every saved count line, including zero variances.
       - variances: export only lines whose saved variance is non-zero.
    */
    $exportScope = strtolower(trim((string)($_GET['export_scope'] ?? 'all')));
    if (!in_array($exportScope, ['all', 'variances'], true)) {
        $exportScope = 'all';
    }

    $showSystemQuantities = in_array($exportMode, ['system', 'results'], true);
    $showSavedResults = ($exportMode === 'results');

    $exportLines = $lines;
    if ($showSavedResults && $exportScope === 'variances') {
        $exportLines = array_values(array_filter($lines, static function (array $line): bool {
            return abs((float)($line['variance_qty'] ?? 0)) > 0.0001;
        }));
    }

    $safeNo = preg_replace('/[^A-Za-z0-9_-]/', '_', (string)$session['stock_take_no']);
    if ($showSavedResults) {
        $modeSuffix = $exportScope === 'variances'
            ? 'variance_items_only'
            : 'all_counts_and_variances';
    } else {
        $modeSuffix = $showSystemQuantities ? 'with_system_qty' : 'blank';
    }
    $filename = 'stock_take_' . $safeNo . '_' . $modeSuffix . '_' . date('Ymd_His') . '.xls';

    header('Content-Type: application/vnd.ms-excel; charset=UTF-8');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Pragma: no-cache');
    header('Expires: 0');

    echo "\xEF\xBB\xBF";
    echo '<html><head><meta charset="UTF-8"><style>';
    echo 'body{font-family:Arial,sans-serif;} table{border-collapse:collapse;font-size:11px;width:100%;}';
    echo 'th{background:#1f2937;color:#fff;font-weight:bold;} th,td{border:1px solid #d1d5db;padding:6px;vertical-align:top;}';
    echo '.title{font-size:18px;font-weight:bold;margin-bottom:4px}.sub{color:#4b5563;margin-bottom:10px}.right{text-align:right}.editable{background:#fff7ed}.variance{background:#f3f4f6;font-weight:bold}.small{font-size:10px;color:#6b7280}';
    echo '</style></head><body>';
    echo '<div class="title">Stock Take Count Sheet</div>';
    $exportLabel = $showSavedResults
        ? ($exportScope === 'variances' ? 'Variance Items Only' : 'All Saved Counts')
        : ($showSystemQuantities ? 'With System Quantities' : 'Blank Count Sheet');

    echo '<div class="sub">Stock Take: ' . h($session['stock_take_no']) . ' | Store: ' . h($session['location_name']) . ' | Date: ' . h($session['stock_take_date']) . ' | Status: ' . h(ucwords($session['status'])) . ' | Export: ' . h($exportLabel) . '</div>';
    if ($showSavedResults) {
        if ($exportScope === 'variances') {
            echo '<div class="small">This report includes only items whose saved variance quantity is not zero.</div>';
        } else {
            echo '<div class="small">This report includes every saved physical count, including items with no variance.</div>';
        }
    } else {
        echo '<div class="small">Import instructions: edit only the orange Counted Qty and Notes columns, save the file, then import it back on the Stock Take page. Do not change Line ID / Item ID / Item Code.</div>';
    }
    if (!$showSystemQuantities) {
        echo '<div class="small">Blank mode hides system/count/variance quantities for blind physical counting.</div>';
    }
    echo '<br>';
    echo '<table>';
    echo '<thead><tr>';
    foreach (['Line ID','Item ID','Item Code','Item Name','Category','Unit','System Qty','Counted Qty','Variance Qty','Unit Cost','Variance Value','Notes'] as $head) {
        echo '<th>' . h($head) . '</th>';
    }
    echo '</tr></thead><tbody>';
    foreach ($exportLines as $line) {
        echo '<tr>';
        echo '<td>' . h((int)$line['id']) . '</td>';
        echo '<td>' . h((int)$line['item_id']) . '</td>';
        echo '<td>' . h($line['item_code'] ?: '') . '</td>';
        echo '<td>' . h($line['item_name'] ?: '') . '</td>';
        echo '<td>' . h($line['category_name'] ?: '') . '</td>';
        echo '<td>' . h($line['unit_code'] ?: '') . '</td>';
        echo '<td class="right">' . ($showSystemQuantities ? h(number_format((float)$line['system_qty'], 4, '.', '')) : '') . '</td>';
        echo '<td class="right editable">' . ($showSavedResults
            ? h(number_format((float)$line['counted_qty'], 4, '.', ''))
            : ($showSystemQuantities ? h(number_format((float)$line['system_qty'], 4, '.', '')) : '')) . '</td>';
        echo '<td class="right variance">' . ($showSavedResults
            ? h(number_format((float)$line['variance_qty'], 4, '.', ''))
            : ($showSystemQuantities ? h(number_format(0, 4, '.', '')) : '')) . '</td>';
        echo '<td class="right">' . ($showSystemQuantities ? h(number_format((float)$line['unit_cost'], 4, '.', '')) : '') . '</td>';
        echo '<td class="right variance">' . ($showSavedResults
            ? h(number_format((float)$line['variance_value'], 4, '.', ''))
            : ($showSystemQuantities ? h(number_format(0, 4, '.', '')) : '')) . '</td>';
        echo '<td class="editable">' . h($line['notes'] ?: '') . '</td>';
        echo '</tr>';
    }
    if (!$exportLines) {
        echo '<tr><td colspan="12" style="text-align:center;padding:18px;color:#6b7280;">No items matched the selected export option.</td></tr>';
    }
    echo '</tbody></table></body></html>';
    exit;
}

$flashes = st_get_flash();

function st_status_badge(string $status): string {
    if ($status === 'posted') return 'text-bg-success';
    if ($status === 'draft') return 'text-bg-warning';
    if ($status === 'cancelled') return 'text-bg-secondary';
    return 'text-bg-light';
}

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-clipboard-check"></i> Stores &amp; POS Inventory</div>
            <div class="hero-title mt-2">Stock Take</div>
            <div class="hero-subtitle mt-2">
                Count physical stock, compare with system balances, then post variance adjustments safely.
            </div>
        </div>
        <div class="col-lg-4 text-lg-end">
            <a href="stock_movements.php" class="btn btn-light me-2">
                <i class="bi bi-arrow-left-right me-2"></i>Movements
            </a>
            <a href="inventory_items.php" class="btn btn-outline-light">
                <i class="bi bi-box-seam me-2"></i>Items
            </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-4">
        <div class="card panel-card mb-4">
            <div class="card-header"><h5 class="mb-0">Create Stock Take</h5></div>
            <div class="card-body">
                <?php
                    $openDraftWarn = isset($_GET['open_draft_warning']) && !empty($_SESSION['stock_take_open_drafts']);
                    $odw = $openDraftWarn ? $_SESSION['stock_take_open_drafts'] : null;
                    $preselectStore = $odw ? (int)$odw['store_id'] : 0;
                ?>
                <?php if ($openDraftWarn): ?>
                    <div class="alert alert-warning">
                        <strong><i class="bi bi-exclamation-triangle me-1"></i>Open draft already exists for <?php echo h($odw['store_name']); ?>.</strong>
                        <ul class="mb-2 mt-2">
                            <?php foreach ($odw['drafts'] as $od): ?>
                                <li><?php echo h((string)$od['stock_take_no']); ?>
                                    &middot; created <?php echo h(date('d M Y H:i', strtotime((string)$od['created_at']))); ?></li>
                            <?php endforeach; ?>
                        </ul>
                        <div class="small mb-2">Counting two sheets against the same location at once can produce conflicting baselines. Finish or cancel the existing count first, or create anyway.</div>
                        <form method="post" onsubmit="return confirm('Create a second draft stock take for this location anyway?');">
                            <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                            <input type="hidden" name="action" value="create_session">
                            <input type="hidden" name="override_open_draft" value="1">
                            <input type="hidden" name="store_id" value="<?php echo (int)$odw['store_id']; ?>">
                            <input type="hidden" name="stock_take_date" value="<?php echo h((string)$odw['form']['stock_take_date']); ?>">
                            <input type="hidden" name="notes" value="<?php echo h((string)$odw['form']['notes']); ?>">
                            <input type="hidden" name="stock_scope" value="<?php echo h((string)$odw['form']['stock_scope']); ?>">
                            <button class="btn btn-warning btn-sm">
                                <i class="bi bi-plus-circle me-1"></i>Create anyway
                            </button>
                        </form>
                    </div>
                    <?php unset($_SESSION['stock_take_open_drafts']); ?>
                <?php endif; ?>
                <form method="post">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="create_session">

                    <div class="mb-3">
                        <label class="form-label">Stockholding Location</label>
                        <select name="store_id" class="form-select" required>
                            <option value="">Select stockholding location</option>
                            <?php foreach ($stores as $store): ?>
                                <option value="<?php echo (int)$store['id']; ?>"<?php echo ($preselectStore === (int)$store['id']) ? ' selected' : ''; ?>>
                                    <?php echo h($store['location_name']); ?>
                                    <?php echo !empty($store['location_code']) ? ' (' . h($store['location_code']) . ')' : ''; ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">The count sheet will be created for this location only.</div>
                    </div>

                    <div class="mb-3">
                        <label class="form-label">Items to Include</label>
                        <select name="stock_scope" class="form-select">
                            <option value="location_only" selected>Only items with stock activity in selected location</option>
                            <option value="all_active">All active stock items</option>
                        </select>
                        <div class="form-text">Use location-only for Bar Bulk, Bar, Kitchen, Curio, Spa, etc. Use all-active only for a brand-new location.</div>
                    </div>

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

                    <div class="mb-3">
                        <label class="form-label">Notes</label>
                        <textarea name="notes" class="form-control" rows="3" placeholder="Monthly stock count / shift handover etc."></textarea>
                    </div>

                    <button class="btn btn-primary w-100">
                        <i class="bi bi-plus-circle me-2"></i>Create Location Count Sheet
                    </button>
                </form>
            </div>
        </div>


        <div class="card panel-card mb-4">
            <div class="card-header"><h5 class="mb-0">Import Opening Stock by Location</h5></div>
            <div class="card-body">
                <form method="post" enctype="multipart/form-data" onsubmit="return confirm('Import this Stock On Hand file as OPENING stock movements by Storage Area?');">
                    <?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 Date</label>
                        <input type="date" name="opening_date" class="form-control" value="<?php echo h(date('Y-m-d')); ?>">
                    </div>

                    <div class="mb-3">
                        <label class="form-label">Stock On Hand File</label>
                        <input type="file" name="opening_file" class="form-control" accept=".xlsx,.xls,.csv,.txt,.html,.htm" required>
                        <div class="form-text">Uses Product, Product Description, Storage Area, Full Master Units, Total Smaller Units, Average Cost and Last Cost columns.</div>
                    </div>

                    <label class="d-flex align-items-start gap-2 small mb-3">
                        <input type="checkbox" name="replace_existing_opening" value="1" checked style="margin-top:3px">
                        <span>Replace previous OPENING_IMPORT movements for the imported locations before posting. Keep ticked to avoid doubling opening stock if you re-import.</span>
                    </label>

                    <button class="btn btn-dark w-100">
                        <i class="bi bi-upload me-2"></i>Import as Opening Stock
                    </button>
                </form>
            </div>
        </div>

        <div class="card panel-card">
            <div class="card-header"><h5 class="mb-0">Stock Take History</h5></div>
            <div class="card-body">
                <form method="get" class="row g-2 mb-3">
                    <div class="col-6">
                        <input type="date" name="date_from" class="form-control form-control-sm" value="<?php echo h($dateFrom); ?>">
                    </div>
                    <div class="col-6">
                        <input type="date" name="date_to" class="form-control form-control-sm" value="<?php echo h($dateTo); ?>">
                    </div>
                    <div class="col-6">
                        <select name="store_id" class="form-select form-select-sm">
                            <option value="0">All stores</option>
                            <?php foreach ($stores as $store): ?>
                                <option value="<?php echo (int)$store['id']; ?>" <?php echo $storeFilter === (int)$store['id'] ? 'selected' : ''; ?>>
                                    <?php echo h($store['location_name']); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-4">
                        <select name="status" class="form-select form-select-sm">
                            <option value="">All</option>
                            <option value="draft" <?php echo $status === 'draft' ? 'selected' : ''; ?>>Draft</option>
                            <option value="posted" <?php echo $status === 'posted' ? 'selected' : ''; ?>>Posted</option>
                            <option value="cancelled" <?php echo $status === 'cancelled' ? 'selected' : ''; ?>>Cancelled</option>
                        </select>
                    </div>
                    <div class="col-2 d-grid">
                        <button class="btn btn-sm btn-primary"><i class="bi bi-funnel"></i></button>
                    </div>
                </form>

                <div class="session-list">
                    <?php if (!$sessions): ?>
                        <div class="text-center text-muted py-4">No stock takes found.</div>
                    <?php else: ?>
                        <?php foreach ($sessions as $row): ?>
                            <a class="session-row <?php echo $sessionId === (int)$row['id'] ? 'active' : ''; ?>" href="stock_take.php?session_id=<?php echo (int)$row['id']; ?>">
                                <div>
                                    <strong><?php echo h($row['stock_take_no']); ?></strong>
                                    <div class="small text-muted"><?php echo h($row['location_name']); ?></div>

                                    <div class="small mt-2">
                                        <div>
                                            <span class="fw-semibold text-dark">Started:</span>
                                            <?php echo !empty($row['created_at'])
                                                ? h(date('d M Y H:i', strtotime((string)$row['created_at'])))
                                                : '<span class="text-muted">Not recorded</span>'; ?>
                                        </div>

                                        <div class="mt-1">
                                            <span class="fw-semibold <?php echo $row['status'] === 'posted' ? 'text-success' : 'text-muted'; ?>">Posted:</span>
                                            <?php if (!empty($row['posted_at'])): ?>
                                                <?php echo h(date('d M Y H:i', strtotime((string)$row['posted_at']))); ?>
                                            <?php else: ?>
                                                <span class="text-muted fst-italic">Not posted</span>
                                            <?php endif; ?>
                                        </div>
                                    </div>
                                </div>

                                <div class="text-end">
                                    <span class="badge <?php echo h(st_status_badge($row['status'])); ?>"><?php echo h(ucwords($row['status'])); ?></span>
                                    <div class="small text-muted mt-1"><?php echo (int)$row['variance_lines']; ?> var</div>
                                </div>
                            </a>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </div>
            </div>
        </div>
    </div>

    <div class="col-xl-8">
        <?php if (!$session): ?>
            <div class="card panel-card">
                <div class="card-body text-center py-5">
                    <i class="bi bi-clipboard-check display-3 text-muted"></i>
                    <h4 class="mt-3">No stock take selected</h4>
                    <p class="text-muted mb-0">Create a new count sheet or select a stock take from the history panel.</p>
                </div>
            </div>
        <?php else: ?>
            <div class="row g-4 mb-4">
                <div class="col-md-6 col-xl-3">
                    <div class="metric-card">
                        <div class="metric-icon bg-primary-subtle text-primary"><i class="bi bi-list-check"></i></div>
                        <div><div class="metric-label">Lines</div><div class="metric-value"><?php echo (int)$summary['line_count']; ?></div></div>
                    </div>
                </div>
                <div class="col-md-6 col-xl-3">
                    <div class="metric-card">
                        <div class="metric-icon bg-warning-subtle text-warning"><i class="bi bi-exclamation-triangle"></i></div>
                        <div><div class="metric-label">Variance Lines</div><div class="metric-value"><?php echo (int)$summary['variance_lines']; ?></div></div>
                    </div>
                </div>
                <div class="col-md-6 col-xl-3">
                    <div class="metric-card">
                        <div class="metric-icon bg-success-subtle text-success"><i class="bi bi-arrow-down-circle"></i></div>
                        <div><div class="metric-label">Over Count</div><div class="metric-value small-value"><?php echo qty_fmt($summary['positive_qty']); ?></div></div>
                    </div>
                </div>
                <div class="col-md-6 col-xl-3">
                    <div class="metric-card">
                        <div class="metric-icon bg-danger-subtle text-danger"><i class="bi bi-arrow-up-circle"></i></div>
                        <div><div class="metric-label">Short Count</div><div class="metric-value small-value"><?php echo qty_fmt($summary['negative_qty']); ?></div></div>
                    </div>
                </div>
            </div>

            <div class="card panel-card mb-4">
                <div class="card-header d-flex justify-content-between align-items-center">
                    <div>
                        <h5 class="mb-0"><?php echo h($session['stock_take_no']); ?></h5>
                        <div class="small text-muted">
                            <?php echo h($session['location_name']); ?> • <?php echo h($session['stock_take_date']); ?>
                        </div>
                    </div>
                    <div class="d-flex gap-2 align-items-center flex-wrap">
                        <a class="btn btn-sm btn-success" href="#" onclick="return exportStockCountSheet(<?php echo (int)$session['id']; ?>);">
                            <i class="bi bi-file-earmark-excel me-1"></i>Excel Count Sheet
                        </a>
                        <div class="btn-group btn-group-sm">
                            <button type="button"
                                    class="btn btn-outline-success dropdown-toggle"
                                    data-bs-toggle="dropdown"
                                    aria-expanded="false">
                                <i class="bi bi-file-earmark-spreadsheet me-1"></i>Export Counts &amp; Variances
                            </button>
                            <ul class="dropdown-menu dropdown-menu-end">
                                <li>
                                    <a class="dropdown-item"
                                       href="stock_take.php?session_id=<?php echo (int)$session['id']; ?>&amp;export=excel&amp;export_mode=results&amp;export_scope=all">
                                        <i class="bi bi-list-check me-2"></i>
                                        <strong>All Counted Items</strong>
                                        <div class="small text-muted">Includes zero and non-zero variances</div>
                                    </a>
                                </li>
                                <li><hr class="dropdown-divider"></li>
                                <li>
                                    <a class="dropdown-item"
                                       href="stock_take.php?session_id=<?php echo (int)$session['id']; ?>&amp;export=excel&amp;export_mode=results&amp;export_scope=variances">
                                        <i class="bi bi-exclamation-diamond me-2"></i>
                                        <strong>Variance Items Only</strong>
                                        <div class="small text-muted">Excludes items with zero variance</div>
                                    </a>
                                </li>
                            </ul>
                        </div>
                        <span class="badge <?php echo h(st_status_badge($session['status'])); ?>"><?php echo h(ucwords($session['status'])); ?></span>
                    </div>
                </div>
                <div class="card-body">
                    <?php if (!empty($session['notes'])): ?>
                        <div class="alert alert-info"><?php echo h($session['notes']); ?></div>
                    <?php endif; ?>

                    <?php if ($session['status'] === 'draft'): ?>
                    <div class="add-missing-item-panel mb-3">
                        <div class="add-missing-title"><i class="bi bi-plus-circle me-1"></i>Add item not on count sheet</div>
                        <div class="add-missing-body">
                            <div class="input-group input-group-sm">
                                <input type="text" id="addItemSearch" class="form-control" placeholder="Search item name or code..." autocomplete="off">
                                <button type="button" class="btn btn-outline-secondary" id="addItemSearchBtn">
                                    <i class="bi bi-search"></i>
                                </button>
                            </div>
                            <div id="addItemResults" class="add-item-results" style="display:none;"></div>
                        </div>
                    </div>
                    <?php endif; ?>

                    <?php if ($session['status'] === 'draft'): ?>
                        <form method="post" enctype="multipart/form-data" class="import-count-form mb-3" onsubmit="return confirm('Import physical counts from this file? Existing counted quantities will be updated.');">
                            <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                            <input type="hidden" name="action" value="import_counts">
                            <input type="hidden" name="session_id" value="<?php echo (int)$session['id']; ?>">
                            <div class="input-group input-group-sm">
                                <span class="input-group-text"><i class="bi bi-upload"></i></span>
                                <input type="file" name="count_file" class="form-control" accept=".xlsx,.xls,.html,.htm,.csv,.txt" required>
                                <button class="btn btn-outline-primary" type="submit">Import Physical Count</button>
                            </div>
                            <div class="small text-muted mt-1">Use the Excel count sheet export, update Counted Qty/Notes, then import it back before posting.</div>
                        </form>
                    <?php endif; ?>

                    <form method="post" id="stockTakeForm">
                        <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                        <input type="hidden" name="action" value="save_counts">
                        <input type="hidden" name="session_id" value="<?php echo (int)$session['id']; ?>">

                        <div class="stocktake-toolbar mb-3">
                            <div class="input-group">
                                <span class="input-group-text"><i class="bi bi-search"></i></span>
                                <input type="text" id="lineSearch" class="form-control" placeholder="Search item/code/category">
                            </div>
                            <?php if ($session['status'] === 'draft'): ?>
                                <button class="btn btn-primary">
                                    <i class="bi bi-save me-2"></i>Save Counts
                                </button>
                            <?php endif; ?>
                        </div>

                        <div class="table-responsive">
                            <table class="table table-modern align-middle mb-0" id="stockTakeTable">
                                <thead>
                                <tr>
                                    <th>Item</th>
                                    <th class="text-end">System Qty</th>
                                    <th class="text-end">Counted Qty</th>
                                    <th class="text-end">Variance</th>
                                    <th class="text-end">Unit Cost</th>
                                    <th class="text-end">Variance Value</th>
                                    <th>Notes</th>
                                </tr>
                                </thead>
                                <tbody>
                                <?php foreach ($lines as $line): ?>
                                    <?php
                                        $variance = (float)$line['variance_qty'];
                                        $rowClass = $variance > 0 ? 'table-success' : ($variance < 0 ? 'table-danger' : '');
                                    ?>
                                    <tr class="<?php echo h($rowClass); ?>"
                                        data-search="<?php echo h(strtolower(($line['item_name'] ?? '') . ' ' . ($line['item_code'] ?? '') . ' ' . ($line['category_name'] ?? ''))); ?>">
                                        <td>
                                            <strong><?php echo h($line['item_name']); ?></strong>
                                            <div class="small text-muted">
                                                <?php echo h($line['item_code'] ?: ''); ?>
                                                <?php if (!empty($line['category_name'])): ?> • <?php echo h($line['category_name']); ?><?php endif; ?>
                                                <?php if (!empty($line['unit_code'])): ?> • <?php echo h($line['unit_code']); ?><?php endif; ?>
                                            </div>
                                        </td>
                                        <td class="text-end"><?php echo qty_fmt($line['system_qty']); ?></td>
                                        <td class="text-end">
                                            <?php if ($session['status'] === 'draft'): ?>
                                                <input type="number"
                                                       name="counted_qty[<?php echo (int)$line['id']; ?>]"
                                                       class="form-control form-control-sm text-end count-input" data-count-input="1"
                                                       step="0.0001"
                                                       min="0"
                                                       inputmode="decimal"
                                                       value="<?php echo h(qty_fmt($line['counted_qty'])); ?>"
                                                       data-system="<?php echo h($line['system_qty']); ?>"
                                                       data-cost="<?php echo h($line['unit_cost']); ?>">
                                            <?php else: ?>
                                                <?php echo qty_fmt($line['counted_qty']); ?>
                                            <?php endif; ?>
                                        </td>
                                        <td class="text-end fw-bold variance-cell"><?php echo qty_fmt($line['variance_qty']); ?></td>
                                        <td class="text-end"><?php echo money_fmt($line['unit_cost']); ?></td>
                                        <td class="text-end fw-bold variance-value-cell"><?php echo money_fmt($line['variance_value']); ?></td>
                                        <td>
                                            <?php if ($session['status'] === 'draft'): ?>
                                                <input type="text"
                                                       name="line_notes[<?php echo (int)$line['id']; ?>]"
                                                       class="form-control form-control-sm"
                                                       value="<?php echo h($line['notes']); ?>"
                                                       placeholder="Reason">
                                            <?php else: ?>
                                                <?php echo h($line['notes'] ?: ''); ?>
                                            <?php endif; ?>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                    </form>
                </div>

                <?php if ($session['status'] === 'draft'): ?>
                    <div class="card-footer d-flex justify-content-between flex-wrap gap-2">
                        <form method="post" onsubmit="return confirm('Cancel this stock take?');">
                            <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                            <input type="hidden" name="action" value="cancel_session">
                            <input type="hidden" name="session_id" value="<?php echo (int)$session['id']; ?>">
                            <button class="btn btn-outline-danger">
                                <i class="bi bi-x-circle me-2"></i>Cancel Stock Take
                            </button>
                        </form>

                        <?php
                            $driftFlagged = isset($_GET['drift'])
                                && !empty($_SESSION['stock_take_drift'][(int)$session['id']]);
                            $driftRows = $driftFlagged ? $_SESSION['stock_take_drift'][(int)$session['id']] : array();
                        ?>
                        <?php if ($driftFlagged): ?>
                            <div class="alert alert-warning" style="flex-basis:100%;">
                                <strong><i class="bi bi-exclamation-triangle me-1"></i>Stock moved since this count sheet was created.</strong>
                                Posting now will adjust each item <em>to your counted quantity</em> against its current live balance.
                                Review the affected items, then either recount or post anyway:
                                <ul class="mb-0 mt-2">
                                    <?php foreach ($driftRows as $d): ?>
                                        <li>
                                            <strong><?php echo htmlspecialchars((string)$d['name']); ?></strong>:
                                            sheet showed <?php echo rtrim(rtrim(number_format((float)$d['frozen'], 4), '0'), '.'); ?>,
                                            live is now <?php echo rtrim(rtrim(number_format((float)$d['live'], 4), '0'), '.'); ?>
                                            (you counted <?php echo rtrim(rtrim(number_format((float)$d['counted'], 4), '0'), '.'); ?>)
                                        </li>
                                    <?php endforeach; ?>
                                </ul>
                            </div>
                            <form method="post" onsubmit="return confirm('Post anyway? Each item will be adjusted to your counted quantity against its CURRENT live balance. This cannot be edited afterwards.');">
                                <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                <input type="hidden" name="action" value="post_adjustments">
                                <input type="hidden" name="session_id" value="<?php echo (int)$session['id']; ?>">
                                <input type="hidden" name="override_drift" value="1">
                                <button class="btn btn-warning">
                                    <i class="bi bi-check2-circle me-2"></i>Post anyway (adjust to counted)
                                </button>
                            </form>
                        <?php endif; ?>

                        <form method="post" onsubmit="return confirm('Post stock take adjustments? Each item will be reconciled to your counted quantity. This creates stock movement rows and cannot be edited afterwards.');">
                            <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                            <input type="hidden" name="action" value="post_adjustments">
                            <input type="hidden" name="session_id" value="<?php echo (int)$session['id']; ?>">
                            <button class="btn btn-success">
                                <i class="bi bi-check2-circle me-2"></i>Post Adjustments
                            </button>
                        </form>
                    </div>
                <?php endif; ?>
            </div>

            <?php if ($session['status'] === 'posted'): ?>
                <div class="alert alert-success">
                    <strong>Posted:</strong> Adjustment movements have already been created for this stock take.
                    View them in <a href="stock_movements.php?store_id=<?php echo (int)$session['store_id']; ?>">Stock Movements</a>.
                </div>
            <?php endif; ?>
        <?php endif; ?>
    </div>
</div>

<style>
/* Ultra compact stock take layout */
.hero-band{padding:10px 14px!important;margin-bottom:8px!important}
.hero-title{font-size:1.25rem!important;line-height:1.1!important;margin-top:2px!important}
.hero-subtitle{font-size:.78rem!important;line-height:1.2!important;margin-top:2px!important;opacity:.92}
.page-eyebrow{font-size:.68rem!important;letter-spacing:.06em!important}
.hero-band .btn{padding:5px 9px!important;font-size:.78rem!important;border-radius:8px!important}
.row.g-4{--bs-gutter-x:.75rem!important;--bs-gutter-y:.75rem!important}
.row.g-4.mb-4{margin-bottom:8px!important;--bs-gutter-x:.65rem!important;--bs-gutter-y:.65rem!important}
.panel-card .card-header{padding:8px 11px!important}
.panel-card .card-body{padding:10px!important}
.panel-card .card-footer{padding:9px 11px!important}
.form-label{font-size:.7rem!important;margin-bottom:2px!important;font-weight:700!important}
.form-control,.form-select,.input-group-text{height:31px!important;min-height:31px!important;font-size:.8rem!important;padding:3px 7px!important;border-radius:8px!important}
textarea.form-control{height:auto!important;min-height:44px!important}
.btn{border-radius:8px}
.metric-card{padding:8px 10px!important;gap:6px!important;min-height:52px!important}
.metric-icon{width:30px!important;height:30px!important;border-radius:8px!important;font-size:12px!important}
.metric-label{font-size:.68rem!important;margin-bottom:1px!important}
.metric-value{font-size:.95rem!important;line-height:1.05!important}
.small-value{font-size:.95rem!important;letter-spacing:0!important}
.session-list{display:flex;flex-direction:column;gap:6px;max-height:520px;overflow:auto}
.session-row{display:flex;justify-content:space-between;gap:10px;text-decoration:none;color:inherit;border:1px solid rgba(15,23,42,.08);border-radius:12px;padding:8px 10px;background:#fff;transition:.15s ease}
.session-row:hover,.session-row.active{background:#eff6ff;border-color:#bfdbfe}
.stocktake-toolbar{display:flex;gap:8px;align-items:center}
.stocktake-toolbar .input-group{flex:1}
.import-count-form{background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:8px}
.count-input{min-width:105px}
#stockTakeTable thead th{position:sticky;top:0;z-index:10;background:#f8fafc!important;box-shadow:0 2px 0 rgba(15,23,42,.08);white-space:nowrap}
#stockTakeTable th,#stockTakeTable td{padding:6px 8px!important;font-size:.82rem;vertical-align:middle}
.table-responsive{max-height:calc(100vh - 310px);overflow:auto}
@media(max-width:768px){.stocktake-toolbar{flex-direction:column;align-items:stretch}.import-count-form .input-group{display:block}.import-count-form .form-control,.import-count-form .btn,.import-count-form .input-group-text{width:100%;margin-bottom:4px}}
.add-missing-item-panel{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:12px;overflow:hidden;margin-bottom:10px}
.add-missing-title{padding:6px 10px;font-size:.75rem;font-weight:800;color:#166534;text-transform:uppercase;letter-spacing:.04em;border-bottom:1px solid #bbf7d0}
.add-missing-body{padding:8px 10px}
.add-item-results{margin-top:6px;border:1px solid #d1fae5;border-radius:8px;background:#fff;max-height:240px;overflow-y:auto}
.add-item-row{display:flex;justify-content:space-between;align-items:center;padding:7px 10px;border-bottom:1px solid #f0fdf4;font-size:.82rem;gap:8px}
.add-item-row:last-child{border-bottom:0}
.add-item-name{font-weight:700;color:#0f172a}
.add-item-meta{font-size:.72rem;color:#64748b}
.add-item-row .btn{font-size:.72rem;padding:2px 8px;white-space:nowrap}
</style>

<script>
document.addEventListener('DOMContentLoaded', function(){
    /* Enter moves to next Counted Qty; Shift+Enter moves to previous. */
    var countInputs = Array.prototype.slice.call(document.querySelectorAll('.count-input[data-count-input="1"]'));
    countInputs.forEach(function(input, index) {
        input.addEventListener('keydown', function(e) {
            if (e.key !== 'Enter') return;
            e.preventDefault();
            var direction = e.shiftKey ? -1 : 1;
            var nextIndex = index + direction;
            while (nextIndex >= 0 && nextIndex < countInputs.length) {
                var next = countInputs[nextIndex];
                var row = next.closest('tr');
                if (!next.disabled && !next.readOnly && (!row || row.style.display !== 'none')) {
                    next.focus();
                    next.select();
                    return;
                }
                nextIndex += direction;
            }
            input.select();
        });
    });

    const search = document.getElementById('lineSearch');
    const rows = Array.from(document.querySelectorAll('#stockTakeTable tbody tr'));

    if (search) {
        search.addEventListener('input', function(){
            const q = this.value.trim().toLowerCase();
            rows.forEach(row => {
                row.style.display = !q || (row.dataset.search || '').includes(q) ? '' : 'none';
            });
        });
    }

    document.querySelectorAll('.count-input').forEach(input => {
        input.addEventListener('input', function(){
            const tr = this.closest('tr');
            const system = parseFloat(this.dataset.system || '0');
            const cost = parseFloat(this.dataset.cost || '0');
            const counted = parseFloat(this.value || '0');
            const variance = counted - system;
            const varianceValue = variance * cost;

            const varCell = tr.querySelector('.variance-cell');
            const valCell = tr.querySelector('.variance-value-cell');

            if (varCell) varCell.textContent = variance.toFixed(4);
            if (valCell) valCell.textContent = varianceValue.toFixed(2);

            tr.classList.remove('table-success','table-danger');
            if (variance > 0.0001) tr.classList.add('table-success');
            if (variance < -0.0001) tr.classList.add('table-danger');
        });
    });
    // Add missing item search
    var addSearch = document.getElementById('addItemSearch');
    var addResults = document.getElementById('addItemResults');
    var sessionIdHidden = document.querySelector('input[name="session_id"]');
    var sessionIdVal = sessionIdHidden ? sessionIdHidden.value : '';

    function stEscapeHtml(value) {
        return String(value == null ? '' : value).replace(/[&<>"']/g, function(ch) {
            return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'})[ch];
        });
    }

    function csrfInputsHtml() {
        var html = '';
        document.querySelectorAll('input[type="hidden"]').forEach(function(inp){
            var name = inp.getAttribute('name') || '';
            if (!name) return;
            if (name.toLowerCase().indexOf('csrf') !== -1 || name === '_token' || name === 'token') {
                html += '<input type="hidden" name="' + stEscapeHtml(name) + '" value="' + stEscapeHtml(inp.value || '') + '">';
            }
        });
        return html;
    }

    function renderAddResults(items) {
        if (!addResults) return;

        if (!items || !items.length) {
            addResults.innerHTML = '<div class="add-item-row"><span class="add-item-meta">No items found. Try item code, barcode, or part of the item name. Items already on this count sheet are hidden.</span></div>';
        } else {
            addResults.innerHTML = items.map(function(item) {
                return '<div class="add-item-row">'
                    + '<div>'
                    + '<div class="add-item-name">' + stEscapeHtml(item.item_name || '') + '</div>'
                    + '<div class="add-item-meta">' + stEscapeHtml(item.item_code || '') + (item.category_name ? ' &bull; ' + stEscapeHtml(item.category_name) : '') + '</div>'
                    + '</div>'
                    + '<form method="post" style="margin:0">'
                    + csrfInputsHtml()
                    + '<input type="hidden" name="action" value="add_line">'
                    + '<input type="hidden" name="session_id" value="' + stEscapeHtml(sessionIdVal) + '">'
                    + '<input type="hidden" name="add_item_id" value="' + stEscapeHtml(item.id) + '">'
                    + '<button class="btn btn-sm btn-success">Add</button>'
                    + '</form>'
                    + '</div>';
            }).join('');
        }
        addResults.style.display = '';
    }

    function runAddSearch() {
        if (!addSearch || !addResults) return;

        var q = addSearch.value.trim();
        if (q.length < 2) {
            addResults.style.display = 'none';
            addResults.innerHTML = '';
            return;
        }

        addResults.style.display = '';
        addResults.innerHTML = '<div class="add-item-row"><span class="add-item-meta">Searching...</span></div>';

        var fd = new FormData();
        fd.append('action', 'search_items');
        fd.append('session_id', sessionIdVal);
        fd.append('q', q);

        fetch('stock_take.php', {
            method: 'POST',
            body: fd,
            credentials: 'same-origin',
            headers: {'X-Requested-With': 'XMLHttpRequest'}
        })
        .then(function(r) {
            return r.text().then(function(txt) {
                if (!r.ok) throw new Error('HTTP ' + r.status + ': ' + txt.substring(0, 200));
                try {
                    return JSON.parse(txt);
                } catch (e) {
                    throw new Error('Search returned non-JSON response: ' + txt.substring(0, 200));
                }
            });
        })
        .then(renderAddResults)
        .catch(function(err) {
            addResults.style.display = '';
            addResults.innerHTML = '<div class="add-item-row"><span class="add-item-meta text-danger">Search failed: ' + stEscapeHtml(err.message || err) + '</span></div>';
        });
    }

    if (addSearch) {
        var addTimer;
        addSearch.addEventListener('input', function() {
            clearTimeout(addTimer);
            addTimer = setTimeout(runAddSearch, 250);
        });
        addSearch.addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                runAddSearch();
            }
        });

        var addBtn = document.getElementById('addItemSearchBtn');
        if (addBtn) {
            addBtn.addEventListener('click', function(e) {
                e.preventDefault();
                runAddSearch();
            });
        }
    }

});

function exportStockCountSheet(sessionId) {
    const withSystem = confirm('Export stock count sheet WITH system quantities?\n\nOK = With system quantities\nCancel = Blank count sheet');
    const mode = withSystem ? 'system' : 'blank';
    window.location.href = 'stock_take.php?session_id=' + encodeURIComponent(sessionId) + '&export=excel&export_mode=' + encodeURIComponent(mode);
    return false;
}
</script>

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