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

$pageTitle = 'Internal Requisitions';

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('ir_table_exists')) {
    function ir_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('ir_column_exists')) {
    function ir_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('ir_flash')) {
    function ir_flash(string $type, string $message): void {
        $_SESSION['internal_requisition_flash'][] = ['type' => $type, 'message' => $message];
    }
}
if (!function_exists('ir_get_flash')) {
    function ir_get_flash(): array {
        $items = $_SESSION['internal_requisition_flash'] ?? [];
        unset($_SESSION['internal_requisition_flash']);
        return $items;
    }
}
if (!function_exists('ir_next_req_no')) {
    function ir_next_req_no(PDO $pdo): string {
        $prefix = 'IR-' . date('Ymd') . '-';
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM internal_requisitions WHERE requisition_no LIKE :prefix");
        $stmt->execute([':prefix' => $prefix . '%']);
        return $prefix . str_pad(((int)$stmt->fetchColumn()) + 1, 4, '0', STR_PAD_LEFT);
    }
}
if (!function_exists('ir_next_batch_no')) {
    function ir_next_batch_no(): string {
        return 'SM-' . date('Ymd-His') . '-' . strtoupper(substr(bin2hex(random_bytes(3)), 0, 6));
    }
}
if (!function_exists('ir_stock_balance')) {
    function ir_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('ir_recalculate_avg_cost')) {
    function ir_recalculate_avg_cost(PDO $pdo, int $itemId): void {
        if (!ir_table_exists($pdo, 'inventory_items')) return;
        if (!ir_column_exists($pdo, 'inventory_items', 'avg_cost')) return;

        $stmt = $pdo->prepare("SELECT COALESCE(SUM(qty_in),0) AS total_in_qty, COALESCE(SUM(qty_in * unit_cost),0) AS total_in_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['total_in_qty'] ?? 0);
        $cost = (float)($row['total_in_cost'] ?? 0);
        if ($qty > 0) {
            $stmt = $pdo->prepare("UPDATE inventory_items SET avg_cost = :avg_cost WHERE id = :id");
            $stmt->execute([':avg_cost' => $cost / $qty, ':id' => $itemId]);
        }
    }
}
if (!function_exists('ir_current_user_id')) {
    function ir_current_user_id(): ?int {
        foreach (['user_id', 'id', 'UserID', 'userid'] as $key) {
            if (isset($_SESSION[$key]) && (int)$_SESSION[$key] > 0) return (int)$_SESSION[$key];
        }
        if (isset($_SESSION['user']) && is_array($_SESSION['user'])) {
            foreach (['id', 'user_id', 'UserID'] as $key) {
                if (isset($_SESSION['user'][$key]) && (int)$_SESSION['user'][$key] > 0) return (int)$_SESSION['user'][$key];
            }
        }
        return null;
    }
}
if (!function_exists('ir_item_option_text')) {
    function ir_item_option_text(array $item): string {
        $txt = (string)($item['item_name'] ?? '');
        if (!empty($item['item_code'])) $txt .= ' - ' . (string)$item['item_code'];
        if (!empty($item['unit_code'])) $txt .= ' (' . (string)$item['unit_code'] . ')';
        return $txt;
    }
}

if (!function_exists('ir_get_conversion_for_destination')) {
    function ir_get_conversion_for_destination(PDO $pdo, int $destinationItemId): ?array {
        if ($destinationItemId <= 0 || !ir_table_exists($pdo, 'inventory_item_conversions')) {
            return null;
        }

        $stmt = $pdo->prepare("
            SELECT
                c.*,
                src.item_name AS source_item_name,
                src.item_code AS source_item_code,
                src.avg_cost AS source_avg_cost,
                src.cost_price AS source_cost_price,
                dst.item_name AS destination_item_name,
                dst.item_code AS destination_item_code,
                su.unit_code AS source_unit_code,
                du.unit_code AS destination_unit_code
            FROM inventory_item_conversions c
            INNER JOIN inventory_items src ON src.id = c.source_item_id
            INNER JOIN inventory_items dst ON dst.id = c.destination_item_id
            LEFT JOIN inventory_units su ON su.id = src.unit_id
            LEFT JOIN inventory_units du ON du.id = dst.unit_id
            WHERE c.destination_item_id = :destination_item_id
              AND c.is_active = 1
              AND src.is_active = 1
              AND dst.is_active = 1
            ORDER BY c.id ASC
            LIMIT 1
        ");
        $stmt->execute([':destination_item_id' => $destinationItemId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        return $row ?: null;
    }
}

if (!function_exists('ir_conversion_factor')) {
    function ir_conversion_factor(array $conversion): float {
        $sourceQty = (float)($conversion['source_qty'] ?? 0);
        $destinationQty = (float)($conversion['destination_qty'] ?? 0);
        if ($sourceQty <= 0 || $destinationQty <= 0) {
            return 1.0;
        }
        return $destinationQty / $sourceQty;
    }
}

if (!function_exists('ir_calculate_conversion_issue')) {
    function ir_calculate_conversion_issue(array $conversion, float $requestedDestinationQty): array {
        $factor = ir_conversion_factor($conversion);
        if ($factor <= 0) $factor = 1.0;

        $destinationReceiveQty = max(0, $requestedDestinationQty);
        $sourceIssueQty = $destinationReceiveQty / $factor;

        $allowFractional = (int)($conversion['allow_fractional_source'] ?? 0) === 1;
        $roundSourceUp = (int)($conversion['round_source_up'] ?? 0) === 1;

        if (!$allowFractional) {
            if ($roundSourceUp && $sourceIssueQty > 0) {
                $sourceIssueQty = ceil($sourceIssueQty - 0.0000001);
                $destinationReceiveQty = $sourceIssueQty * $factor;
            } else {
                $nearestWhole = round($sourceIssueQty);
                if (abs($sourceIssueQty - $nearestWhole) > 0.0001) {
                    $label = trim((string)($conversion['conversion_name'] ?? ''));
                    if ($label === '') {
                        $label = 'converted item';
                    }
                    throw new RuntimeException(
                        'Qty to Supply for ' . $label . ' must be a full source unit multiple. ' .
                        'Use multiples of ' . number_format($factor, 4, '.', '') . ' destination units.'
                    );
                }
                $sourceIssueQty = $nearestWhole;
            }
        }

        return [
            'source_issue_qty' => round($sourceIssueQty, 4),
            'destination_receive_qty' => round($destinationReceiveQty, 4),
            'conversion_factor' => round($factor, 6),
        ];
    }
}

if (!function_exists('ir_conversion_label')) {
    function ir_conversion_label(array $conversion): string {
        $name = trim((string)($conversion['conversion_name'] ?? ''));
        if ($name !== '') return $name;

        $src = trim((string)($conversion['source_item_name'] ?? 'Source item'));
        $dst = trim((string)($conversion['destination_item_name'] ?? 'Destination item'));
        $srcUnit = trim((string)($conversion['source_unit_code'] ?? ''));
        $dstUnit = trim((string)($conversion['destination_unit_code'] ?? ''));

        return number_format((float)$conversion['source_qty'], 4, '.', '') . ' ' . $srcUnit . ' ' . $src .
            ' = ' . number_format((float)$conversion['destination_qty'], 4, '.', '') . ' ' . $dstUnit . ' ' . $dst;
    }
}

if (!function_exists('ir_item_cost')) {
    function ir_item_cost(PDO $pdo, int $itemId): float {
        $stmt = $pdo->prepare("SELECT COALESCE(NULLIF(avg_cost,0), cost_price, 0) FROM inventory_items WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $itemId]);
        return (float)$stmt->fetchColumn();
    }
}

$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),
        INDEX idx_store_location_active (is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $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),
        INDEX idx_inventory_item_active (is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS stock_movements (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        batch_no VARCHAR(40) NULL,
        line_no INT UNSIGNED NOT NULL DEFAULT 1,
        item_id INT UNSIGNED NOT NULL,
        store_id INT UNSIGNED NOT NULL,
        destination_type VARCHAR(30) NULL,
        destination_store_id INT UNSIGNED NULL,
        destination_room_id INT UNSIGNED NULL,
        destination_name VARCHAR(180) NULL,
        conversion_id INT UNSIGNED NULL,
        source_item_id INT UNSIGNED NULL,
        destination_item_id INT UNSIGNED NULL,
        source_issue_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        destination_receive_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        conversion_factor DECIMAL(14,6) NOT NULL DEFAULT 1.000000,
        conversion_label VARCHAR(180) 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_batch (batch_no),
        INDEX idx_stock_item_store (item_id, store_id),
        INDEX idx_stock_movement_date (movement_date),
        INDEX idx_stock_reference (reference_type, reference_id),
        INDEX idx_stock_destination (destination_type, destination_store_id, destination_room_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $stockAlterCols = [
        'batch_no' => "ALTER TABLE stock_movements ADD COLUMN batch_no VARCHAR(40) NULL AFTER id",
        'line_no' => "ALTER TABLE stock_movements ADD COLUMN line_no INT UNSIGNED NOT NULL DEFAULT 1 AFTER batch_no",
        'destination_type' => "ALTER TABLE stock_movements ADD COLUMN destination_type VARCHAR(30) NULL AFTER store_id",
        'destination_store_id' => "ALTER TABLE stock_movements ADD COLUMN destination_store_id INT UNSIGNED NULL AFTER destination_type",
        'destination_room_id' => "ALTER TABLE stock_movements ADD COLUMN destination_room_id INT UNSIGNED NULL AFTER destination_store_id",
        'destination_name' => "ALTER TABLE stock_movements ADD COLUMN destination_name VARCHAR(180) NULL AFTER destination_room_id",
        'conversion_id' => "ALTER TABLE stock_movements ADD COLUMN conversion_id INT UNSIGNED NULL AFTER destination_name",
        'source_item_id' => "ALTER TABLE stock_movements ADD COLUMN source_item_id INT UNSIGNED NULL AFTER conversion_id",
        'destination_item_id' => "ALTER TABLE stock_movements ADD COLUMN destination_item_id INT UNSIGNED NULL AFTER source_item_id",
        'source_issue_qty' => "ALTER TABLE stock_movements ADD COLUMN source_issue_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER destination_item_id",
        'destination_receive_qty' => "ALTER TABLE stock_movements ADD COLUMN destination_receive_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER source_issue_qty",
        'conversion_factor' => "ALTER TABLE stock_movements ADD COLUMN conversion_factor DECIMAL(14,6) NOT NULL DEFAULT 1.000000 AFTER destination_receive_qty",
        'conversion_label' => "ALTER TABLE stock_movements ADD COLUMN conversion_label VARCHAR(180) NULL AFTER conversion_factor",
    ];
    foreach ($stockAlterCols as $col => $sql) {
        if (!ir_column_exists($pdo, 'stock_movements', $col)) $pdo->exec($sql);
    }

    $pdo->exec("CREATE TABLE IF NOT EXISTS internal_requisitions (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        requisition_no VARCHAR(40) NOT NULL,
        request_store_id INT UNSIGNED NOT NULL,
        source_store_id INT UNSIGNED NOT NULL,
        requisition_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        required_date DATE NULL,
        status ENUM('DRAFT','SUBMITTED','APPROVED','POSTED','REJECTED','CANCELLED') NOT NULL DEFAULT 'SUBMITTED',
        priority ENUM('LOW','NORMAL','HIGH','URGENT') NOT NULL DEFAULT 'NORMAL',
        requested_by BIGINT UNSIGNED NULL,
        approved_by BIGINT UNSIGNED NULL,
        approved_at DATETIME NULL,
        posted_by BIGINT UNSIGNED NULL,
        posted_at DATETIME NULL,
        posted_batch_no VARCHAR(40) NULL,
        fulfilment_status VARCHAR(30) NOT NULL DEFAULT 'PENDING',
        notes TEXT NULL,
        rejection_reason TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_internal_requisition_no (requisition_no),
        INDEX idx_ir_status (status),
        INDEX idx_ir_stores (request_store_id, source_store_id),
        INDEX idx_ir_date (requisition_date)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    /*
       Self-healing fix for older installs:
       Previous versions of this page used different status enum values
       such as PENDING / PARTIAL / FULFILLED. MySQL throws
       "Data truncated for column status" when the PHP tries to save
       SUBMITTED / POSTED into an old enum. Keep all legacy + current
       values so the page can run without manual SQL repairs.
    */
    if (ir_column_exists($pdo, 'internal_requisitions', 'status')) {
        $pdo->exec("
            ALTER TABLE internal_requisitions
            MODIFY COLUMN status ENUM(
                'DRAFT',
                'PENDING',
                'SUBMITTED',
                'APPROVED',
                'PARTIAL',
                'FULFILLED',
                'POSTED',
                'REJECTED',
                'CANCELLED'
            ) NOT NULL DEFAULT 'SUBMITTED'
        ");
        $pdo->exec("
            UPDATE internal_requisitions
            SET status = 'SUBMITTED'
            WHERE status IS NULL OR status = ''
        ");
    }


    $pdo->exec("CREATE TABLE IF NOT EXISTS internal_requisition_lines (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        requisition_id BIGINT UNSIGNED NOT NULL,
        line_no INT UNSIGNED NOT NULL DEFAULT 1,
        item_id INT UNSIGNED NOT NULL,
        requested_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        approved_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        issued_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        shortfall_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        unit_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        line_status VARCHAR(30) NOT NULL DEFAULT 'PENDING',
        line_notes TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX idx_irl_req (requisition_id),
        INDEX idx_irl_item (item_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_item_conversions (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        source_item_id INT UNSIGNED NOT NULL,
        destination_item_id INT UNSIGNED NOT NULL,
        source_qty DECIMAL(14,4) NOT NULL DEFAULT 1.0000,
        destination_qty DECIMAL(14,4) NOT NULL DEFAULT 1.0000,
        allow_fractional_source TINYINT(1) NOT NULL DEFAULT 0,
        round_source_up TINYINT(1) NOT NULL DEFAULT 0,
        conversion_name VARCHAR(180) NULL,
        notes TEXT NULL,
        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_conversion (source_item_id, destination_item_id),
        INDEX idx_conversion_source (source_item_id),
        INDEX idx_conversion_destination (destination_item_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    foreach ([
        ['TOT','Tot / Shot'],
        ['SERVE','Serving'],
        ['GLASS','Glass']
    ] as $unitRow) {
        $stmtUnit = $pdo->prepare("INSERT IGNORE INTO inventory_units (unit_code, unit_name) VALUES (:code, :name)");
        $stmtUnit->execute([':code' => $unitRow[0], ':name' => $unitRow[1]]);
    }

    $reqAlterCols = [
        'priority' => "ALTER TABLE internal_requisitions ADD COLUMN priority ENUM('LOW','NORMAL','HIGH','URGENT') NOT NULL DEFAULT 'NORMAL' AFTER status",
        'approved_by' => "ALTER TABLE internal_requisitions ADD COLUMN approved_by BIGINT UNSIGNED NULL AFTER requested_by",
        'approved_at' => "ALTER TABLE internal_requisitions ADD COLUMN approved_at DATETIME NULL AFTER approved_by",
        'posted_by' => "ALTER TABLE internal_requisitions ADD COLUMN posted_by BIGINT UNSIGNED NULL AFTER approved_at",
        'posted_at' => "ALTER TABLE internal_requisitions ADD COLUMN posted_at DATETIME NULL AFTER posted_by",
        'posted_batch_no' => "ALTER TABLE internal_requisitions ADD COLUMN posted_batch_no VARCHAR(40) NULL AFTER posted_at",
        'fulfilment_status' => "ALTER TABLE internal_requisitions ADD COLUMN fulfilment_status VARCHAR(30) NOT NULL DEFAULT 'PENDING' AFTER posted_batch_no",
        'rejection_reason' => "ALTER TABLE internal_requisitions ADD COLUMN rejection_reason TEXT NULL AFTER notes",
    ];
    foreach ($reqAlterCols as $col => $sql) {
        if (!ir_column_exists($pdo, 'internal_requisitions', $col)) $pdo->exec($sql);
    }

    $lineAlterCols = [
        'approved_qty' => "ALTER TABLE internal_requisition_lines ADD COLUMN approved_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER requested_qty",
        'issued_qty' => "ALTER TABLE internal_requisition_lines ADD COLUMN issued_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER approved_qty",
        'shortfall_qty' => "ALTER TABLE internal_requisition_lines ADD COLUMN shortfall_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER issued_qty",
        'unit_cost' => "ALTER TABLE internal_requisition_lines ADD COLUMN unit_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER issued_qty",
        'line_status' => "ALTER TABLE internal_requisition_lines ADD COLUMN line_status VARCHAR(30) NOT NULL DEFAULT 'PENDING' AFTER unit_cost",
        'line_notes' => "ALTER TABLE internal_requisition_lines ADD COLUMN line_notes TEXT NULL AFTER line_status",
        'source_item_id' => "ALTER TABLE internal_requisition_lines ADD COLUMN source_item_id INT UNSIGNED NULL AFTER item_id",
        'destination_item_id' => "ALTER TABLE internal_requisition_lines ADD COLUMN destination_item_id INT UNSIGNED NULL AFTER source_item_id",
        'conversion_id' => "ALTER TABLE internal_requisition_lines ADD COLUMN conversion_id INT UNSIGNED NULL AFTER destination_item_id",
        'source_issue_qty' => "ALTER TABLE internal_requisition_lines ADD COLUMN source_issue_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER conversion_id",
        'destination_receive_qty' => "ALTER TABLE internal_requisition_lines ADD COLUMN destination_receive_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000 AFTER source_issue_qty",
        'conversion_factor' => "ALTER TABLE internal_requisition_lines ADD COLUMN conversion_factor DECIMAL(14,6) NOT NULL DEFAULT 1.000000 AFTER destination_receive_qty",
        'conversion_label' => "ALTER TABLE internal_requisition_lines ADD COLUMN conversion_label VARCHAR(180) NULL AFTER conversion_factor",
    ];
    foreach ($lineAlterCols as $col => $sql) {
        if (!ir_column_exists($pdo, 'internal_requisition_lines', $col)) $pdo->exec($sql);
    }
} catch (Throwable $e) {
    $errors[] = 'Could not prepare requisition tables: ' . $e->getMessage();
}

$stores = [];
$items = [];
$stockAvailabilityByStore = [];

try {
    $stores = $pdo->query("SELECT * FROM store_locations WHERE is_active = 1 ORDER BY location_name ASC")->fetchAll(PDO::FETCH_ASSOC);
    $items = $pdo->query("SELECT ii.*, c.category_name, u.unit_code FROM inventory_items ii LEFT JOIN inventory_item_categories c ON c.id = ii.category_id LEFT JOIN inventory_units u ON u.id = ii.unit_id WHERE ii.is_active = 1 AND ii.is_stock_item = 1 ORDER BY c.category_name ASC, ii.item_name ASC")->fetchAll(PDO::FETCH_ASSOC);

    $stmt = $pdo->query("SELECT sm.store_id, sm.item_id, COALESCE(SUM(sm.qty_in - sm.qty_out),0) AS balance_qty FROM stock_movements sm INNER JOIN inventory_items ii ON ii.id = sm.item_id WHERE ii.is_active = 1 AND ii.is_stock_item = 1 GROUP BY sm.store_id, sm.item_id");
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $stockRow) {
        $stockAvailabilityByStore[(int)$stockRow['store_id']][(int)$stockRow['item_id']] = (float)$stockRow['balance_qty'];
    }
} catch (Throwable $e) {
    $errors[] = 'Could not load requisition form data: ' . $e->getMessage();
}

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

        if ($action === 'create_requisition') {
            $requestStoreId = (int)($_POST['request_store_id'] ?? 0);
            $sourceStoreId = (int)($_POST['source_store_id'] ?? 0);
            $requiredDate = trim((string)($_POST['required_date'] ?? ''));
            $priority = strtoupper(trim((string)($_POST['priority'] ?? 'NORMAL')));
            $notes = trim((string)($_POST['notes'] ?? ''));
            $itemIds = $_POST['item_id'] ?? [];
            $qtys = $_POST['requested_qty'] ?? [];
            $lineNotes = $_POST['line_notes'] ?? [];

            if (!is_array($itemIds)) $itemIds = [$itemIds];
            if (!is_array($qtys)) $qtys = [$qtys];
            if (!is_array($lineNotes)) $lineNotes = [$lineNotes];
            if ($requestStoreId <= 0) throw new RuntimeException('Please select the requesting store.');
            if ($sourceStoreId <= 0) throw new RuntimeException('Please select the source store.');
            if ($requestStoreId === $sourceStoreId) throw new RuntimeException('Requesting store and source store cannot be the same.');
            if (!in_array($priority, ['LOW','NORMAL','HIGH','URGENT'], true)) $priority = 'NORMAL';
            if ($requiredDate !== '' && strtotime($requiredDate) === false) $requiredDate = '';

            $lines = [];
            foreach ($itemIds as $idx => $rawItemId) {
                $itemId = (int)$rawItemId;
                $qty = (float)($qtys[$idx] ?? 0);
                $lineNote = trim((string)($lineNotes[$idx] ?? ''));
                if ($itemId <= 0 && $qty <= 0) continue;
                if ($itemId <= 0) throw new RuntimeException('One requisition line has no item selected.');
                if ($qty <= 0) throw new RuntimeException('Requested quantity must be greater than zero on every line.');

                $stmt = $pdo->prepare("SELECT id, cost_price, avg_cost FROM inventory_items WHERE id = :id AND is_active = 1 AND is_stock_item = 1 LIMIT 1");
                $stmt->execute([':id' => $itemId]);
                $item = $stmt->fetch(PDO::FETCH_ASSOC);
                if (!$item) throw new RuntimeException('Inventory item not found or inactive.');

                $unitCost = (float)($item['avg_cost'] ?: $item['cost_price']);
                $lines[] = ['item_id' => $itemId, 'qty' => $qty, 'unit_cost' => $unitCost, 'note' => $lineNote];
            }
            if (!$lines) throw new RuntimeException('Please add at least one item line.');

            $pdo->beginTransaction();
            $reqNo = ir_next_req_no($pdo);

            $stmt = $pdo->prepare("INSERT INTO internal_requisitions (requisition_no, request_store_id, source_store_id, requisition_date, required_date, status, priority, requested_by, notes) VALUES (:requisition_no, :request_store_id, :source_store_id, NOW(), :required_date, 'SUBMITTED', :priority, :requested_by, :notes)");
            $stmt->execute([
                ':requisition_no' => $reqNo,
                ':request_store_id' => $requestStoreId,
                ':source_store_id' => $sourceStoreId,
                ':required_date' => $requiredDate !== '' ? date('Y-m-d', strtotime($requiredDate)) : null,
                ':priority' => $priority,
                ':requested_by' => $userId,
                ':notes' => $notes !== '' ? $notes : null,
            ]);
            $reqId = (int)$pdo->lastInsertId();

            $insertLine = $pdo->prepare("INSERT INTO internal_requisition_lines (requisition_id, line_no, item_id, requested_qty, approved_qty, issued_qty, shortfall_qty, unit_cost, line_status, line_notes) VALUES (:requisition_id, :line_no, :item_id, :requested_qty, :approved_qty, 0, 0, :unit_cost, 'PENDING', :line_notes)");
            $lineNo = 1;
            foreach ($lines as $line) {
                $insertLine->execute([
                    ':requisition_id' => $reqId,
                    ':line_no' => $lineNo,
                    ':item_id' => (int)$line['item_id'],
                    ':requested_qty' => (float)$line['qty'],
                    ':approved_qty' => (float)$line['qty'],
                    ':unit_cost' => (float)$line['unit_cost'],
                    ':line_notes' => $line['note'] !== '' ? $line['note'] : null,
                ]);
                $lineNo++;
            }

            $pdo->commit();
            ir_flash('success', 'Internal requisition created successfully: ' . $reqNo);
            header('Location: internal_requisition.php');
            exit;
        }

        if ($action === 'approve_requisition' || $action === 'post_requisition') {
            $reqId = (int)($_POST['id'] ?? 0);
            if ($reqId <= 0) throw new RuntimeException('Invalid requisition selected.');

            $pdo->beginTransaction();

            $stmt = $pdo->prepare("SELECT r.*, fs.location_name AS source_store_name, ts.location_name AS request_store_name FROM internal_requisitions r INNER JOIN store_locations fs ON fs.id = r.source_store_id INNER JOIN store_locations ts ON ts.id = r.request_store_id WHERE r.id = :id FOR UPDATE");
            $stmt->execute([':id' => $reqId]);
            $req = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$req) throw new RuntimeException('Requisition not found.');
            if (in_array((string)$req['status'], ['POSTED','REJECTED','CANCELLED'], true)) {
                throw new RuntimeException('This requisition cannot be approved or posted because it is already ' . $req['status'] . '.');
            }

            $stmt = $pdo->prepare("SELECT l.*, ii.item_name, ii.item_code, ii.cost_price, ii.avg_cost FROM internal_requisition_lines l INNER JOIN inventory_items ii ON ii.id = l.item_id WHERE l.requisition_id = :id ORDER BY l.line_no ASC, l.id ASC");
            $stmt->execute([':id' => $reqId]);
            $lines = $stmt->fetchAll(PDO::FETCH_ASSOC);
            if (!$lines) throw new RuntimeException('This requisition has no lines.');

            $approvedInput = $_POST['approved_qty'] ?? [];
            $issueInput = $_POST['issue_qty'] ?? [];
            if ($action === 'post_requisition' && (!is_array($issueInput) || count($issueInput) === 0)) {
                throw new RuntimeException('Please expand the requisition lines and enter Qty to Supply for each line before posting. The system will not automatically issue all available stock.');
            }
            foreach ($lines as $line) {
                $lineId = (int)$line['id'];
                $approvedQty = isset($approvedInput[$lineId]) ? (float)$approvedInput[$lineId] : (float)($line['approved_qty'] ?: $line['requested_qty']);
                if ($approvedQty < 0) throw new RuntimeException('Approved quantity cannot be negative.');
                if ($approvedQty > (float)$line['requested_qty']) {
                    throw new RuntimeException('Approved quantity cannot exceed requested quantity for ' . $line['item_name'] . '.');
                }
                $pdo->prepare("UPDATE internal_requisition_lines SET approved_qty = :approved_qty WHERE id = :id")
                    ->execute([':approved_qty' => $approvedQty, ':id' => $lineId]);
                $line['approved_qty'] = $approvedQty;
            }

            $stmt = $pdo->prepare("SELECT l.*, ii.item_name, ii.item_code, ii.cost_price, ii.avg_cost FROM internal_requisition_lines l INNER JOIN inventory_items ii ON ii.id = l.item_id WHERE l.requisition_id = :id ORDER BY l.line_no ASC, l.id ASC");
            $stmt->execute([':id' => $reqId]);
            $lines = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $pdo->prepare("UPDATE internal_requisitions SET status = 'APPROVED', fulfilment_status = 'APPROVED', approved_by = :approved_by, approved_at = COALESCE(approved_at, NOW()) WHERE id = :id")
                ->execute([':approved_by' => $userId, ':id' => $reqId]);

            if ($action === 'post_requisition') {
                $batchNo = ir_next_batch_no();
                $insertMove = $pdo->prepare("INSERT INTO stock_movements
                (batch_no, line_no, item_id, store_id, destination_type, destination_store_id, destination_room_id, destination_name,
                 conversion_id, source_item_id, destination_item_id, source_issue_qty, destination_receive_qty, conversion_factor, conversion_label,
                 movement_type, qty_in, qty_out, unit_cost, total_cost, reference_type, reference_id, notes, movement_date)
                VALUES
                (:batch_no, :line_no, :item_id, :store_id, :destination_type, :destination_store_id, :destination_room_id, :destination_name,
                 :conversion_id, :source_item_id, :destination_item_id, :source_issue_qty, :destination_receive_qty, :conversion_factor, :conversion_label,
                 :movement_type, :qty_in, :qty_out, :unit_cost, :total_cost, :reference_type, :reference_id, :notes, NOW())");

                $lineNo = 1;
                $postedItems = [];
                $totalIssued = 0.0;
                $totalApproved = 0.0;
                $postedLineCount = 0;

                foreach ($lines as $line) {
                    $itemId = (int)$line['item_id']; // Item requested by destination store
                    $approvedQty = (float)($line['approved_qty'] ?: $line['requested_qty']);
                    $totalApproved += $approvedQty;

                    if ($approvedQty <= 0) {
                        $pdo->prepare("UPDATE internal_requisition_lines SET issued_qty = 0, shortfall_qty = 0, source_issue_qty = 0, destination_receive_qty = 0, line_status = 'REJECTED' WHERE id = :id")
                            ->execute([':id' => (int)$line['id']]);
                        continue;
                    }

                    $lineId = (int)$line['id'];
                    $issueQty = isset($issueInput[$lineId]) ? (float)$issueInput[$lineId] : 0.0; // Always entered in requested/destination item units

                    if ($issueQty < 0) {
                        throw new RuntimeException('Qty to supply cannot be negative for ' . $line['item_name'] . '.');
                    }
                    if ($issueQty > $approvedQty) {
                        throw new RuntimeException('Qty to supply cannot exceed approved quantity for ' . $line['item_name'] . '.');
                    }

                    $conversion = ir_get_conversion_for_destination($pdo, $itemId);
                    $sourceItemId = $itemId;
                    $destinationItemId = $itemId;
                    $sourceIssueQty = $issueQty;
                    $destinationReceiveQty = $issueQty;
                    $conversionId = null;
                    $conversionFactor = 1.0;
                    $conversionLabel = null;

                    $destinationUnitCostSource = (float)($line['unit_cost'] ?: $line['avg_cost'] ?: $line['cost_price']);
                    $sourceUnitCost = $destinationUnitCostSource;
                    $destinationUnitCost = $destinationUnitCostSource;
                    $totalCost = round($issueQty * $destinationUnitCostSource, 4);

                    if ($conversion) {
                        $calc = ir_calculate_conversion_issue($conversion, $issueQty);

                        $sourceItemId = (int)$conversion['source_item_id'];
                        $destinationItemId = (int)$conversion['destination_item_id'];
                        $sourceIssueQty = (float)$calc['source_issue_qty'];
                        $destinationReceiveQty = (float)$calc['destination_receive_qty'];
                        $conversionId = (int)$conversion['id'];
                        $conversionFactor = (float)$calc['conversion_factor'];
                        $conversionLabel = ir_conversion_label($conversion);

                        /*
                           If the conversion rule is configured to round source up, the received
                           destination qty can be higher than the approved destination qty.
                           This is intentional for full-bottle/full-case control.
                           Example: approved 20 tots, round source up = 1 bottle, receive 40 tots.
                        */

                        $sourceUnitCost = ir_item_cost($pdo, $sourceItemId);
                        $totalCost = round($sourceIssueQty * $sourceUnitCost, 4);
                        $destinationUnitCost = $destinationReceiveQty > 0 ? round($totalCost / $destinationReceiveQty, 4) : 0.0;
                    }

                    $availableSourceQty = ir_stock_balance($pdo, $sourceItemId, (int)$req['source_store_id']);
                    if ($sourceIssueQty > $availableSourceQty) {
                        $availableLabel = $conversion
                            ? (($conversion['source_item_name'] ?? 'source item') . ' available: ' . money_fmt($availableSourceQty) . ' ' . ($conversion['source_unit_code'] ?? ''))
                            : ('Available: ' . money_fmt($availableSourceQty));

                        throw new RuntimeException(
                            'Qty to supply for ' . $line['item_name'] . ' exceeds current stock available at source. ' . $availableLabel
                        );
                    }

                    $shortfallQty = max(0, $approvedQty - $destinationReceiveQty);
                    $lineStatus = $approvedQty <= 0 ? 'REJECTED' : ($destinationReceiveQty <= 0 ? 'PENDING' : ($shortfallQty > 0 ? 'PARTIAL' : 'FULFILLED'));

                    if ($destinationReceiveQty > 0) {
                        $note = 'Internal requisition ' . $req['requisition_no'] . ' transfer from ' . $req['source_store_name'] . ' to ' . $req['request_store_name'];
                        if ($conversion) {
                            $note .= ' | Converted: ' . money_fmt($sourceIssueQty) . ' ' . ($conversion['source_unit_code'] ?? '') . ' ' . ($conversion['source_item_name'] ?? 'source item') .
                                     ' -> ' . money_fmt($destinationReceiveQty) . ' ' . ($conversion['destination_unit_code'] ?? '') . ' ' . ($conversion['destination_item_name'] ?? 'destination item');
                        }
                        if ($shortfallQty > 0) {
                            $note .= ' | Partial: supplied ' . money_fmt($destinationReceiveQty) . ' of approved ' . money_fmt($approvedQty) . ', shortfall ' . money_fmt($shortfallQty);
                        }

                        $insertMove->execute([
                            ':batch_no' => $batchNo,
                            ':line_no' => $lineNo,
                            ':item_id' => $sourceItemId,
                            ':store_id' => (int)$req['source_store_id'],
                            ':destination_type' => 'STORE',
                            ':destination_store_id' => (int)$req['request_store_id'],
                            ':destination_room_id' => null,
                            ':destination_name' => null,
                            ':conversion_id' => $conversionId,
                            ':source_item_id' => $sourceItemId,
                            ':destination_item_id' => $destinationItemId,
                            ':source_issue_qty' => $sourceIssueQty,
                            ':destination_receive_qty' => $destinationReceiveQty,
                            ':conversion_factor' => $conversionFactor,
                            ':conversion_label' => $conversionLabel,
                            ':movement_type' => 'TRANSFER_OUT',
                            ':qty_in' => 0,
                            ':qty_out' => $sourceIssueQty,
                            ':unit_cost' => $sourceUnitCost,
                            ':total_cost' => $totalCost,
                            ':reference_type' => 'INTERNAL_REQUISITION',
                            ':reference_id' => $reqId,
                            ':notes' => $note,
                        ]);

                        $insertMove->execute([
                            ':batch_no' => $batchNo,
                            ':line_no' => $lineNo,
                            ':item_id' => $destinationItemId,
                            ':store_id' => (int)$req['request_store_id'],
                            ':destination_type' => 'STORE',
                            ':destination_store_id' => (int)$req['source_store_id'],
                            ':destination_room_id' => null,
                            ':destination_name' => null,
                            ':conversion_id' => $conversionId,
                            ':source_item_id' => $sourceItemId,
                            ':destination_item_id' => $destinationItemId,
                            ':source_issue_qty' => $sourceIssueQty,
                            ':destination_receive_qty' => $destinationReceiveQty,
                            ':conversion_factor' => $conversionFactor,
                            ':conversion_label' => $conversionLabel,
                            ':movement_type' => 'TRANSFER_IN',
                            ':qty_in' => $destinationReceiveQty,
                            ':qty_out' => 0,
                            ':unit_cost' => $destinationUnitCost,
                            ':total_cost' => $totalCost,
                            ':reference_type' => 'INTERNAL_REQUISITION',
                            ':reference_id' => $reqId,
                            ':notes' => $note,
                        ]);

                        $postedItems[$sourceItemId] = true;
                        $postedItems[$destinationItemId] = true;
                        $postedLineCount++;
                        $lineNo++;
                    }

                    $totalIssued += $destinationReceiveQty;
                    $pdo->prepare("
                        UPDATE internal_requisition_lines
                        SET issued_qty = :issued_qty,
                            shortfall_qty = :shortfall_qty,
                            unit_cost = :unit_cost,
                            line_status = :line_status,
                            source_item_id = :source_item_id,
                            destination_item_id = :destination_item_id,
                            conversion_id = :conversion_id,
                            source_issue_qty = :source_issue_qty,
                            destination_receive_qty = :destination_receive_qty,
                            conversion_factor = :conversion_factor,
                            conversion_label = :conversion_label
                        WHERE id = :id
                    ")->execute([
                        ':issued_qty' => $destinationReceiveQty,
                        ':shortfall_qty' => $shortfallQty,
                        ':unit_cost' => $destinationUnitCost,
                        ':line_status' => $lineStatus,
                        ':source_item_id' => $sourceItemId,
                        ':destination_item_id' => $destinationItemId,
                        ':conversion_id' => $conversionId,
                        ':source_issue_qty' => $sourceIssueQty,
                        ':destination_receive_qty' => $destinationReceiveQty,
                        ':conversion_factor' => $conversionFactor,
                        ':conversion_label' => $conversionLabel,
                        ':id' => (int)$line['id']
                    ]);
                }

                if ($postedLineCount <= 0) {
                    throw new RuntimeException('No quantities were supplied. Enter Qty to Supply on at least one line before posting.');
                }

                $fulfilmentStatus = ($totalApproved > 0 && $totalIssued >= $totalApproved) ? 'FULFILLED' : 'PARTIAL';

                $pdo->prepare("UPDATE internal_requisitions SET status = 'POSTED', fulfilment_status = :fulfilment_status, posted_by = :posted_by, posted_at = NOW(), posted_batch_no = :posted_batch_no WHERE id = :id")
                    ->execute([':fulfilment_status' => $fulfilmentStatus, ':posted_by' => $userId, ':posted_batch_no' => $batchNo, ':id' => $reqId]);

                foreach (array_keys($postedItems) as $itemId) {
                    ir_recalculate_avg_cost($pdo, (int)$itemId);
                }

                $pdo->commit();
                ir_flash('success', 'Requisition posted. Batch: ' . $batchNo . ' | Fulfilment: ' . $fulfilmentStatus . ' | Issued: ' . money_fmt($totalIssued) . ' of approved ' . money_fmt($totalApproved));
                header('Location: internal_requisition.php?status=POSTED');
                exit;
            }

            $pdo->commit();
            ir_flash('success', 'Requisition approved successfully. You can now post the transfer.');
            header('Location: internal_requisition.php?status=APPROVED');
            exit;
        }

        if ($action === 'reject_requisition' || $action === 'cancel_requisition') {
            $reqId = (int)($_POST['id'] ?? 0);
            $reason = trim((string)($_POST['reason'] ?? ''));
            if ($reqId <= 0) throw new RuntimeException('Invalid requisition selected.');
            $newStatus = $action === 'reject_requisition' ? 'REJECTED' : 'CANCELLED';

            $stmt = $pdo->prepare("SELECT status FROM internal_requisitions WHERE id = :id LIMIT 1");
            $stmt->execute([':id' => $reqId]);
            $status = (string)$stmt->fetchColumn();
            if ($status === 'POSTED') throw new RuntimeException('Posted requisitions cannot be rejected or cancelled.');

            $stmt = $pdo->prepare("UPDATE internal_requisitions SET status = :status, rejection_reason = :reason WHERE id = :id");
            $stmt->execute([':status' => $newStatus, ':reason' => $reason !== '' ? $reason : null, ':id' => $reqId]);
            ir_flash('success', 'Requisition marked as ' . strtolower($newStatus) . '.');
            header('Location: internal_requisition.php?status=' . $newStatus);
            exit;
        }

        throw new RuntimeException('Invalid action.');
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        ir_flash('danger', $e->getMessage());
        header('Location: internal_requisition.php');
        exit;
    }
}

$statusFilter = strtoupper(trim((string)($_GET['status'] ?? '')));
$sourceFilter = (int)($_GET['source_store_id'] ?? 0);
$requestFilter = (int)($_GET['request_store_id'] ?? 0);
$search = trim((string)($_GET['q'] ?? ''));
$dateFrom = trim((string)($_GET['date_from'] ?? date('Y-m-01')));
$dateTo = trim((string)($_GET['date_to'] ?? date('Y-m-d')));
if (strtotime($dateFrom) === false) $dateFrom = date('Y-m-01');
if (strtotime($dateTo) === false) $dateTo = date('Y-m-d');
if (strtotime($dateFrom) > strtotime($dateTo)) { $tmp = $dateFrom; $dateFrom = $dateTo; $dateTo = $tmp; }

$where = "DATE(r.requisition_date) BETWEEN :date_from AND :date_to";
$params = [':date_from' => $dateFrom, ':date_to' => $dateTo];
if ($statusFilter !== '' && in_array($statusFilter, ['DRAFT','PENDING','SUBMITTED','APPROVED','PARTIAL','FULFILLED','POSTED','REJECTED','CANCELLED'], true)) {
    $where .= " AND r.status = :status";
    $params[':status'] = $statusFilter;
}
if ($sourceFilter > 0) {
    $where .= " AND r.source_store_id = :source_store_id";
    $params[':source_store_id'] = $sourceFilter;
}
if ($requestFilter > 0) {
    $where .= " AND r.request_store_id = :request_store_id";
    $params[':request_store_id'] = $requestFilter;
}
if ($search !== '') {
    $where .= " AND (r.requisition_no LIKE :q_req_no OR fs.location_name LIKE :q_source_store OR ts.location_name LIKE :q_request_store OR r.notes LIKE :q_notes OR r.posted_batch_no LIKE :q_batch_no)";
    $likeSearch = '%' . $search . '%';
    $params[':q_req_no'] = $likeSearch;
    $params[':q_source_store'] = $likeSearch;
    $params[':q_request_store'] = $likeSearch;
    $params[':q_notes'] = $likeSearch;
    $params[':q_batch_no'] = $likeSearch;
}

$requisitions = [];
$summary = ['total' => 0, 'pending' => 0, 'submitted' => 0, 'approved' => 0, 'partial' => 0, 'fulfilled' => 0, 'posted' => 0, 'rejected' => 0];
try {
    $stmt = $pdo->prepare("SELECT r.*, fs.location_name AS source_store_name, ts.location_name AS request_store_name, COUNT(l.id) AS line_count, COALESCE(SUM(l.requested_qty),0) AS total_requested_qty, COALESCE(SUM(l.approved_qty),0) AS total_approved_qty, COALESCE(SUM(l.issued_qty),0) AS total_issued_qty, COALESCE(SUM(l.shortfall_qty),0) AS total_shortfall_qty, COALESCE(SUM((CASE WHEN l.issued_qty > 0 THEN l.issued_qty WHEN l.approved_qty > 0 THEN l.approved_qty ELSE l.requested_qty END) * l.unit_cost),0) AS estimated_value FROM internal_requisitions r INNER JOIN store_locations fs ON fs.id = r.source_store_id INNER JOIN store_locations ts ON ts.id = r.request_store_id LEFT JOIN internal_requisition_lines l ON l.requisition_id = r.id WHERE $where GROUP BY r.id ORDER BY r.requisition_date DESC, r.id DESC LIMIT 500");
    $stmt->execute($params);
    $requisitions = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $stmt = $pdo->query("SELECT status, COUNT(*) AS cnt FROM internal_requisitions GROUP BY status");
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $summary['total'] += (int)$row['cnt'];
        $key = strtolower((string)$row['status']);
        if (isset($summary[$key])) $summary[$key] = (int)$row['cnt'];
    }
} catch (Throwable $e) {
    $errors[] = 'Could not load internal requisitions: ' . $e->getMessage();
}

$reqLinesById = [];
if ($requisitions) {
    try {
        $ids = array_map(fn($r) => (int)$r['id'], $requisitions);
        $placeholders = implode(',', array_fill(0, count($ids), '?'));
        $stmt = $pdo->prepare("SELECT l.*, ii.item_name, ii.item_code, u.unit_code FROM internal_requisition_lines l INNER JOIN inventory_items ii ON ii.id = l.item_id LEFT JOIN inventory_units u ON u.id = ii.unit_id WHERE l.requisition_id IN ($placeholders) ORDER BY l.requisition_id ASC, l.line_no ASC, l.id ASC");
        $stmt->execute($ids);
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $line) {
            $reqLinesById[(int)$line['requisition_id']][] = $line;
        }
    } catch (Throwable $e) {}
}

$flashes = ir_get_flash();
$statusBadge = function(string $status): string {
    switch ($status) {
        case 'PENDING':
            return 'text-bg-info';
        case 'SUBMITTED':
            return 'text-bg-primary';
        case 'APPROVED':
        case 'PARTIAL':
            return 'text-bg-warning';
        case 'FULFILLED':
        case 'POSTED':
            return 'text-bg-success';
        case 'REJECTED':
            return 'text-bg-danger';
        case 'CANCELLED':
            return 'text-bg-secondary';
        default:
            return 'text-bg-light';
    }
};
$priorityBadge = function(string $priority): string {
    switch ($priority) {
        case 'URGENT':
            return 'text-bg-danger';
        case 'HIGH':
            return 'text-bg-warning';
        case 'LOW':
            return 'text-bg-secondary';
        default:
            return 'text-bg-info';
    }
};

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

<div class="hero-band">
    <div class="row g-3 align-items-center">
        <div class="col-lg-8">
            <div class="page-eyebrow text-white-50"><i class="bi bi-diagram-3"></i> Stores &amp; POS Inventory</div>
            <div class="hero-title mt-1">Internal Requisitions</div>
            <div class="hero-subtitle mt-1">Store-to-store requests that approve and post directly into Stock Movements transfer batches.</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>Stock Movements</a>
            <a href="store_locations.php" class="btn btn-outline-light"><i class="bi bi-shop me-2"></i>Stores</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-3 mb-3">
    <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">All Requisitions</div><div class="metric-value"><?php echo (int)$summary['total']; ?></div></div></div></div>
    <div class="col-md-6 col-xl-3"><div class="metric-card"><div class="metric-icon bg-info-subtle text-info"><i class="bi bi-send"></i></div><div><div class="metric-label">Submitted</div><div class="metric-value"><?php echo (int)$summary['submitted']; ?></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-shield-check"></i></div><div><div class="metric-label">Approved</div><div class="metric-value"><?php echo (int)$summary['approved']; ?></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-check2-circle"></i></div><div><div class="metric-label">Posted Transfers</div><div class="metric-value"><?php echo (int)$summary['posted']; ?></div></div></div></div>
</div>

<div class="ir-page-workspace">
    <div class="ir-create-section">
        <div class="card panel-card mb-4">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Create Internal Requisition</h5>
                <span class="badge text-bg-light">Request first, transfer after approval</span>
            </div>
            <div class="card-body">
                <form method="post" id="irForm">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="create_requisition">

                    <div class="row g-3">
                        <div class="col-md-6">
                            <label class="form-label">Requesting Store</label>
                            <select name="request_store_id" id="requestStore" class="form-select" required>
                                <option value="">Store needing items</option>
                                <?php foreach ($stores as $store): ?>
                                    <option value="<?php echo (int)$store['id']; ?>"><?php echo h($store['location_name']); ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                        <div class="col-md-6">
                            <label class="form-label">Source Store</label>
                            <select name="source_store_id" id="sourceStore" class="form-select" required>
                                <option value="">Store supplying items</option>
                                <?php foreach ($stores as $store): ?>
                                    <option value="<?php echo (int)$store['id']; ?>"><?php echo h($store['location_name']); ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                        <div class="col-md-6">
                            <label class="form-label">Required Date</label>
                            <input type="date" name="required_date" class="form-control" value="<?php echo h(date('Y-m-d')); ?>">
                        </div>
                        <div class="col-md-6">
                            <label class="form-label">Priority</label>
                            <select name="priority" class="form-select">
                                <option value="NORMAL">Normal</option>
                                <option value="LOW">Low</option>
                                <option value="HIGH">High</option>
                                <option value="URGENT">Urgent</option>
                            </select>
                        </div>
                    </div>

                    <hr class="my-3">

                    <div class="d-flex justify-content-between align-items-center mb-2">
                        <div>
                            <h6 class="mb-0">Requested Items</h6>
                            <div class="text-muted small">Add one or more stock items.</div>
                        </div>
                        <button type="button" class="btn btn-sm btn-outline-primary" id="addLineBtn"><i class="bi bi-plus-circle me-1"></i>Add Line</button>
                    </div>

                    <div id="irLines" class="ir-lines">
                        <div class="ir-line-card">
                            <div class="d-flex justify-content-between align-items-center mb-2">
                                <strong>Line 1</strong>
                                <button type="button" class="btn btn-sm btn-outline-danger remove-line" style="display:none;"><i class="bi bi-x-lg"></i></button>
                            </div>
                            <div class="row g-2">
                                <div class="col-md-4">
                                    <label class="form-label">Item</label>
                                    <select name="item_id[]" class="form-select item-select" required>
                                        <option value="">Select item</option>
                                        <?php foreach ($items as $item): ?>
                                            <option value="<?php echo (int)$item['id']; ?>" data-cost="<?php echo h($item['avg_cost'] ?: $item['cost_price']); ?>" data-unit="<?php echo h($item['unit_code'] ?: ''); ?>"><?php echo h(ir_item_option_text($item)); ?></option>
                                        <?php endforeach; ?>
                                    </select>
                                    <div class="stock-help small text-muted mt-1">Select source store to see quantity on hand.</div>
                                </div>
                                <div class="col-md-3">
                                    <label class="form-label">Qty Requested</label>
                                    <input type="number" step="0.0001"  min="1" name="requested_qty[]" class="form-control qty-input" required>
                                </div>
                                
                                <div class="col-5">
                                    <label class="form-label">Notes</label>
                                    <input type="text" name="line_notes[]" class="form-control" placeholder="Line note / reason optional">
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="movement-total-box mt-3">
                        <div><span class="text-muted small">Lines</span><strong id="lineCount">0</strong></div>
                        <div><span class="text-muted small">Estimated Value</span><strong id="estimatedValue">0.00</strong></div>
                    </div>

                    <div class="mt-3">
                        <label class="form-label">Notes</label>
                        <textarea name="notes" class="form-control" rows="3" placeholder="Purpose, urgency, authorisation, event or department need..."></textarea>
                    </div>

                    <div class="alert alert-info small mt-3 mb-0">
                        <strong>Flow:</strong> Create request → Approve &amp; Post Transfer. At issue stage the approver chooses Qty to Supply per line. Available stock is shown, but the source store can supply less than available when stock must be shared.
                    </div>

                    <button class="btn btn-primary w-100 mt-3"><i class="bi bi-send-check me-2"></i>Submit Requisition</button>
                </form>
            </div>
        </div>
    </div>

    <div class="ir-register-section">
        <div class="card panel-card mb-4">
            <div class="card-body">
                <form method="get" class="row g-2 align-items-end">
                    <div class="col-md-2"><label class="form-label">From</label><input type="date" name="date_from" class="form-control" value="<?php echo h($dateFrom); ?>"></div>
                    <div class="col-md-2"><label class="form-label">To</label><input type="date" name="date_to" class="form-control" value="<?php echo h($dateTo); ?>"></div>
                    <div class="col-md-2"><label class="form-label">Status</label><select name="status" class="form-select"><option value="">All</option><?php foreach (['PENDING','SUBMITTED','APPROVED','POSTED','REJECTED','CANCELLED'] as $st): ?><option value="<?php echo h($st); ?>" <?php echo $statusFilter === $st ? 'selected' : ''; ?>><?php echo h($st); ?></option><?php endforeach; ?></select></div>
                    <div class="col-md-2"><label class="form-label">Source</label><select name="source_store_id" class="form-select"><option value="0">All</option><?php foreach ($stores as $store): ?><option value="<?php echo (int)$store['id']; ?>" <?php echo $sourceFilter === (int)$store['id'] ? 'selected' : ''; ?>><?php echo h($store['location_name']); ?></option><?php endforeach; ?></select></div>
                    <div class="col-md-2"><label class="form-label">Request</label><select name="request_store_id" class="form-select"><option value="0">All</option><?php foreach ($stores as $store): ?><option value="<?php echo (int)$store['id']; ?>" <?php echo $requestFilter === (int)$store['id'] ? 'selected' : ''; ?>><?php echo h($store['location_name']); ?></option><?php endforeach; ?></select></div>
                    <div class="col-md-1"><label class="form-label">Search</label><input type="text" name="q" class="form-control" value="<?php echo h($search); ?>"></div>
                    <div class="col-md-1 d-grid"><button class="btn btn-primary"><i class="bi bi-funnel"></i></button></div>
                </form>
            </div>
        </div>

        <div class="card panel-card">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Requisition List</h5>
                <span class="text-muted small">Open each requisition to approve and choose Qty to Supply</span>
            </div>
            <div class="card-body p-0">
                <div class="ir-table-wrap">
                    <table class="table table-modern align-middle mb-0 ir-table">
                        <thead>
                        <tr>
                            <th style="width:40px;"></th>
                            <th>Requisition</th>
                            <th>Stores</th>
                            <th>Status</th>
                            <th class="text-end">Lines</th>
                            <th class="text-end">Qty</th>
                            <th class="text-end">Value</th>
                            <th>Batch</th>
                            <th class="text-end">Action</th>
                        </tr>
                        </thead>
                        <tbody>
                        <?php if (!$requisitions): ?>
                            <tr><td colspan="9" class="text-center text-muted py-4">No internal requisitions found.</td></tr>
                        <?php else: ?>
                            <?php $idx = 0; foreach ($requisitions as $req): $idx++; $detailId = 'reqLines_' . $idx; ?>
                                <tr class="req-summary-row">
                                    <td><button type="button" class="btn btn-sm btn-light req-toggle" data-target="<?php echo h($detailId); ?>"><i class="bi bi-chevron-down"></i></button></td>
                                    <td>
                                        <strong><?php echo h($req['requisition_no']); ?></strong>
                                        <div class="small text-muted"><?php echo h(date('Y-m-d H:i', strtotime($req['requisition_date']))); ?></div>
                                        <?php if (!empty($req['required_date'])): ?><div class="small text-muted">Required: <?php echo h(date('Y-m-d', strtotime($req['required_date']))); ?></div><?php endif; ?>
                                    </td>
                                    <td>
                                        <div><span class="text-muted small">From:</span> <strong><?php echo h($req['source_store_name']); ?></strong></div>
                                        <div><span class="text-muted small">To:</span> <strong><?php echo h($req['request_store_name']); ?></strong></div>
                                    </td>
                                    <td>
                                        <span class="badge <?php echo h($statusBadge((string)$req['status'])); ?>"><?php echo h($req['status']); ?></span>
                                        <span class="badge <?php echo h($priorityBadge((string)$req['priority'])); ?>"><?php echo h($req['priority']); ?></span>
                                        <?php if (!empty($req['fulfilment_status']) && $req['fulfilment_status'] !== 'PENDING'): ?>
                                            <span class="badge <?php echo $req['fulfilment_status'] === 'PARTIAL' ? 'text-bg-warning' : ($req['fulfilment_status'] === 'FULFILLED' ? 'text-bg-success' : 'text-bg-light'); ?>"><?php echo h($req['fulfilment_status']); ?></span>
                                        <?php endif; ?>
                                    </td>
                                    <td class="text-end fw-bold"><?php echo (int)$req['line_count']; ?></td>
                                    <td class="text-end fw-bold"><?php echo money_fmt($req['total_requested_qty']); ?></td>
                                    <td class="text-end fw-bold"><?php echo money_fmt($req['estimated_value']); ?></td>
                                    <td>
                                        <?php if (!empty($req['posted_batch_no'])): ?>
                                            <span class="badge text-bg-dark"><?php echo h($req['posted_batch_no']); ?></span>
                                            <a class="small d-block mt-1" href="stock_movements.php?q=<?php echo urlencode((string)$req['posted_batch_no']); ?>">View movement</a>
                                        <?php else: ?>
                                            <span class="text-muted">—</span>
                                        <?php endif; ?>
                                    </td>
                                    <td class="text-end">
                                        <?php if (in_array((string)$req['status'], ['PENDING','SUBMITTED','APPROVED'], true)): ?>
                                            <button type="button"
                                                    class="btn btn-sm btn-success req-issue-open"
                                                    data-target="<?php echo h($detailId); ?>"
                                                    title="Open issuing panel and choose quantities to supply">
                                                <i class="bi bi-box-arrow-up me-1"></i>Issue
                                            </button>
                                        <?php endif; ?>
                                        <?php if (in_array((string)$req['status'], ['PENDING','SUBMITTED'], true)): ?>
                                            <form method="post" class="d-inline" onsubmit="return confirm('Approve this requisition without posting transfer now?');">
                                                <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                                <input type="hidden" name="action" value="approve_requisition">
                                                <input type="hidden" name="id" value="<?php echo (int)$req['id']; ?>">
                                                <button class="btn btn-sm btn-outline-primary" title="Approve only"><i class="bi bi-shield-check"></i></button>
                                            </form>
                                            <form method="post" class="d-inline" onsubmit="return confirm('Reject this requisition?');">
                                                <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                                <input type="hidden" name="action" value="reject_requisition">
                                                <input type="hidden" name="id" value="<?php echo (int)$req['id']; ?>">
                                                <button class="btn btn-sm btn-outline-danger" title="Reject"><i class="bi bi-x-circle"></i></button>
                                            </form>
                                        <?php endif; ?>
                                    </td>
                                </tr>
                                <tr id="<?php echo h($detailId); ?>" class="req-detail-row" style="display:none;">
                                    <td colspan="9" class="p-0">
                                        <div class="req-detail-box">
                                            <?php if (!empty($req['notes'])): ?><div class="small mb-2"><strong>Notes:</strong> <?php echo h($req['notes']); ?></div><?php endif; ?>
                                            <?php if (!empty($req['rejection_reason'])): ?><div class="small text-danger mb-2"><strong>Reason:</strong> <?php echo h($req['rejection_reason']); ?></div><?php endif; ?>
                                            <?php if (in_array((string)$req['status'], ['PENDING','SUBMITTED','APPROVED'], true)): ?>
                                                <div class="alert alert-warning py-2 px-3 small mb-2">
                                                    <strong>Issuing rule:</strong> the approver controls Qty to Supply per line. Available stock is shown as guidance only; the system will not automatically issue everything available.
                                                </div>
                                            <?php endif; ?>
                                            <?php $canIssueThisReq = in_array((string)$req['status'], ['PENDING','SUBMITTED','APPROVED'], true); ?>
                                            <?php if ($canIssueThisReq): ?>
                                            <form method="post" class="issue-form" onsubmit="return confirm('Post this requisition using the Qty to Supply values entered?\n\nOnly those quantities will be transferred. Any approved quantity not supplied will remain as shortfall / partial fulfilment.');">
                                                <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                                <input type="hidden" name="action" value="post_requisition">
                                                <input type="hidden" name="id" value="<?php echo (int)$req['id']; ?>">
                                            <?php endif; ?>
                                            <table class="table table-sm align-middle mb-0 req-lines-table">
                                                <thead><tr><th>Line</th><th>Item</th><th class="text-end">Requested</th><th class="text-end">Approved</th><th class="text-end">Available Now</th><th class="text-end">Qty to Supply</th><th class="text-end">After Supply</th><th class="text-end">Issued</th><th class="text-end">Shortfall</th><th>Status</th><th class="text-end">Unit Cost</th><th>Notes</th></tr></thead>
                                                <tbody>
                                                <?php foreach (($reqLinesById[(int)$req['id']] ?? []) as $line): ?>
                                                    <?php
                                                        $lineConversion = ir_get_conversion_for_destination($pdo, (int)$line['item_id']);
                                                        $approvedQtyForLine = (float)($line['approved_qty'] ?: $line['requested_qty']);

                                                        if ($lineConversion) {
                                                            $lineFactor = ir_conversion_factor($lineConversion);
                                                            $sourceAvailable = ir_stock_balance($pdo, (int)$lineConversion['source_item_id'], (int)$req['source_store_id']);
                                                            $currentAvailable = $sourceAvailable * $lineFactor; // shown in destination/requested item units
                                                            $defaultSupplyQty = min($approvedQtyForLine, max(0, $currentAvailable));
                                                            if ((int)($lineConversion['allow_fractional_source'] ?? 0) !== 1 && (int)($lineConversion['round_source_up'] ?? 0) !== 1 && $lineFactor > 0) {
                                                                $defaultSupplyQty = floor($defaultSupplyQty / $lineFactor) * $lineFactor;
                                                            }
                                                            $availableTitle = 'Source stock: ' . money_fmt($sourceAvailable) . ' ' . h($lineConversion['source_unit_code'] ?? '') . ' ' . h($lineConversion['source_item_name'] ?? '');
                                                        } else {
                                                            $currentAvailable = ir_stock_balance($pdo, (int)$line['item_id'], (int)$req['source_store_id']);
                                                            $defaultSupplyQty = min($approvedQtyForLine, max(0, $currentAvailable));
                                                            $availableTitle = '';
                                                        }

                                                        $defaultAfterShortfallQty = max(0, $approvedQtyForLine - $defaultSupplyQty);
                                                        $willShortfall = $canIssueThisReq && $defaultAfterShortfallQty > 0.00001;
                                                    ?>
                                                    <tr class="<?php echo $willShortfall ? 'table-warning' : ''; ?>">
                                                        <td><span class="badge text-bg-light">Line <?php echo (int)$line['line_no']; ?></span></td>
                                                        <td>
                                                            <strong><?php echo h($line['item_name']); ?></strong>
                                                            <div class="small text-muted"><?php echo h($line['item_code'] ?: ''); ?> <?php echo h($line['unit_code'] ?: ''); ?></div>
                                                            <?php if ($lineConversion): ?>
                                                                <div class="small text-primary fw-semibold mt-1">
                                                                    <i class="bi bi-shuffle me-1"></i>
                                                                    <?php echo h(ir_conversion_label($lineConversion)); ?>
                                                                </div>
                                                            <?php elseif (!empty($line['conversion_label'])): ?>
                                                                <div class="small text-primary fw-semibold mt-1">
                                                                    <i class="bi bi-shuffle me-1"></i><?php echo h($line['conversion_label']); ?>
                                                                </div>
                                                            <?php endif; ?>
                                                        </td>
                                                        <td class="text-end"><?php echo money_fmt($line['requested_qty']); ?></td>
                                                        <td class="text-end">
                                                            <?php if ($canIssueThisReq): ?>
                                                                <input type="number" step="0.0001" min="0" max="<?php echo h((float)$line['requested_qty']); ?>" name="approved_qty[<?php echo (int)$line['id']; ?>]" class="form-control form-control-sm text-end approved-qty-input" value="<?php echo h($approvedQtyForLine); ?>" data-requested="<?php echo h((float)$line['requested_qty']); ?>">
                                                            <?php else: ?>
                                                                <?php echo money_fmt($line['approved_qty']); ?>
                                                            <?php endif; ?>
                                                        </td>
                                                        <td class="text-end <?php echo $currentAvailable <= 0 ? 'text-danger fw-bold' : 'text-success fw-bold'; ?>" title="<?php echo h($availableTitle); ?>">
                                                            <?php echo money_fmt($currentAvailable); ?>
                                                            <?php if ($lineConversion): ?><div class="small text-muted">dest units</div><?php endif; ?>
                                                        </td>
                                                        <td class="text-end fw-bold">
                                                            <?php if ($canIssueThisReq): ?>
                                                                <input type="number" step="0.0001" min="0" max="<?php echo h($currentAvailable); ?>" name="issue_qty[<?php echo (int)$line['id']; ?>]" class="form-control form-control-sm text-end issue-qty-input" value="<?php echo h($defaultSupplyQty); ?>" data-available="<?php echo h($currentAvailable); ?>" data-approved="<?php echo h($approvedQtyForLine); ?>">
                                                                <?php if ($currentAvailable < $approvedQtyForLine): ?><div class="small text-warning">Available less than approved</div><?php endif; ?>
                                                            <?php else: ?>
                                                                —
                                                            <?php endif; ?>
                                                        </td>
                                                        <td class="text-end fw-bold issue-shortfall-preview">
                                                            <?php echo $canIssueThisReq ? money_fmt($defaultAfterShortfallQty) : '—'; ?>
                                                        </td>
                                                        <td class="text-end fw-bold"><?php echo money_fmt($line['issued_qty']); ?></td>
                                                        <td class="text-end text-warning fw-bold"><?php echo money_fmt($line['shortfall_qty'] ?? 0); ?></td>
                                                        <td><span class="badge <?php echo ($line['line_status'] ?? 'PENDING') === 'FULFILLED' ? 'text-bg-success' : (($line['line_status'] ?? 'PENDING') === 'PARTIAL' ? 'text-bg-warning' : (($line['line_status'] ?? 'PENDING') === 'REJECTED' ? 'text-bg-danger' : 'text-bg-light')); ?>"><?php echo h($line['line_status'] ?? 'PENDING'); ?></span></td>
                                                        <td class="text-end"><?php echo money_fmt($line['unit_cost']); ?></td>
                                                        <td><?php echo h($line['line_notes'] ?: ''); ?></td>
                                                    </tr>
                                                <?php endforeach; ?>
                                                </tbody>
                                            </table>
                                            <?php if ($canIssueThisReq): ?>
                                                <div class="d-flex justify-content-between align-items-center gap-2 mt-3 flex-wrap">
                                                    <div class="small text-muted">
                                                        Qty to Supply defaults to available stock capped by approved quantity. Adjust it down if the source store must share stock with other locations.
                                                    </div>
                                                    <button class="btn btn-sm btn-success">
                                                        <i class="bi bi-box-arrow-up me-1"></i>Post Selected Supply Quantities
                                                    </button>
                                                </div>
                                            </form>
                                            <?php endif; ?>
                                        </div>
                                    </td>
                                </tr>
                            <?php endforeach; ?>
                        <?php endif; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

<style>
/* Purchase-order inspired Internal Requisition workspace */
.hero-band{padding:16px 20px!important;margin-bottom:14px!important;border-radius:16px!important}.hero-title{font-size:1.45rem!important;line-height:1.15!important}.hero-subtitle{font-size:.84rem!important}.page-eyebrow{font-size:.72rem!important;letter-spacing:.06em!important}.hero-band .btn{height:40px;padding:0 14px!important;font-size:.8rem!important;border-radius:9px!important;display:inline-flex;align-items:center}
.metric-card{padding:12px 14px!important;gap:10px!important;min-height:66px!important;border:1px solid #e3e8ef!important;border-radius:13px!important;box-shadow:0 2px 5px rgba(16,24,40,.03)!important}.metric-icon{width:38px!important;height:38px!important;border-radius:10px!important;font-size:15px!important}.metric-label{font-size:.72rem!important;margin-bottom:2px!important;color:#667085!important}.metric-value{font-size:1.15rem!important;line-height:1.1!important;color:#101828!important}
.ir-page-workspace{display:flex;flex-direction:column;gap:16px}.ir-create-section,.ir-register-section{min-width:0}.panel-card{border:1px solid #e3e8ef!important;border-radius:15px!important;box-shadow:0 2px 6px rgba(16,24,40,.04)!important;overflow:visible!important}.panel-card>.card-header{min-height:58px;padding:14px 18px!important;background:#fff!important;border-bottom:1px solid #e7ebf2!important;border-radius:15px 15px 0 0!important}.panel-card>.card-header h5{font-size:16px;font-weight:750;color:#101828}.panel-card>.card-body{padding:16px 18px!important}
#irForm>.row{display:grid!important;grid-template-columns:1.35fr 1.35fr .8fr .8fr;gap:16px!important;margin:0!important}#irForm>.row>[class*=col-]{width:auto!important;padding:0!important}.form-label{font-size:.72rem!important;margin-bottom:6px!important;font-weight:700!important;color:#263145!important}.form-control,.form-select{height:42px!important;min-height:42px!important;font-size:.82rem!important;padding:7px 10px!important;border-radius:9px!important;border-color:#d8dee8!important}textarea.form-control{height:auto!important;min-height:64px!important;resize:vertical}.form-control:focus,.form-select:focus{border-color:#84adff!important;box-shadow:0 0 0 3px rgba(13,110,253,.10)!important}
#irForm hr{margin:16px 0!important;border-color:#edf0f4}.ir-lines{display:flex;flex-direction:column;gap:0;max-height:390px;overflow:auto;border:1px solid #e3e8ef;border-radius:10px;background:#fff}.ir-line-card{border:0;border-bottom:1px solid #edf0f4;border-radius:0;padding:12px 14px;background:#fff;box-shadow:none}.ir-line-card:last-child{border-bottom:0}.ir-line-card>.d-flex{margin-bottom:8px!important}.ir-line-card>.d-flex strong{display:inline-flex;align-items:center;justify-content:center;min-width:58px;height:26px;border-radius:999px;background:#f2f4f7;color:#475467;font-size:.72rem}.ir-line-card .row{display:grid!important;grid-template-columns:minmax(300px,2fr) 150px minmax(220px,1fr);gap:12px!important;margin:0!important;align-items:start}.ir-line-card .row>[class*=col-]{width:auto!important;padding:0!important}.ir-line-card .col-12{grid-column:auto!important;padding-top:24px!important}.ir-line-card .form-label{min-height:20px;margin-bottom:6px}.ir-line-card .form-control,.ir-line-card .form-select,.ir-line-card .native-item-picker .form-control{height:43px}.ir-line-card .remove-line{width:34px;height:34px;border:1px solid #f1c0c4;color:#d92d20;background:#fff;border-radius:8px}.ir-line-card .remove-line:hover{background:#fff1f2}.movement-total-box{display:flex;justify-content:flex-end;gap:36px;align-items:center;border:1px solid #dfe5ee;background:#f8fafc;border-radius:11px;padding:12px 16px}.movement-total-box>div{display:flex;align-items:center;gap:10px}.movement-total-box strong{font-size:1rem;color:#0d6efd}.movement-total-box span{font-size:.72rem!important}
#irForm>.alert{border:1px solid #cfe0ff;background:#f4f8ff;color:#344054;border-radius:10px}#irForm>button[type=submit],#irForm>button:not([type]){width:auto!important;min-width:210px!important;float:right;height:44px;border-radius:9px;font-weight:700}
.ir-register-section>.panel-card:first-child .card-body{padding:12px 14px!important}.ir-register-section form.row{display:grid!important;grid-template-columns:130px 130px 150px 1fr 1fr minmax(170px,1.2fr) 46px;gap:10px!important;margin:0!important}.ir-register-section form.row>[class*=col-]{width:auto!important;padding:0!important}.ir-register-section form.row .btn{height:42px;border-radius:9px}
.ir-table-wrap{max-height:720px;overflow:auto;position:relative}.ir-table{min-width:1080px}.ir-table thead th{position:sticky;top:0;z-index:50;background:#f7f9fc;color:#667085;box-shadow:0 1px 0 #e2e8f0;border-bottom:0;white-space:nowrap;text-transform:uppercase;font-size:.66rem;letter-spacing:.045em;padding:11px 10px}.ir-table tbody td{padding:11px 10px;border-color:#edf0f4}.req-summary-row:hover{background:#f8fafc}.req-toggle{border:1px solid #d8dee8;border-radius:8px}.req-toggle.is-open i{transform:rotate(180deg)}.req-toggle i{transition:transform .18s ease}.req-detail-box{background:#f8fafc;border-top:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;padding:16px}.req-lines-table{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden}.req-lines-table thead th{font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;color:#64748b;background:#f1f5f9}.stock-help.is-ok{color:#047857!important;font-weight:600}.stock-help.is-empty{color:#b91c1c!important;font-weight:600}.stock-help.is-warn{color:#b45309!important;font-weight:600}
.native-item-picker{position:relative;width:100%;z-index:30}.native-item-picker.is-open{z-index:9999}.native-item-picker .item-search-list{display:none;position:fixed;left:0;top:0;width:320px;max-height:300px;overflow:auto;background:#fff;border:1px solid #cbd5e1;border-radius:10px;box-shadow:0 18px 35px rgba(15,23,42,.20);padding:6px;z-index:2147483647}.native-item-picker.is-open .item-search-list{display:block}.native-item-picker .item-search-option{display:block;width:100%;text-align:left;border:0;background:#fff;border-radius:8px;padding:9px 10px;font-size:.8rem;color:#111827;line-height:1.2}.native-item-picker .item-search-option:hover,.native-item-picker .item-search-option.is-active{background:#eff6ff;color:#1d4ed8}.native-item-picker .item-search-option .meta{display:block;font-size:.7rem;color:#64748b;margin-top:3px}.native-item-picker .item-search-empty{padding:10px;color:#64748b;font-size:.8rem;text-align:center}.ir-line-card,.ir-lines,.panel-card .card-body,form#irForm{overflow:visible}.ir-lines{overflow:auto!important}
@media(max-width:1100px){#irForm>.row{grid-template-columns:1fr 1fr}.ir-line-card .row{grid-template-columns:minmax(240px,1fr) 140px}.ir-line-card .col-12{grid-column:1/-1!important}.ir-register-section form.row{grid-template-columns:repeat(3,1fr)}}@media(max-width:700px){#irForm>.row,.ir-line-card .row,.ir-register-section form.row{grid-template-columns:1fr}.ir-line-card .col-12{grid-column:auto!important;padding-top:0!important}.hero-band .col-lg-4{margin-top:10px}.movement-total-box{justify-content:space-between;gap:12px}.panel-card>.card-body{padding:12px!important}}
</style>

<script>
document.addEventListener('DOMContentLoaded', function(){
    const sourceStore = document.getElementById('sourceStore');
    const requestStore = document.getElementById('requestStore');
    const linesWrap = document.getElementById('irLines');
    const addLineBtn = document.getElementById('addLineBtn');
    const stockAvailability = <?php echo json_encode($stockAvailabilityByStore, JSON_NUMERIC_CHECK); ?>;

    function money(v){ return (parseFloat(v || 0)).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); }
    function sourceId(){ return parseInt(sourceStore ? sourceStore.value || 0 : 0, 10); }

    function rebuildNativePicker(select){
        if (!select || select.dataset.pickerReady === '1') return;
        select.dataset.pickerReady = '1';
        select.style.display = 'none';
        const wrapper = document.createElement('div');
        wrapper.className = 'native-item-picker';
        const input = document.createElement('input');
        input.type = 'text'; input.className = 'form-control item-search-input'; input.placeholder = 'Type item name, code or barcode...'; input.autocomplete = 'off';
        const list = document.createElement('div'); list.className = 'item-search-list';
        select.parentNode.insertBefore(wrapper, select); wrapper.appendChild(input); wrapper.appendChild(list); wrapper.appendChild(select);
        const options = Array.from(select.options).filter(o => o.value !== '');
        function render(filter){
            const q = (filter || '').toLowerCase().trim(); list.innerHTML = '';
            let shown = 0;
            options.forEach(opt => {
                const txt = opt.textContent.trim();
                if (q && !txt.toLowerCase().includes(q)) return;
                if (shown >= 80) return;
                const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'item-search-option';
                const selectedStoreId = sourceId();
                const optionItemId = parseInt(opt.value || 0, 10);
                const onHand = (selectedStoreId && stockAvailability[selectedStoreId] && stockAvailability[selectedStoreId][optionItemId])
                    ? parseFloat(stockAvailability[selectedStoreId][optionItemId])
                    : 0;
                const onHandClass = onHand > 0 ? 'text-success' : 'text-danger';
                btn.innerHTML = '<strong>' + txt.replace(/[&<>]/g, s => ({'&':'&amp;','<':'&lt;','>':'&gt;'}[s])) + '</strong>'
                    + '<span class="meta">Unit cost: ' + money(opt.dataset.cost || 0)
                    + ' &nbsp;|&nbsp; <span class="' + onHandClass + '">Qty on hand: ' + money(onHand) + '</span></span>';
                btn.addEventListener('click', function(){ select.value = opt.value; input.value = txt; wrapper.classList.remove('is-open'); select.dispatchEvent(new Event('change', {bubbles:true})); });
                list.appendChild(btn); shown++;
            });
            if (!shown) list.innerHTML = '<div class="item-search-empty">No matching items found</div>';
        }
        function positionList(){
            const rect = input.getBoundingClientRect();
            const gap = 5;
            const viewportPadding = 10;
            const preferredHeight = Math.min(300, Math.max(180, window.innerHeight * 0.42));
            const spaceBelow = window.innerHeight - rect.bottom - viewportPadding;
            const spaceAbove = rect.top - viewportPadding;
            const openUp = spaceBelow < 190 && spaceAbove > spaceBelow;
            const listHeight = Math.min(preferredHeight, Math.max(140, openUp ? spaceAbove - gap : spaceBelow - gap));
            list.style.left = Math.max(viewportPadding, Math.min(rect.left, window.innerWidth - rect.width - viewportPadding)) + 'px';
            list.style.width = Math.max(280, rect.width) + 'px';
            list.style.maxHeight = listHeight + 'px';
            list.style.top = openUp
                ? Math.max(viewportPadding, rect.top - listHeight - gap) + 'px'
                : Math.min(window.innerHeight - listHeight - viewportPadding, rect.bottom + gap) + 'px';
        }
        function openPicker(){ wrapper.classList.add('is-open'); render(input.value); positionList(); }
        input.addEventListener('focus', openPicker);
        input.addEventListener('click', openPicker);
        input.addEventListener('input', function(){ wrapper.classList.add('is-open'); render(input.value); positionList(); });
        document.addEventListener('click', function(e){ if (!wrapper.contains(e.target)) wrapper.classList.remove('is-open'); });
        window.addEventListener('resize', function(){ if (wrapper.classList.contains('is-open')) positionList(); });
        window.addEventListener('scroll', function(){ if (wrapper.classList.contains('is-open')) positionList(); }, true);
        select.addEventListener('change', function(){ const opt = select.options[select.selectedIndex]; if (opt && opt.value) input.value = opt.textContent.trim(); });
    }

    function updateLineNumbers(){
        const cards = linesWrap.querySelectorAll('.ir-line-card');
        cards.forEach((card, i) => {
            const strong = card.querySelector('strong'); if (strong) strong.textContent = 'Line ' + (i + 1);
            const remove = card.querySelector('.remove-line'); if (remove) remove.style.display = cards.length > 1 ? '' : 'none';
        });
        document.getElementById('lineCount').textContent = cards.length;
    }
    function updateTotals(){
        let total = 0;
        linesWrap.querySelectorAll('.ir-line-card').forEach(card => {
            const select = card.querySelector('select.item-select');
            const qty = parseFloat((card.querySelector('.qty-input') || {}).value || 0);
            const opt = select ? select.options[select.selectedIndex] : null;
            const cost = opt ? parseFloat(opt.dataset.cost || 0) : 0;
            total += qty * cost;
        });
        document.getElementById('estimatedValue').textContent = money(total);
    }
    function updateAvailability(card){
        const help = card.querySelector('.stock-help');
        const select = card.querySelector('select.item-select');
        if (!help || !select) return;
        help.className = 'stock-help small text-muted mt-1';
        const sid = sourceId();
        const itemId = parseInt(select.value || 0, 10);
        if (!sid || !itemId) { help.textContent = 'Select source store to see quantity on hand.'; return; }
        const bal = stockAvailability[sid] && stockAvailability[sid][itemId] ? parseFloat(stockAvailability[sid][itemId]) : 0;
        const qtyInput = card.querySelector('.qty-input');
        const requestedQty = qtyInput ? parseFloat(qtyInput.value || 0) : 0;
        if (requestedQty > 0 && requestedQty > bal) {
            const issueQty = Math.max(0, bal);
            const shortfallQty = requestedQty - issueQty;
            help.textContent = 'Warning: requested ' + money(requestedQty) + ', available ' + money(bal) + '. Posting will issue ' + money(issueQty) + ' and leave shortfall ' + money(shortfallQty) + '.';
            help.classList.add('is-warn');
        } else {
            help.textContent = 'Qty on hand at source: ' + money(bal);
            help.classList.add(bal > 0 ? 'is-ok' : 'is-empty');
        }
    }
    function wireCard(card){
        rebuildNativePicker(card.querySelector('select.item-select'));
        card.querySelectorAll('select.item-select,.qty-input').forEach(el => el.addEventListener('change', function(){ updateAvailability(card); updateTotals(); }));
        card.querySelectorAll('.qty-input').forEach(el => el.addEventListener('input', updateTotals));
        const remove = card.querySelector('.remove-line');
        if (remove) remove.addEventListener('click', function(){ card.remove(); updateLineNumbers(); updateTotals(); });
        updateAvailability(card);
    }
    if (addLineBtn) addLineBtn.addEventListener('click', function(){
        const first = linesWrap.querySelector('.ir-line-card');
        if (!first) return;
        const clone = first.cloneNode(true);
        clone.querySelectorAll('input').forEach(input => input.value = '');
        clone.querySelectorAll('select').forEach(select => { select.value = ''; select.style.display = ''; select.dataset.pickerReady = ''; });
        clone.querySelectorAll('.native-item-picker').forEach(p => { const sel = p.querySelector('select'); if (sel) p.parentNode.insertBefore(sel, p); p.remove(); });
        linesWrap.appendChild(clone); wireCard(clone); updateLineNumbers(); updateTotals();
        linesWrap.scrollTop = linesWrap.scrollHeight;
    });
    if (sourceStore) sourceStore.addEventListener('change', function(){ linesWrap.querySelectorAll('.ir-line-card').forEach(updateAvailability); });
    if (requestStore && sourceStore) {
        function checkStores(){ if (requestStore.value && sourceStore.value && requestStore.value === sourceStore.value) { sourceStore.setCustomValidity('Source store cannot be the same as requesting store.'); } else { sourceStore.setCustomValidity(''); } }
        requestStore.addEventListener('change', checkStores); sourceStore.addEventListener('change', checkStores);
    }
    linesWrap.querySelectorAll('.ir-line-card').forEach(wireCard); updateLineNumbers(); updateTotals();



    document.querySelectorAll('.issue-form').forEach(function(form){
        function syncRow(row){
            const approvedInput = row.querySelector('.approved-qty-input');
            const issueInput = row.querySelector('.issue-qty-input');
            const preview = row.querySelector('.issue-shortfall-preview');
            if (!approvedInput || !issueInput || !preview) return;

            const requested = parseFloat(approvedInput.dataset.requested || '0') || 0;
            const available = parseFloat(issueInput.dataset.available || '0') || 0;
            let approved = parseFloat(approvedInput.value || '0') || 0;
            let issue = parseFloat(issueInput.value || '0') || 0;

            if (approved < 0) approved = 0;
            if (requested > 0 && approved > requested) approved = requested;
            approvedInput.value = approved;
            issueInput.dataset.approved = approved;
            issueInput.max = Math.min(approved, available);

            if (issue < 0) issue = 0;
            if (issue > approved) issue = approved;
            if (issue > available) issue = available;
            issueInput.value = issue;

            const shortfall = Math.max(0, approved - issue);
            preview.textContent = money(shortfall);
            preview.classList.toggle('text-warning', shortfall > 0);
        }

        form.querySelectorAll('tr').forEach(syncRow);
        form.addEventListener('input', function(e){
            if (e.target.classList.contains('approved-qty-input') || e.target.classList.contains('issue-qty-input')) {
                const row = e.target.closest('tr');
                if (row) syncRow(row);
            }
        });
    });

    function toggleReqPanel(targetId, forceOpen){
        const row = document.getElementById(targetId);
        if (!row) return;
        const currentlyOpen = row.style.display !== 'none';
        const shouldOpen = typeof forceOpen === 'boolean' ? forceOpen : !currentlyOpen;
        row.style.display = shouldOpen ? '' : 'none';
        document.querySelectorAll('[data-target="' + targetId + '"]').forEach(function(btn){
            btn.classList.toggle('is-open', shouldOpen);
        });
        if (shouldOpen) {
            row.scrollIntoView({behavior:'smooth', block:'nearest'});
            const firstIssue = row.querySelector('.issue-qty-input');
            if (firstIssue) setTimeout(function(){ firstIssue.focus(); firstIssue.select(); }, 250);
        }
    }

    document.querySelectorAll('.req-toggle').forEach(btn => btn.addEventListener('click', function(){
        toggleReqPanel(this.dataset.target);
    }));

    document.querySelectorAll('.req-issue-open').forEach(btn => btn.addEventListener('click', function(){
        toggleReqPanel(this.dataset.target, true);
    }));
});
</script>

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