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

$pageTitle = 'GRN Receiving';

if (file_exists(__DIR__ . '/../../includes/permission_check.php')) {
    require_once __DIR__ . '/../../includes/permission_check.php';
    if (function_exists('require_permission')) {
        require_permission($pdo, 'purchase_orders', 'edit');
    }
}

function h($v){ return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
function money($v){ return number_format((float)$v,2); }
function qty($v){ return number_format((float)$v,4); }

$errors = [];

/* Ensure GRN table */
try{
    $pdo->exec("CREATE TABLE IF NOT EXISTS grn (
        id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        po_id BIGINT UNSIGNED NOT NULL,
        grn_date DATETIME NOT NULL,
        received_by INT UNSIGNED NULL,
        notes TEXT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )");

    $pdo->exec("CREATE TABLE IF NOT EXISTS grn_items (
        id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        grn_id BIGINT UNSIGNED NOT NULL,
        item_id INT UNSIGNED NOT NULL,
        store_id INT UNSIGNED NULL,
        qty_received DECIMAL(14,4) DEFAULT 0,
        unit_cost DECIMAL(14,4) DEFAULT 0,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )");

    $storeColumnCheck = $pdo->prepare("
        SELECT COUNT(*)
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = 'grn_items'
          AND column_name = 'store_id'
    ");
    $storeColumnCheck->execute();

    if ((int)$storeColumnCheck->fetchColumn() === 0) {
        $pdo->exec("
            ALTER TABLE grn_items
            ADD COLUMN store_id INT UNSIGNED NULL AFTER item_id
        ");
    }
}catch(Throwable $e){
    $errors[] = $e->getMessage();
}

/* Handle receive */
if($_SERVER['REQUEST_METHOD']=='POST'){
    try{
        if(function_exists('verify_csrf')) verify_csrf();

        $poId = (int)$_POST['po_id'];

        if ($poId <= 0) {
            throw new RuntimeException('Invalid purchase order.');
        }

        $poStmt = $pdo->prepare("
            SELECT id, store_id, po_no
            FROM purchase_orders
            WHERE id = ?
            LIMIT 1
        ");
        $poStmt->execute([$poId]);
        $po = $poStmt->fetch(PDO::FETCH_ASSOC);

        if (!$po) {
            throw new RuntimeException('Purchase order not found.');
        }

        $activeStores = [];
        $storeStmt = $pdo->query("
            SELECT id, location_name
            FROM store_locations
            WHERE is_active = 1
            ORDER BY location_name ASC
        ");

        foreach ($storeStmt->fetchAll(PDO::FETCH_ASSOC) as $storeRow) {
            $activeStores[(int)$storeRow['id']] = (string)$storeRow['location_name'];
        }

        $defaultStoreId = (int)($po['store_id'] ?? 0);
        if ($defaultStoreId <= 0 || !isset($activeStores[$defaultStoreId])) {
            throw new RuntimeException('The purchase order default receiving store is not active.');
        }

        $pdo->beginTransaction();

        $stmt = $pdo->prepare("INSERT INTO grn (po_id,grn_date,received_by) VALUES (?,?,?)");
        $stmt->execute([$poId, date('Y-m-d H:i:s'), $_SESSION['user_id'] ?? null]);
        $grnId = $pdo->lastInsertId();

        foreach($_POST['qty'] as $itemId=>$q){
            $q = (float)$q;
            if($q<=0) continue;

            $cost = (float)($_POST['cost'][$itemId] ?? 0);

            /*
             * Each item may override the PO default receiving store.
             * Blank/zero means use the purchase order's receiving store.
             */
            $lineStoreId = (int)($_POST['store_id'][$itemId] ?? 0);
            if ($lineStoreId <= 0) {
                $lineStoreId = $defaultStoreId;
            }

            if (!isset($activeStores[$lineStoreId])) {
                throw new RuntimeException(
                    'Please select a valid storage area for item #' . (int)$itemId . '.'
                );
            }

            $stmt = $pdo->prepare("
                INSERT INTO grn_items
                (grn_id, item_id, store_id, qty_received, unit_cost)
                VALUES (?, ?, ?, ?, ?)
            ");
            $stmt->execute([$grnId, $itemId, $lineStoreId, $q, $cost]);

            /* Stock movement goes to the selected line storage area. */
            $stmt = $pdo->prepare("
                INSERT INTO stock_movements
                (
                    item_id,
                    store_id,
                    movement_type,
                    qty_in,
                    unit_cost,
                    total_cost,
                    reference_type,
                    reference_id,
                    notes
                )
                VALUES (?, ?, 'GRN', ?, ?, ?, 'GRN', ?, ?)
            ");
            $stmt->execute([
                $itemId,
                $lineStoreId,
                $q,
                $cost,
                $q * $cost,
                $grnId,
                'GRN received from PO '
                    . ($po['po_no'] ?? ('#' . $poId))
                    . ' into '
                    . $activeStores[$lineStoreId]
            ]);

            /* update received qty */
            $stmt = $pdo->prepare("UPDATE purchase_order_items SET received_qty = received_qty + ? WHERE purchase_order_id=? AND item_id=?");
            $stmt->execute([$q,$poId,$itemId]);
        }

        /* update PO status */
        $stmt = $pdo->prepare("
            UPDATE purchase_orders 
            SET status = 
                CASE 
                    WHEN EXISTS(
                        SELECT 1 FROM purchase_order_items 
                        WHERE purchase_order_id=? AND qty > received_qty
                    ) THEN 'part_received'
                    ELSE 'received'
                END
            WHERE id=?");
        $stmt->execute([$poId,$poId]);

        $pdo->commit();

        header("Location: grn_receive.php?po_id=".$poId."&success=1");
        exit;

    }catch(Throwable $e){
        $pdo->rollBack();
        $errors[] = $e->getMessage();
    }
}

/* Load approved/ordered POs */
$pos = $pdo->query("
    SELECT po.*, s.supplier_name, sl.location_name
    FROM purchase_orders po
    LEFT JOIN suppliers s ON s.id=po.supplier_id
    LEFT JOIN store_locations sl ON sl.id=po.store_id
    WHERE po.status IN ('approved','ordered','part_received')
    ORDER BY po.created_at DESC
")->fetchAll(PDO::FETCH_ASSOC);

$poId = (int)($_GET['po_id'] ?? 0);
$items = [];
$stores = [];

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

$selectedPo = null;

if($poId){
    $poStmt = $pdo->prepare("
        SELECT po.*, sl.location_name
        FROM purchase_orders po
        LEFT JOIN store_locations sl ON sl.id = po.store_id
        WHERE po.id = ?
        LIMIT 1
    ");
    $poStmt->execute([$poId]);
    $selectedPo = $poStmt->fetch(PDO::FETCH_ASSOC) ?: null;

    $stmt = $pdo->prepare("
        SELECT poi.*, ii.item_name, ii.item_code
        FROM purchase_order_items poi
        LEFT JOIN inventory_items ii ON ii.id=poi.item_id
        WHERE purchase_order_id=?");
    $stmt->execute([$poId]);
    $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

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

<div class="card panel-card mb-4">
    <div class="card-header"><h5>Select Purchase Order</h5></div>
    <div class="card-body">
        <form method="get">
            <select name="po_id" class="form-select" onchange="this.form.submit()">
                <option value="">Select PO...</option>
                <?php foreach($pos as $p): ?>
                    <option value="<?php echo $p['id']; ?>" <?php if($poId==$p['id']) echo 'selected'; ?>>
                        <?php echo $p['po_no'].' - '.$p['supplier_name'].' ('.$p['status'].')'; ?>
                    </option>
                <?php endforeach; ?>
            </select>
        </form>
    </div>
</div>

<?php if($poId && $items): ?>
<form method="post">
<?php if(function_exists('csrf_field')) echo csrf_field(); ?>
<input type="hidden" name="po_id" value="<?php echo $poId; ?>">

<div class="card panel-card">
    <div class="card-header"><h5>Receive Items</h5></div>
    <div class="card-body p-0">
        <div class="alert alert-info rounded-0 border-start-0 border-end-0 mb-0">
            Each item defaults to the purchase order receiving store. Select a different
            Storage Area on a line to receive items from the same PO into different locations.
        </div>
        <table class="table table-modern">
            <thead>
                <tr>
                    <th>Item</th>
                    <th class="text-end">Ordered</th>
                    <th class="text-end">Received</th>
                    <th class="text-end">Balance</th>
                    <th>Storage Area</th>
                    <th class="text-end">Receive Now</th>
                    <th class="text-end">Cost</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach($items as $it): 
                    $bal = $it['qty'] - $it['received_qty'];
                ?>
                <tr>
                    <td><?php echo h($it['item_name']); ?></td>
                    <td class="text-end"><?php echo qty($it['qty']); ?></td>
                    <td class="text-end"><?php echo qty($it['received_qty']); ?></td>
                    <td class="text-end"><?php echo qty($bal); ?></td>
                    <td style="min-width:220px;">
                        <select
                            name="store_id[<?php echo (int)$it['item_id']; ?>]"
                            class="form-select"
                        >
                            <option value="0">
                                Use default<?php echo $selectedPo && !empty($selectedPo['location_name']) ? ' — ' . h($selectedPo['location_name']) : ''; ?>
                            </option>

                            <?php foreach ($stores as $store): ?>
                                <option
                                    value="<?php echo (int)$store['id']; ?>"
                                    <?php echo $selectedPo && (int)$store['id'] === (int)$selectedPo['store_id'] ? 'selected' : ''; ?>
                                >
                                    <?php echo h($store['location_name']); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Override the PO receiving store for this item.</div>
                    </td>
                    <td class="text-end">
                        <input type="number" step="0.0001" name="qty[<?php echo $it['item_id']; ?>]" 
                               value="<?php echo $bal; ?>" class="form-control text-end">
                    </td>
                    <td class="text-end">
                        <input type="number" step="0.0001" name="cost[<?php echo $it['item_id']; ?>]" 
                               value="<?php echo $it['unit_cost']; ?>" class="form-control text-end">
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <div class="card-footer text-end">
        <button class="btn btn-success">
            <i class="bi bi-check-circle"></i> Receive Stock
        </button>
    </div>
</div>
</form>
<?php endif; ?>

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