<?php
/*
|--------------------------------------------------------------------------
| company/sp_part_request_form.php — create a Part / Toner Request
|--------------------------------------------------------------------------
*/
ob_start(); session_start();
require_once '../config/database.php';
require_once '../config/modules.php';
require_once '../config/module_access.php';
require_once '../config/part_request_flow.php';
if (!isset($_SESSION['user_id']) || empty($_SESSION['company_id'])) { header('Location: ../auth/login.php'); exit; }
$companyId=(int)$_SESSION['company_id']; $userId=(int)$_SESSION['user_id']; $role=$_SESSION['role']??''; $companyName=$_SESSION['company_name']??'Company'; $userName=$_SESSION['name']??'Staff';
$enabled=company_enabled_modules($pdo,$companyId);
if(!module_on($enabled,'part_request')){http_response_code(403);exit('Part/Toner Request is not enabled for your company.');}
if(!function_exists('esc')){function esc($v){return htmlspecialchars((string)$v,ENT_QUOTES,'UTF-8');}}
pr_ensure_schema($pdo);
$prole=pr_role($pdo,$companyId,$userId,$role);
$canView=pr_can_create($prole);
$canHandle=pr_can_queue($prole);
if(!$canView){http_response_code(403);exit('You do not have permission to create requests. Ask your admin to assign you a role.');}
// current staff code
$myCode=''; try{ $s=$pdo->prepare("SELECT staff_code FROM company_staff WHERE company_id=? AND user_id=? LIMIT 1"); $s->execute([$companyId,$userId]); $myCode=(string)($s->fetchColumn()?:''); }catch(Throwable $e){}

/* Tables (idempotent) */
$pdo->exec("
  CREATE TABLE IF NOT EXISTS sp_part_requests (
    id INT AUTO_INCREMENT PRIMARY KEY,
    company_id INT NOT NULL,
    req_no VARCHAR(40) DEFAULT NULL,
    req_date DATE DEFAULT NULL,
    machine_no VARCHAR(100) DEFAULT NULL,
    sd_no VARCHAR(50) DEFAULT NULL,
    customer_name VARCHAR(255) DEFAULT NULL,
    location VARCHAR(255) DEFAULT NULL,
    issued_by_user_id INT DEFAULT NULL,
    issued_by_code VARCHAR(50) DEFAULT NULL,
    issued_by_name VARCHAR(255) DEFAULT NULL,
    ack_manager VARCHAR(255) DEFAULT NULL,
    note TEXT,
    packing_no VARCHAR(100) DEFAULT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'open',
    handled_by_user_id INT DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX(company_id,status)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
");
$pdo->exec("
  CREATE TABLE IF NOT EXISTS sp_part_request_items (
    id INT AUTO_INCREMENT PRIMARY KEY,
    company_id INT NOT NULL,
    request_id INT NOT NULL,
    order_code VARCHAR(100) DEFAULT NULL,
    part_details VARCHAR(500) DEFAULT NULL,
    type VARCHAR(60) DEFAULT NULL,
    color VARCHAR(20) DEFAULT NULL,
    qty INT NOT NULL DEFAULT 0,
    barcode VARCHAR(150) DEFAULT NULL,
    note VARCHAR(255) DEFAULT NULL,
    done TINYINT(1) NOT NULL DEFAULT 0,
    INDEX(company_id,request_id)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
");
if(!$pdo->query("SHOW COLUMNS FROM sp_part_request_items LIKE 'type'")->fetch()){
  $pdo->exec("ALTER TABLE sp_part_request_items ADD COLUMN type VARCHAR(60) DEFAULT NULL AFTER part_details");
}

/* AJAX: machine lookup -> customer/sd/location (company-scoped) */
if(isset($_GET['lookup'])){ header('Content-Type: application/json');
  $mno=trim($_GET['lookup']); $out=['found'=>false,'customer_name'=>'','sd_no'=>'','location'=>'','machine_model'=>'','serial_no'=>''];
  if($mno!==''){ $st=$pdo->prepare("SELECT m.sd_no,m.location_text,m.machine_model,m.serial_no,c.customer_name FROM sp_machines m LEFT JOIN sp_customers c ON c.company_id=m.company_id AND c.sd_no=m.sd_no WHERE m.company_id=? AND m.unique_machine_no=? LIMIT 1"); $st->execute([$companyId,$mno]);
    if($r=$st->fetch(PDO::FETCH_ASSOC)){ $out=['found'=>true,'customer_name'=>(string)($r['customer_name']??''),'sd_no'=>(string)($r['sd_no']??''),'location'=>(string)($r['location_text']??''),'machine_model'=>(string)($r['machine_model']??''),'serial_no'=>(string)($r['serial_no']??'')]; } }
  echo json_encode($out); exit; }

/* AJAX: order-code suggestions from stock items (company-scoped) */
if(isset($_GET['suggest'])){ header('Content-Type: application/json');
  $q=trim($_GET['suggest']); $out=[];
  $hex=function($c){ $c=strtolower(trim((string)$c)); return ['cyan'=>'#06b6d4','magenta'=>'#db2777','yellow'=>'#eab308','black'=>'#111827','other'=>'#64748b'][$c] ?? '#cbd5e1'; };
  if($q!==''){ $like='%'.$q.'%';
    $st=$pdo->prepare("SELECT i.order_code, i.short_code, i.description, i.machine_type, i.color,
                              COALESCE(SUM(CASE WHEN m.direction='In' THEN m.qty ELSE -m.qty END),0) AS on_hand
                       FROM sp_stock_items i
                       LEFT JOIN sp_stock_movements m ON m.item_id=i.id AND m.company_id=i.company_id
                       WHERE i.company_id=? AND (i.order_code LIKE ? OR i.short_code LIKE ? OR i.description LIKE ? OR i.machine_type LIKE ?)
                       GROUP BY i.id
                       ORDER BY i.machine_type ASC, i.order_code ASC LIMIT 200");
    $st->execute([$companyId,$like,$like,$like,$like]);
    foreach($st->fetchAll(PDO::FETCH_ASSOC) as $it){
      $color=(string)($it['color']??'');
      if($color===''){ $t=strtoupper(($it['order_code']??'').' '.($it['short_code']??'').' '.($it['description']??''));
        foreach(['CYAN'=>'Cyan','MAGENTA'=>'Magenta','YELLOW'=>'Yellow','BLACK'=>'Black'] as $k=>$v){ if(strpos($t,$k)!==false){ $color=$v; break; } } }
      $out[]=['order_code'=>(string)($it['order_code']??''),'description'=>(string)($it['description']??''),
              'type'=>(string)($it['machine_type']??''),'color'=>$color,'color_hex'=>$hex($color),'on_hand'=>(int)$it['on_hand']];
    }
  }
  echo json_encode($out); exit; }

/* Handle create */
if(isset($_POST['submit_request'])){
  $reqNo='PR-'.date('YmdHis');
  $ins=$pdo->prepare("INSERT INTO sp_part_requests
    (company_id, req_no, req_date, machine_no, machine_model, serial_no, sd_no, customer_name, location, issued_by_user_id, issued_by_code, issued_by_name, ack_manager, note, status)
    VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?, 'open')");
  $ins->execute([
    $companyId, $reqNo,
    ($_POST['req_date'] ?? '') ?: null,
    trim($_POST['machine_no'] ?? ''),
    trim($_POST['machine_model'] ?? ''),
    trim($_POST['serial_no'] ?? ''),
    trim($_POST['sd_no'] ?? ''),
    trim($_POST['customer_name'] ?? ''),
    trim($_POST['location'] ?? ''),
    (int)($_POST['issued_by_user_id'] ?? $userId),
    trim($_POST['issued_by_code'] ?? ''),
    trim($_POST['issued_by_name'] ?? ''),
    trim($_POST['ack_manager'] ?? ''),
    trim($_POST['note'] ?? ''),
  ]);
  $newId=(int)$pdo->lastInsertId();

  $orders  = $_POST['item_order']   ?? [];
  $details = $_POST['item_details'] ?? [];
  $types   = $_POST['item_type']    ?? [];
  $colors  = $_POST['item_color']   ?? [];
  $qtys    = $_POST['item_qty']     ?? [];
  $barcodes= $_POST['item_barcode'] ?? [];
  $notes   = $_POST['item_note']    ?? [];
  $itemIns=$pdo->prepare("INSERT INTO sp_part_request_items
    (company_id, request_id, order_code, part_details, type, color, qty, barcode, note)
    VALUES (?,?,?,?,?,?,?,?,?)");
  $n=is_array($orders)?count($orders):0;
  for($i=0;$i<$n;$i++){
    $oc=trim((string)($orders[$i]  ?? ''));
    $pd=trim((string)($details[$i] ?? ''));
    $ty=trim((string)($types[$i]   ?? ''));
    $cl=trim((string)($colors[$i]  ?? ''));
    $qt=(int)str_replace(',','',(string)($qtys[$i] ?? '0'));
    $bc=trim((string)($barcodes[$i]?? ''));
    $nt=trim((string)($notes[$i]   ?? ''));
    if($oc!=='' || $pd!=='' || $bc!==''){
      $itemIns->execute([$companyId,$newId,$oc,$pd,$ty,$cl,$qt,$bc,$nt]);
    }
  }
  header('Location: sp_part_request_view.php?id='.$newId); exit;
}

$today=date('Y-m-d');
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>New Request Form</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Lao:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
        :root {
            --bg:#f3f6fb; --card:#fff; --ink:#111827; --muted:#64748b; --line:#e6eaf2;
            --brand:#2563eb; --brand2:#1d4ed8;
            --shadow:0 12px 30px rgba(30,41,59,.08); --shadow-sm:0 2px 6px rgba(30,41,59,.06);
        }
        * { box-sizing:border-box; }
        body { margin:0; font-family:'Noto Sans Lao','Inter',Arial,sans-serif; background:var(--bg); color:var(--ink); }
        .wrap { max-width:1180px; margin:0 auto; padding:10px 16px 24px; }
        .page-head { display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; margin-bottom:10px; }
        .page-head h1 { margin:0; font-size:22px; font-weight:800; }
        .card { background:var(--card); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow); padding:16px 18px; margin-bottom:14px; }
        .section-title { font-size:13px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); margin:6px 0 12px; }
        .btn { background:var(--brand); color:#fff; border:none; padding:10px 16px; border-radius:10px; cursor:pointer; font-weight:700; text-decoration:none; display:inline-flex; align-items:center; gap:6px; font-size:14px; font-family:inherit; }
        .btn:hover { background:var(--brand2); }
        .btn-add { background:#059669; } .btn-add:hover { background:#047857; }
        .btn-clear { background:#eef2f7; color:#475569; } .btn-clear:hover { background:#e2e8f0; }
        .btn-x { background:#fef2f2; color:#dc2626; border:1px solid #fecaca; }
        .btn-x:hover { background:#fee2e2; }
        .field { margin-bottom:12px; }
        .field label { display:block; font-size:12px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin-bottom:5px; }
        .field input, .field textarea { width:100%; padding:10px 12px; border:1px solid #e2e8f0; border-radius:10px; font-size:14px; font-family:inherit; background:#fff; }
        .field input[readonly] { background:#f1f5f9; color:#334155; }
        .grid4 { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; }
        .grid2 { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
        .hint { color:var(--muted); font-size:12px; margin-top:4px; }
        .table-scroll { overflow-x:auto; border-radius:12px; }
        table.items { width:100%; border-collapse:collapse; min-width:900px; }
        table.items thead th { background:#f8fafc; color:var(--muted); text-transform:uppercase; font-size:11px; letter-spacing:.04em; font-weight:700; padding:9px 8px; text-align:left; border-bottom:1px solid var(--line); white-space:nowrap; }
        table.items tbody td { padding:6px; border-bottom:1px solid var(--line); vertical-align:top; }
        table.items input { width:100%; padding:8px 9px; border:1px solid #e2e8f0; border-radius:8px; font-size:13px; font-family:inherit; background:#fff; }
        .issued-box { background:#eff6ff; border:1px solid #bfdbfe; color:#1d4ed8; padding:10px 14px; border-radius:12px; font-weight:700; font-size:14px; }
        .ac-wrap { position:relative; }
        .ac-list { position:absolute; top:calc(100% + 2px); left:0; z-index:60; width:320px; background:#fff; border:1px solid #e2e8f0; border-radius:10px; box-shadow:0 12px 30px rgba(30,41,59,.16); max-height:300px; overflow-y:auto; display:none; }
        .ac-list.show { display:block; }
        .ac-grp { font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#334155; background:#f8fafc; padding:5px 10px; border-bottom:1px solid #e6eaf2; position:sticky; top:0; }
        .ac-item { display:flex; align-items:center; gap:6px; padding:7px 10px; cursor:pointer; border-bottom:1px solid #f1f5f9; }
        .ac-item:hover { background:#eff6ff; }
        .ac-dot { width:13px; height:13px; border-radius:4px; flex:0 0 auto; border:1px solid rgba(0,0,0,.15); }
        .ac-cn { font-size:11px; font-weight:700; color:#64748b; }
        .ac-oc { font-weight:800; font-size:13px; color:#0f172a; }
        /* Stock-style grouped grid for the header search */
        .ac-grid { position:absolute; top:calc(100% + 4px); left:0; z-index:60; width:min(780px,92vw); background:#fff; border:1px solid #e2e8f0; border-radius:12px; box-shadow:0 12px 30px rgba(30,41,59,.16); max-height:60vh; overflow-y:auto; display:none; padding:12px; gap:16px; flex-wrap:wrap; align-items:flex-start; }
        .ac-grid.show { display:flex; }
        .ac-col { display:flex; flex-direction:column; gap:3px; min-width:190px; }
        .ac-col-head { font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:#334155; border-bottom:2px solid #e2e8f0; padding:0 4px 5px; margin-bottom:3px; }
        .ac-row { display:flex; align-items:center; gap:6px; padding:6px 8px; border-radius:8px; cursor:pointer; }
        .ac-row:hover { background:#eff6ff; }
        .ac-code { font-weight:800; font-size:14px; color:#0f172a; }
        .ac-qty { margin-left:auto; min-width:26px; text-align:center; font-weight:800; font-size:13px; color:#166534; background:#dcfce7; border-radius:999px; padding:2px 8px; }
        .ac-qty-out { color:#b91c1c; background:#fee2e2; }
        input[type=number]::-webkit-outer-spin-button, input[type=number]::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
        input[type=number] { -moz-appearance:textfield; }
        @media (max-width:900px){ .grid4 { grid-template-columns:1fr 1fr; } .grid2 { grid-template-columns:1fr; } }
    </style>
</head>
<body>
    <div class="wrap">
        <?php $spActive='create'; include 'sp_nav.php'; ?>

        <div class="page-head">
            <h1>New Request Form</h1>
            <a href="sp_part_requests.php" class="btn btn-clear">&larr; Back to list</a>
        </div>

        <form method="POST" autocomplete="off" onsubmit="return validateItems();">
            <div class="card">
                <div class="section-title">Request details</div>
                <div class="grid4">
                    <div class="field">
                        <label>Date</label>
                        <input type="date" name="req_date" value="<?= esc($today) ?>">
                    </div>
                    <div class="field">
                        <label>Machine No</label>
                        <input type="text" id="machine_no" name="machine_no" placeholder="Type machine no..." onchange="machineLookup(this)">
                    </div>
                    <div class="field">
                        <label>Company Name</label>
                        <input type="text" id="customer_name" name="customer_name" readonly>
                    </div>
                    <div class="field">
                        <label>SD No</label>
                        <input type="text" id="sd_no" name="sd_no" readonly>
                    </div>
                    <div class="field">
                        <label>Machine Model</label>
                        <input type="text" id="machine_model" name="machine_model" readonly>
                    </div>
                    <div class="field">
                        <label>Serial No</label>
                        <input type="text" id="serial_no" name="serial_no" readonly>
                    </div>
                    <div class="field" style="grid-column:span 2;">
                        <label>Location</label>
                        <input type="text" id="location" name="location" readonly>
                    </div>
                </div>
            </div>

            <div class="card">
                <div style="display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-bottom:10px;">
                    <div class="section-title" style="margin:0;">Requested items</div>
                    <div class="ac-wrap" style="position:relative; min-width:240px;">
                        <input type="text" id="item-search" placeholder="🔍 Search stock to add..." oninput="searchAdd(this)" autocomplete="off" style="width:320px; max-width:78vw;">
                        <div class="ac-grid" id="item-search-list"></div>
                    </div>
                </div>
                <div class="table-scroll">
                    <table class="items">
                        <thead>
                            <tr>
                                <th style="width:180px;">Order Code</th>
                                <th>Part Details</th>
                                <th style="width:110px;">Type</th>
                                <th style="width:110px;">Color</th>
                                <th style="width:80px;">Qty</th>
                                <th style="width:160px;">Barcode</th>
                                <th style="width:160px;">Note</th>
                                <th style="width:44px;"></th>
                            </tr>
                        </thead>
                        <tbody id="items-body">
                            <!-- rows injected by JS; template below -->
                        </tbody>
                    </table>
                </div>
                <div class="hint">Add one line per toner colour, each with its own barcode.</div>
                <div style="margin-top:12px;">
                    <button type="button" class="btn btn-add" onclick="addRow()">+ Add line</button>
                </div>
            </div>

            <div class="card">
                <div class="section-title">Sign-off</div>
                <div class="grid2">
                    <div class="field">
                        <label>Issued by</label>
                        <div class="issued-box"><?= esc($myCode) ?><?= $myCode!=='' ? ' — ' : '' ?><?= esc($userName) ?></div>
                        <input type="hidden" name="issued_by_code" value="<?= esc($myCode) ?>">
                        <input type="hidden" name="issued_by_name" value="<?= esc($userName) ?>">
                        <input type="hidden" name="issued_by_user_id" value="<?= (int)$userId ?>">
                    </div>
                    <div class="field">
                        <label>Acknowledged by Department Manager (optional)</label>
                        <input type="text" name="ack_manager" placeholder="Manager name">
                    </div>
                    <div class="field" style="grid-column:span 2;">
                        <label>Note</label>
                        <textarea name="note" rows="2" placeholder="Any additional note..."></textarea>
                    </div>
                </div>
                <div style="margin-top:8px; display:flex; gap:10px; flex-wrap:wrap;">
                    <button type="submit" name="submit_request" class="btn">Submit request</button>
                    <a href="sp_part_requests.php" class="btn btn-clear">Cancel</a>
                </div>
            </div>
        </form>
    </div>

    <template id="row-tpl">
        <tr>
            <td>
                <div class="ac-wrap">
                    <input type="text" name="item_order[]" class="oc-input" placeholder="Order code" oninput="ocSuggest(this)" autocomplete="off">
                    <div class="ac-list"></div>
                </div>
            </td>
            <td><input type="text" name="item_details[]" placeholder="Part details"></td>
            <td><input type="text" name="item_type[]" placeholder="Type" onchange="drumCheck(this)"></td>
            <td><input type="text" name="item_color[]" placeholder="Color"></td>
            <td><input type="number" name="item_qty[]" value="1" placeholder="1" min="1"></td>
            <td><input type="text" name="item_barcode[]" placeholder="Barcode"></td>
            <td><input type="text" name="item_note[]" placeholder="Note"></td>
            <td style="text-align:center;"><button type="button" class="btn btn-x" style="padding:6px 10px;" onclick="removeRow(this)">&times;</button></td>
        </tr>
    </template>

    <!-- DRUM roller picker (multi-select) -->
    <div id="drum-modal" style="display:none; position:fixed; inset:0; background:rgba(15,23,42,.45); z-index:9999; align-items:center; justify-content:center;">
        <div style="background:#fff; border-radius:16px; padding:22px 24px; width:320px; max-width:90vw; box-shadow:0 20px 50px rgba(0,0,0,.25); text-align:center;">
            <div style="font-size:17px; font-weight:800; color:#0f172a; margin-bottom:4px;">DRUM — pick roller(s)</div>
            <div style="font-size:13px; color:#64748b; margin-bottom:16px;">Tick all that apply. Qty becomes the number you select.</div>
            <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px;">
                <label class="drum-opt"><input type="checkbox" class="drum-cb" value="R1"> R1</label>
                <label class="drum-opt"><input type="checkbox" class="drum-cb" value="R2"> R2</label>
                <label class="drum-opt"><input type="checkbox" class="drum-cb" value="R3"> R3</label>
                <label class="drum-opt"><input type="checkbox" class="drum-cb" value="R4"> R4</label>
            </div>
            <div id="drum-count" style="font-size:13px; font-weight:700; color:#2563eb; margin-top:14px;">0 selected</div>
            <button type="button" onclick="applyDrum()" style="margin-top:12px; background:#059669; color:#fff; border:none; padding:12px 18px; border-radius:11px; font-weight:800; cursor:pointer; width:100%;">✅ Done</button>
        </div>
    </div>
    <style>
        .drum-opt { display:flex; align-items:center; justify-content:center; gap:9px; background:#eff6ff; color:#1d4ed8; border:1.5px solid #bfdbfe; padding:14px 0; border-radius:12px; font-size:16px; font-weight:800; cursor:pointer; user-select:none; }
        .drum-opt.on { background:#2563eb; color:#fff; border-color:#2563eb; }
        .drum-opt input { width:18px; height:18px; }
    </style>

    <script>
        // DRUM roller picker — when Type contains DRUM, tick R1..R4.
        // The picks go into the line's Note (e.g. "R1, R2, R3") and Qty = number picked.
        var drumRow=null;
        function drumCheck(el){
            var v=(el.value||'').trim().toUpperCase();
            if(v.indexOf('DRUM')===-1) return;
            drumRow = el.closest('tr');
            // pre-tick from whatever is already in the Note
            var note = drumRow ? drumRow.querySelector('input[name="item_note[]"]') : null;
            var existing = note ? (note.value||'').toUpperCase() : '';
            document.querySelectorAll('.drum-cb').forEach(function(cb){
                cb.checked = existing.split(/[\s,]+/).indexOf(cb.value)!==-1;
                cb.parentElement.classList.toggle('on', cb.checked);
            });
            updateDrumCount();
            document.getElementById('drum-modal').style.display='flex';
        }
        function updateDrumCount(){
            var n=document.querySelectorAll('.drum-cb:checked').length;
            var el=document.getElementById('drum-count');
            if(el) el.textContent = n+' selected';
        }
        function applyDrum(){
            var picks=[];
            document.querySelectorAll('.drum-cb:checked').forEach(function(cb){ picks.push(cb.value); });
            if(drumRow && picks.length>0){
                var note = drumRow.querySelector('input[name="item_note[]"]');
                var qty  = drumRow.querySelector('input[name="item_qty[]"]');
                if(note) note.value = picks.join(', ');
                if(qty)  qty.value  = picks.length;
            }
            closeDrum();
        }
        function closeDrum(){ document.getElementById('drum-modal').style.display='none'; drumRow=null; }
        // highlight ticked options + live count
        document.addEventListener('change', function(ev){
            if(ev.target && ev.target.classList && ev.target.classList.contains('drum-cb')){
                ev.target.parentElement.classList.toggle('on', ev.target.checked);
                updateDrumCount();
            }
        });

        // Highlight a field red + clear on input
        function markBad(el){
            if(!el) return;
            el.style.borderColor='#7f1d1d'; el.style.background='#fff1f2'; el.style.boxShadow='0 0 0 3px rgba(185,28,28,.30)';
            el.oninput=function(){ this.style.borderColor=''; this.style.background=''; this.style.boxShadow=''; };
        }

        // Validate on submit: Machine No + at least one Order Code required, then Qty per line
        function validateItems(){
            // 1) Machine No required
            var mno=document.getElementById('machine_no');
            if(mno && mno.value.trim()===''){
                markBad(mno);
                alert('ກະລຸນາໃສ່ ເລກເຄື່ອງ / Machine No is required');
                mno.focus();
                return false;
            }
            // 2) at least one Order Code
            var codes=document.querySelectorAll('input[name="item_order[]"]');
            var hasCode=false;
            codes.forEach(function(c){ if(c.value.trim()!=='') hasCode=true; });
            if(!hasCode){
                if(codes[0]){ markBad(codes[0]); codes[0].focus(); }
                alert('ກະລຸນາໃສ່ Order Code ຢ່າງໜ້ອຍ 1 ລາຍການ / At least one Order Code is required');
                return false;
            }
            // 3) Qty per used line
            var rows=document.querySelectorAll('#items-body tr');
            for(var i=0;i<rows.length;i++){
                var oc=rows[i].querySelector('input[name="item_order[]"]');
                var pd=rows[i].querySelector('input[name="item_details[]"]');
                var q =rows[i].querySelector('input[name="item_qty[]"]');
                var used=((oc&&oc.value.trim()!=='')||(pd&&pd.value.trim()!==''));
                if(used && q && (q.value.trim()==='' || parseInt(q.value,10)<1)){
                    q.style.borderColor='#7f1d1d';
                    q.style.background='#b91c1c';
                    q.style.color='#fff';
                    q.style.boxShadow='0 0 0 3px rgba(185,28,28,.35)';
                    q.oninput=function(){ this.style.borderColor=''; this.style.background=''; this.style.color=''; this.style.boxShadow=''; };
                    alert('ກະລຸນາໃສ່ ຈໍານວນ / Need Qty');
                    q.focus();
                    return false;
                }
            }
            return true;
        }

        // Machine lookup -> fill customer/sd/location
        function machineLookup(el){
            var v=(el.value||'').trim();
            if(!v){ return; }
            fetch('sp_part_request_form.php?lookup='+encodeURIComponent(v))
                .then(function(r){ return r.json(); })
                .then(function(d){
                    var c=document.getElementById('customer_name');
                    var s=document.getElementById('sd_no');
                    var l=document.getElementById('location');
                    var mm=document.getElementById('machine_model');
                    var sn=document.getElementById('serial_no');
                    if(d && d.found){
                        if(c) c.value=d.customer_name||'';
                        if(s) s.value=d.sd_no||'';
                        if(l) l.value=d.location||'';
                        if(mm) mm.value=d.machine_model||'';
                        if(sn) sn.value=d.serial_no||'';
                    } else {
                        if(c) c.value=''; if(s) s.value=''; if(l) l.value='';
                        if(mm) mm.value=''; if(sn) sn.value='';
                    }
                })
                .catch(function(){});
        }

        // Add / remove item rows
        function addRow(){
            var tpl=document.getElementById('row-tpl');
            var body=document.getElementById('items-body');
            var node=tpl.content.cloneNode(true);
            body.appendChild(node);
        }
        function removeRow(btn){
            var body=document.getElementById('items-body');
            var tr=btn.closest('tr');
            if(tr){ tr.parentNode.removeChild(tr); }
            if(!body.querySelector('tr')){ addRow(); }
        }

        // Order-code autocomplete per row
        var ocTimers=new WeakMap();
        function ocSuggest(input){
            var box=input.parentNode.querySelector('.ac-list');
            var q=(input.value||'').trim();
            clearTimeout(ocTimers.get(input));
            if(q.length<2){ box.classList.remove('show'); box.innerHTML=''; return; }
            var t=setTimeout(function(){
                fetch('sp_part_request_form.php?suggest='+encodeURIComponent(q))
                    .then(function(r){ return r.json(); })
                    .then(function(list){ renderSuggest(input, box, list||[]); })
                    .catch(function(){});
            },180);
            ocTimers.set(input,t);
        }
        function renderSuggest(input, box, list){
            if(!list.length){ box.classList.remove('show'); box.innerHTML=''; return; }
            var groups={}, order=[];
            list.forEach(function(it){ var t=(it.type&&it.type.trim())?it.type.trim():'Other'; if(!groups[t]){groups[t]=[];order.push(t);} groups[t].push(it); });
            box.innerHTML=order.map(function(type){
                var rows=groups[type].map(function(it){
                    return '<div class="ac-item" data-oc="'+escAttr(it.order_code)+'" data-desc="'+escAttr(it.description)+'" data-type="'+escAttr(it.type)+'" data-color="'+escAttr(it.color)+'">'+
                        '<span class="ac-dot" style="background:'+(it.color_hex||'#cbd5e1')+'"></span>'+
                        (it.color?'<span class="ac-cn">'+escHtml(it.color)+'</span>':'')+
                        '<span class="ac-oc">'+escHtml(it.order_code||'(no code)')+'</span></div>';
                }).join('');
                return '<div class="ac-grp">'+escHtml(type)+'</div>'+rows;
            }).join('');
            box.classList.add('show');
            var tr=input.closest('tr');
            box.querySelectorAll('.ac-item').forEach(function(el){
                el.addEventListener('mousedown', function(e){
                    e.preventDefault();
                    var oc=el.getAttribute('data-oc')||'', desc=el.getAttribute('data-desc')||'',
                        type=el.getAttribute('data-type')||'', color=el.getAttribute('data-color')||'';
                    input.value=oc;
                    var d=tr.querySelector('input[name="item_details[]"]');
                    var t=tr.querySelector('input[name="item_type[]"]');
                    var c=tr.querySelector('input[name="item_color[]"]');
                    if(d) d.value=desc;
                    if(t) t.value=type;
                    if(c) c.value=(type.toLowerCase().indexOf('toner')!==-1)?color:'';
                    box.classList.remove('show'); box.innerHTML='';
                });
            });
        }
        function escHtml(s){ return (s||'').replace(/[&<>"]/g,function(c){ return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]; }); }
        function escAttr(s){ return escHtml(s).replace(/"/g,'&quot;'); }
        document.addEventListener('click', function(e){
            document.querySelectorAll('.ac-list.show, .ac-grid.show').forEach(function(b){
                if(!b.parentNode.contains(e.target)){ b.classList.remove('show'); }
            });
        });

        // Header search -> add a filled line
        var saTimer=null;
        function searchAdd(input){
            var box=document.getElementById('item-search-list');
            var q=(input.value||'').trim();
            clearTimeout(saTimer);
            if(q.length<2){ box.classList.remove('show'); box.innerHTML=''; return; }
            saTimer=setTimeout(function(){
                fetch('sp_part_request_form.php?suggest='+encodeURIComponent(q))
                    .then(function(r){ return r.json(); })
                    .then(function(list){ renderAddSearch(input, box, list||[]); })
                    .catch(function(){});
            },180);
        }
        function renderAddSearch(input, box, list){
            if(!list.length){ box.classList.remove('show'); box.innerHTML=''; return; }
            var groups={}, order=[];
            list.forEach(function(it){ var t=(it.type&&it.type.trim())?it.type.trim():'Other'; if(!groups[t]){groups[t]=[];order.push(t);} groups[t].push(it); });
            box.innerHTML=order.map(function(type){
                var rows=groups[type].map(function(it){
                    var q=(typeof it.on_hand!=='undefined')?it.on_hand:'';
                    var qcls=(q!==''&&q<=0)?' ac-qty-out':'';
                    return '<div class="ac-row" data-oc="'+escAttr(it.order_code)+'" data-desc="'+escAttr(it.description)+'" data-type="'+escAttr(it.type)+'" data-color="'+escAttr(it.color)+'">'+
                        '<span class="ac-dot" style="background:'+(it.color_hex||'#cbd5e1')+'"></span>'+
                        (it.color?'<span class="ac-cn">'+escHtml(it.color)+'</span>':'')+
                        '<span class="ac-code">'+escHtml(it.order_code||'(no code)')+'</span>'+
                        (q!==''?'<span class="ac-qty'+qcls+'">'+q+'</span>':'')+'</div>';
                }).join('');
                return '<div class="ac-col"><div class="ac-col-head">'+escHtml(type)+'</div>'+rows+'</div>';
            }).join('');
            box.classList.add('show');
            box.querySelectorAll('.ac-row').forEach(function(el){
                el.addEventListener('mousedown', function(e){
                    e.preventDefault();
                    fillNewRow(el.getAttribute('data-oc')||'', el.getAttribute('data-desc')||'', el.getAttribute('data-type')||'', el.getAttribute('data-color')||'');
                    input.value=''; box.classList.remove('show'); box.innerHTML=''; input.focus();
                });
            });
        }
        function fillNewRow(oc, desc, type, color){
            var body=document.getElementById('items-body');
            var tr=null;
            body.querySelectorAll('tr').forEach(function(row){
                if(tr) return;
                var o=row.querySelector('input[name="item_order[]"]');
                if(o && !o.value.trim()){ tr=row; }
            });
            if(!tr){ addRow(); tr=body.lastElementChild; }
            var o=tr.querySelector('input[name="item_order[]"]');
            var d=tr.querySelector('input[name="item_details[]"]');
            var t=tr.querySelector('input[name="item_type[]"]');
            var c=tr.querySelector('input[name="item_color[]"]');
            if(o) o.value=oc;
            if(d) d.value=desc;
            if(t) t.value=type;
            if(c) c.value=(type.toLowerCase().indexOf('toner')!==-1)?color:'';
            if(t && type) drumCheck(t);
        }

        // Start with one empty row
        addRow();
    </script>
</body>
</html>