<?php
require_once __DIR__ . '/../helpers/auth.php';
require_once __DIR__ . '/../helpers/audit.php';
require_once __DIR__ . '/../helpers/inventory.php';

require_role(['admin', 'staff']);

$pdo = db();
$title = 'Stock Out - Caerus Tech IMS';
$user = current_user();

function h(?string $value): string
{
    return htmlspecialchars((string)($value ?? ''), ENT_QUOTES, 'UTF-8');
}
function post_str(string $key): string
{
    return trim((string)($_POST[$key] ?? ''));
}
function post_int(string $key): int
{
    return (int)($_POST[$key] ?? 0);
}

if (isset($_GET['ajax']) && $_GET['ajax'] === 'lookup') {
    header('Content-Type: application/json; charset=utf-8');
    $code = trim((string)($_GET['code'] ?? ''));
    if ($code === '') {
        echo json_encode(['ok' => false, 'error' => 'Missing scan code']);
        exit;
    }

    try {
        $product = inventory_find_product_by_code($pdo, $code, true);
        if (!$product) {
            echo json_encode(['ok' => false, 'error' => 'Barcode or SKU not found']);
            exit;
        }

        echo json_encode([
            'ok' => true,
            'product' => [
                'id' => (int)$product['id'],
                'sku' => (string)$product['sku'],
                'name' => (string)$product['name'],
                'unit' => (string)($product['unit'] ?? 'pcs'),
                'barcode_value' => (string)($product['barcode_value'] ?? ''),
                'current_stock' => (int)$product['current_stock'],
                'reorder_level' => (int)($product['reorder_level'] ?? 0),
            ],
        ]);
    } catch (Throwable $e) {
        http_response_code(500);
        echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
    }
    exit;
}

$error = '';
$success = '';
$lastStock = null;
$products = $pdo->query('SELECT id, sku, name, barcode_value FROM products WHERE is_active = 1 ORDER BY name ASC')->fetchAll(PDO::FETCH_ASSOC);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $product_id = post_int('product_id');
    $qty = post_int('quantity');
    $notes = post_str('notes');

    if ($product_id <= 0 || $qty <= 0) {
        $error = 'Scan a valid product and enter a quantity greater than zero.';
    } else {
        try {
            $result = inventory_create_movement(
                $pdo,
                $product_id,
                'OUT',
                $qty,
                null,
                'MANUAL',
                null,
                $notes !== '' ? $notes : null,
                (int)($user['id'] ?? 0),
                true
            );
            $lastStock = $result['current_stock'];
            $product = inventory_get_product($pdo, $product_id);
            audit_log('STOCK_OUT', 'inventory_movements', (string)$result['movement_id'], json_encode([
                'product_id' => $product_id,
                'sku' => $product['sku'] ?? null,
                'barcode_value' => $product['barcode_value'] ?? null,
                'quantity' => $qty,
            ], JSON_UNESCAPED_SLASHES));
            $success = 'Stock released successfully. Remaining stock: ' . (int)$lastStock;
        } catch (Throwable $e) {
            $error = 'Unable to save stock-out entry: ' . $e->getMessage();
        }
    }
}

$recent = $pdo->query("
    SELECT m.id, m.created_at, m.quantity, m.notes, p.sku, p.name, p.barcode_value
    FROM inventory_movements m
    INNER JOIN products p ON p.id = m.product_id
    WHERE m.movement_type = 'OUT'
    ORDER BY m.created_at DESC, m.id DESC
    LIMIT 20
")->fetchAll(PDO::FETCH_ASSOC);

require_once __DIR__ . '/../templates/header.php';
require_once __DIR__ . '/../templates/sidebar.php';
?>
<main class="col-12 col-lg-10 app-content">
  <div class="page-head">
    <div>
      <div class="page-kicker">Inventory release</div>
      <h1 class="page-title">Stock out</h1>
      <p class="page-subtitle">Deduct stock by scanning the barcode, confirming the quantity, and saving. Negative inventory is blocked automatically.</p>
    </div>
  </div>

  <div class="row g-3 mb-3">
    <div class="col-12 col-md-4"><div class="stat-card"><div class="stat-label">Active products</div><div class="stat-value"><?= count($products) ?></div><div class="stat-sub">Available for stock release</div></div></div>
    <div class="col-12 col-md-4"><div class="stat-card"><div class="stat-label">Recent OUT rows</div><div class="stat-value"><?= count($recent) ?></div><div class="stat-sub">Last 20 movements</div></div></div>
    <div class="col-12 col-md-4"><div class="stat-card"><div class="stat-label">Last remaining stock</div><div class="stat-value"><?= $lastStock !== null ? (int)$lastStock : '—' ?></div><div class="stat-sub">From your latest successful entry</div></div></div>
  </div>

  <?php if ($error !== ''): ?>
    <div class="alert alert-danger mb-3"><?= h($error) ?></div>
  <?php endif; ?>
  <?php if ($success !== ''): ?>
    <div class="alert alert-success mb-3"><?= h($success) ?></div>
  <?php endif; ?>

  <div class="row g-3 align-items-start">
    <div class="col-12 col-xl-5">
      <div class="card scanner-panel">
        <div class="card-body p-4">
          <div class="d-flex justify-content-between align-items-start mb-3">
            <div>
              <h5 class="mb-1">Release stock</h5>
              <div class="text-muted small">Scanner flow: scan barcode → quantity → save.</div>
            </div>
            <button class="btn btn-sm btn-outline-secondary" type="button" id="btnCamera">Camera scan</button>
          </div>

          <form method="post" id="stockForm" autocomplete="off" class="d-grid gap-3">
            <div>
              <label class="form-label" for="scan_code">Scan barcode or SKU</label>
              <input class="form-control" id="scan_code" type="text" placeholder="Scan with USB scanner or type manually" autocomplete="off" autocapitalize="off" spellcheck="false">
              <div class="form-text">You can still choose a product manually below if needed.</div>
            </div>

            <div class="soft-panel">
              <div class="small text-muted mb-1">Selected product</div>
              <div class="fw-semibold" id="selected_name">No product selected</div>
              <div class="small text-muted" id="selected_meta">Scan a barcode or choose a product below.</div>
            </div>

            <div>
              <label class="form-label">Fallback product selector</label>
              <select class="form-select" id="product_id" name="product_id" required>
                <option value="0">Select a product</option>
                <?php foreach ($products as $product): ?>
                  <option value="<?= (int)$product['id'] ?>" data-sku="<?= h($product['sku']) ?>" data-barcode="<?= h($product['barcode_value'] ?? '') ?>">
                    <?= h($product['name']) ?> (<?= h($product['sku']) ?><?= !empty($product['barcode_value']) ? ' · ' . h($product['barcode_value']) : '' ?>)
                  </option>
                <?php endforeach; ?>
              </select>
            </div>

            <div class="row g-3">
              <div class="col-md-6">
                <label class="form-label">Current stock</label>
                <input class="form-control" id="current_stock" type="text" value="-" readonly>
              </div>
              <div class="col-md-6">
                <label class="form-label">Quantity</label>
                <input class="form-control" id="quantity" name="quantity" type="number" min="1" step="1" required>
              </div>
            </div>

            <div class="d-flex align-items-center justify-content-between gap-3">
              <div class="form-check">
                <input class="form-check-input" type="checkbox" id="auto_submit">
                <label class="form-check-label" for="auto_submit">Auto-save when qty is ready</label>
              </div>
              <div class="small text-muted">Negative stock is blocked.</div>
            </div>

            <div>
              <label class="form-label">Notes</label>
              <input class="form-control" name="notes" maxlength="255" placeholder="Reason, request number, or destination">
            </div>

            <button class="btn btn-dark w-100" type="submit">Save stock out</button>
          </form>
        </div>
      </div>
    </div>

    <div class="col-12 col-xl-7">
      <div class="card">
        <div class="card-body p-4">
          <div class="d-flex justify-content-between align-items-center mb-3">
            <div>
              <h5 class="mb-1">Recent stock-out history</h5>
              <div class="text-muted small">Verify released quantities and notes in one place.</div>
            </div>
          </div>

          <div class="table-responsive">
            <table class="table align-middle">
              <thead>
                <tr>
                  <th>Date</th>
                  <th>Product</th>
                  <th class="text-end">Qty</th>
                  <th>Notes</th>
                </tr>
              </thead>
              <tbody>
                <?php if (!$recent): ?>
                  <tr><td colspan="4" class="text-muted">No stock-out records yet.</td></tr>
                <?php else: ?>
                  <?php foreach ($recent as $row): ?>
                    <tr>
                      <td><?= h($row['created_at']) ?></td>
                      <td>
                        <div class="fw-semibold"><?= h($row['name']) ?></div>
                        <div class="small text-muted"><span class="code-chip"><?= h($row['sku']) ?></span><?= !empty($row['barcode_value']) ? ' · ' . h($row['barcode_value']) : '' ?></div>
                      </td>
                      <td class="text-end fw-semibold"><?= (int)$row['quantity'] ?></td>
                      <td><?= h($row['notes'] ?? '—') ?></td>
                    </tr>
                  <?php endforeach; ?>
                <?php endif; ?>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </div>
</main>

<div class="modal fade" id="cameraModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Camera barcode scanner</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <div class="alert alert-info py-2 mb-3">Supported: UPC-A, UPC-E, EAN, Code 128, Code 39, and QR.</div>
        <video id="barcode_video" style="width:100%; border-radius:14px;" muted playsinline></video>
        <div id="scan_status" class="scanner-status mt-2">Ready to scan.</div>
      </div>
    </div>
  </div>
</div>

<?php require_once __DIR__ . '/../templates/footer.php'; ?>
<script src="https://cdn.jsdelivr.net/npm/@zxing/library@0.21.3/umd/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@zxing/browser@0.1.5/umd/zxing-browser.min.js"></script>
<script>
(function () {
  const scanInput = document.getElementById('scan_code');
  const selectEl = document.getElementById('product_id');
  const qtyEl = document.getElementById('quantity');
  const stockEl = document.getElementById('current_stock');
  const formEl = document.getElementById('stockForm');
  const autoSubmitEl = document.getElementById('auto_submit');
  const selectedNameEl = document.getElementById('selected_name');
  const selectedMetaEl = document.getElementById('selected_meta');
  const btnCamera = document.getElementById('btnCamera');
  const modalEl = document.getElementById('cameraModal');
  const videoEl = document.getElementById('barcode_video');
  const statusEl = document.getElementById('scan_status');
  const cameraModal = new bootstrap.Modal(modalEl);
  let controls = null;
  let cameraStream = null;
  let scanTimer = null;
  let zxingReader = null;

  function setSelected(product) {
    if (!product) {
      selectedNameEl.textContent = 'No product selected';
      selectedMetaEl.textContent = 'Scan a barcode or choose a product below.';
      stockEl.value = '-';
      return;
    }

    selectedNameEl.textContent = product.name;
    const bits = [];
    if (product.sku) bits.push('SKU ' + product.sku);
    if (product.barcode_value) bits.push('Barcode ' + product.barcode_value);
    if (product.unit) bits.push(product.unit);
    selectedMetaEl.textContent = bits.join(' · ');
    stockEl.value = String(product.current_stock ?? '-');
  }

  function digitsOnly(value) {
    return String(value || '').replace(/\D+/g, '');
  }

  function buildLookupCandidates(value) {
    const raw = String(value || '').trim();
    if (!raw) return [];

    const digits = digitsOnly(raw);
    const candidates = [];
    const push = (candidate) => {
      candidate = String(candidate || '').trim();
      if (candidate && !candidates.includes(candidate)) {
        candidates.push(candidate);
      }
    };

    push(raw);
    push(digits);

    if (digits) {
      push(digits.replace(/^0+/, ''));
      if (digits.length === 13 && digits.startsWith('0')) {
        push(digits.slice(1));
      }
      if (digits.length === 12) {
        push('0' + digits);
      }
    }

    return candidates.filter(Boolean);
  }

  function optionToProduct(option) {
    if (!option || !option.value || option.value === '0') {
      return null;
    }

    return {
      id: Number(option.value || 0),
      name: option.dataset.name || String(option.textContent || '').split(' (')[0].trim(),
      sku: option.dataset.sku || '',
      barcode_value: option.dataset.barcode || '',
      unit: option.dataset.unit || '',
      supplier_name: option.dataset.supplier || '',
      current_stock: option.dataset.stock !== undefined && option.dataset.stock !== '' ? Number(option.dataset.stock) : '-',
    };
  }

  function findLocalProduct(code) {
    const candidates = buildLookupCandidates(code);
    if (!candidates.length) return null;

    for (const option of Array.from(selectEl.options)) {
      const product = optionToProduct(option);
      if (!product) continue;

      const productCandidates = new Set([
        ...buildLookupCandidates(product.barcode_value),
        ...buildLookupCandidates(product.sku),
      ]);

      for (const candidate of candidates) {
        if (productCandidates.has(candidate)) {
          return product;
        }
      }
    }

    return null;
  }

  function maybeAutoSubmit() {
    const pid = Number(selectEl.value || 0);
    const qty = Number(qtyEl.value || 0);
    if (autoSubmitEl.checked && pid > 0 && qty > 0) {
      formEl.submit();
    }
  }

  async function lookupProduct(code, focusQty = true) {
    const value = String(code || '').trim();
    if (!value) {
      setSelected(null);
      return false;
    }

    const localProduct = findLocalProduct(value);
    if (localProduct) {
      setSelected(localProduct);
      statusEl.textContent = 'Matched ' + localProduct.name;
      if (focusQty) qtyEl.focus();
      maybeAutoSubmit();
    }

    try {
      const res = await fetch(`stock_out.php?ajax=lookup&code=${encodeURIComponent(value)}`, {
        headers: { 'Accept': 'application/json' }
      });
      const data = await res.json();
      if (!data.ok) {
        if (localProduct) {
          return true;
        }
        setSelected(null);
        statusEl.textContent = data.error || 'Product not found.';
        return false;
      }

      const product = data.product;
      setSelected(product);
      statusEl.textContent = 'Matched ' + product.name;
      if (focusQty) qtyEl.focus();
      maybeAutoSubmit();
      return true;
    } catch (error) {
      if (localProduct) {
        return true;
      }
      statusEl.textContent = 'Lookup failed.';
      return false;
    }
  }

  let lookupTimer = null;

  function scheduleLookup(delay = 250, focusQty = false) {
    const code = String(scanInput.value || '').trim();
    window.clearTimeout(lookupTimer);

    if (!code) {
      setSelected(null);
      return;
    }

    lookupTimer = window.setTimeout(() => {
      lookupProduct(code, focusQty);
    }, delay);
  }

  scanInput.addEventListener('keydown', function (event) {
    if (event.key === 'Enter') {
      event.preventDefault();
      window.clearTimeout(lookupTimer);
      lookupProduct(scanInput.value, true);
    }
  });

  scanInput.addEventListener('input', function () {
    scheduleLookup(250, false);
  });

  scanInput.addEventListener('change', function () {
    scheduleLookup(0, false);
  });

  scanInput.addEventListener('blur', function () {
    scheduleLookup(0, false);
  });

  scanInput.addEventListener('paste', function () {
    window.setTimeout(() => scheduleLookup(0, false), 0);
  });

  selectEl.addEventListener('change', function () {
    const option = selectEl.options[selectEl.selectedIndex];
    const preferred = option?.dataset?.barcode || option?.dataset?.sku || '';
    if (!preferred) {
      setSelected(null);
      return;
    }
    lookupProduct(preferred, false);
  });

  qtyEl.addEventListener('input', maybeAutoSubmit);

  async function stopCamera() {
    try {
      if (scanTimer) {
        window.clearInterval(scanTimer);
      }
    } catch (error) {}
    scanTimer = null;

    try {
      if (controls && typeof controls.stop === 'function') {
        controls.stop();
      }
    } catch (error) {}
    controls = null;

    try {
      if (zxingReader && typeof zxingReader.reset === 'function') {
        zxingReader.reset();
      }
    } catch (error) {}
    zxingReader = null;

    try {
      if (cameraStream) {
        cameraStream.getTracks().forEach((track) => track.stop());
      }
    } catch (error) {}
    cameraStream = null;

    try {
      videoEl.pause();
      videoEl.srcObject = null;
      videoEl.removeAttribute('src');
      videoEl.load();
    } catch (error) {}
  }

  function normalizeScannedCode(value) {
    return String(value || '').replace(/\s+/g, '').trim();
  }

  async function handleDetectedCode(rawText) {
    const text = normalizeScannedCode(rawText);
    if (!text) return;
    statusEl.textContent = 'Detected ' + text;
    scanInput.value = text;
    await stopCamera();
    cameraModal.hide();
    lookupProduct(text, true);
  }

  async function startBarcodeDetectorScanner() {
    const supportedFormats = [
      'ean_13', 'ean_8', 'upc_a', 'upc_e', 'code_128', 'code_39', 'codabar', 'itf'
    ];
    const detector = new BarcodeDetector({ formats: supportedFormats });

    cameraStream = await navigator.mediaDevices.getUserMedia({
      audio: false,
      video: {
        facingMode: { ideal: 'environment' },
        width: { ideal: 1280 },
        height: { ideal: 720 }
      }
    });

    videoEl.setAttribute('autoplay', 'autoplay');
    videoEl.setAttribute('muted', 'muted');
    videoEl.setAttribute('playsinline', 'playsinline');
    videoEl.srcObject = cameraStream;
    await videoEl.play();

    statusEl.textContent = 'Scanning... point the barcode clearly inside the camera.';

    scanTimer = window.setInterval(async function () {
      if (!videoEl.videoWidth || !videoEl.videoHeight) {
        return;
      }

      try {
        const barcodes = await detector.detect(videoEl);
        if (barcodes && barcodes.length > 0) {
          const raw = barcodes[0].rawValue || '';
          if (raw) {
            await handleDetectedCode(raw);
          }
        }
      } catch (error) {
        statusEl.textContent = 'Scanning...';
      }
    }, 300);
  }

  async function startZXingScanner() {
    if (!window.ZXingBrowser || !window.ZXing) {
      throw new Error('Scanner library failed to load.');
    }

    const formats = [
      ZXing.BarcodeFormat.UPC_A,
      ZXing.BarcodeFormat.UPC_E,
      ZXing.BarcodeFormat.EAN_13,
      ZXing.BarcodeFormat.EAN_8,
      ZXing.BarcodeFormat.CODE_128,
      ZXing.BarcodeFormat.CODE_39,
      ZXing.BarcodeFormat.CODE_93,
      ZXing.BarcodeFormat.ITF,
      ZXing.BarcodeFormat.CODABAR,
      ZXing.BarcodeFormat.QR_CODE,
    ];

    const hints = new Map();
    hints.set(ZXing.DecodeHintType.POSSIBLE_FORMATS, formats);
    hints.set(ZXing.DecodeHintType.TRY_HARDER, true);

    zxingReader = new ZXingBrowser.BrowserMultiFormatReader(hints);

    const devices = await ZXingBrowser.BrowserCodeReader.listVideoInputDevices();
    let preferredDeviceId = null;
    if (devices && devices.length) {
      const rear = devices.find((device) => /back|rear|environment/i.test(device.label || ''));
      preferredDeviceId = (rear || devices[0]).deviceId;
    }

    statusEl.textContent = 'Scanning... point the barcode clearly inside the camera.';
    controls = await zxingReader.decodeFromVideoDevice(preferredDeviceId, videoEl, async (result, err) => {
      if (result) {
        const text = result.getText ? result.getText() : String(result);
        await handleDetectedCode(text);
        return;
      }

      if (err && err.name && err.name !== 'NotFoundException') {
        statusEl.textContent = 'Trying to focus camera...';
      }
    });
  }

  async function startCamera() {
    if (!window.isSecureContext) {
      alert('Phone camera scanning needs HTTPS. Open the site with https:// first.');
      return;
    }

    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      alert('This browser does not support camera scanning on this page.');
      return;
    }

    await stopCamera();
    cameraModal.show();
    statusEl.textContent = 'Starting camera...';

    try {
      if ('BarcodeDetector' in window) {
        await startBarcodeDetectorScanner();
      } else {
        await startZXingScanner();
      }
    } catch (error) {
      console.error('Camera scanner error:', error);
      statusEl.textContent = error && error.message ? error.message : 'Camera failed to start.';
    }
  }

  btnCamera.addEventListener('click', startCamera);
  modalEl.addEventListener('hidden.bs.modal', stopCamera);
  window.addEventListener('load', function () { scanInput.focus(); });
})();
</script>
