<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel">
  <span class="text-sm font-bold text-gray-700">지정판매소 판매</span>
</section>

<div class="border border-gray-300 rounded-lg p-3 mt-2 bg-white space-y-3">
  <form id="sale-save-form" action="<?= base_url('bag/sale/designated/save') ?>" method="POST">
    <?= csrf_field() ?>
    <input type="hidden" name="so_idx" id="save-so-idx" value=""/>
    <input type="hidden" name="ds_idx" id="save-ds-idx" value=""/>
    <input type="hidden" name="scans_json" id="save-scans-json" value="[]"/>

    <div class="flex flex-wrap items-end gap-2">
      <div class="relative">
        <label class="block text-xs font-bold text-gray-700 mb-1">판매소 검색</label>
        <input id="shop-search" type="text" class="border border-gray-300 rounded px-2 py-1.5 text-sm w-[36rem] max-w-full" placeholder="코드/상호/대표자/전화/주소"/>
        <datalist id="shop-search-list" class="hidden">
          <?php foreach (($shops ?? []) as $shop): ?>
            <option value="<?= esc(trim(($shop->ds_shop_no ?? '') . ' ' . ($shop->ds_name ?? '') . ' ' . ($shop->ds_rep_name ?? '') . ' ' . ($shop->ds_tel ?? '') . ' ' . ($shop->ds_addr ?? ''))) ?>"></option>
          <?php endforeach; ?>
        </datalist>
        <div id="shop-search-suggest" class="hidden absolute left-0 top-full mt-1 w-[36rem] max-w-full max-h-56 overflow-auto border border-gray-300 rounded-lg bg-white shadow-lg z-20"></div>
      </div>
      <div>
        <label class="block text-xs font-bold text-gray-700 mb-1">봉투코드 입력(스캔)</label>
        <input id="barcode-input" type="text" class="border border-gray-300 rounded px-2 py-1.5 text-sm w-80" placeholder="박스/팩/낱장 바코드"/>
      </div>
      <div>
        <label class="block text-xs font-bold text-gray-700 mb-1">판매일</label>
        <div class="border border-gray-300 bg-gray-100 rounded px-2 py-1.5 text-sm w-36"><?= esc(date('Y-m-d')) ?></div>
      </div>
      <button type="submit" class="bg-btn-search text-white px-4 py-1.5 rounded-sm text-sm shadow hover:opacity-90">판매 저장</button>
    </div>
  </form>

  <div id="scan-message" class="text-sm text-gray-600"></div>

  <div class="grid grid-cols-1 xl:grid-cols-5 gap-3">
    <section class="xl:col-span-2 border border-gray-300 rounded-lg overflow-hidden">
      <div class="px-3 py-2 border-b bg-gray-50 text-sm font-semibold text-gray-700">지정판매소 정보</div>
      <table class="w-full text-sm">
        <tr><th class="text-left px-3 py-1.5 w-28">판매소 코드</th><td id="shop-info-code" class="px-3 py-1.5">-</td></tr>
        <tr><th class="text-left px-3 py-1.5">상호</th><td id="shop-info-name" class="px-3 py-1.5">-</td></tr>
        <tr><th class="text-left px-3 py-1.5">대표자명</th><td id="shop-info-rep" class="px-3 py-1.5">-</td></tr>
        <tr><th class="text-left px-3 py-1.5">대표전화</th><td id="shop-info-tel" class="px-3 py-1.5">-</td></tr>
        <tr><th class="text-left px-3 py-1.5">주소</th><td id="shop-info-addr" class="px-3 py-1.5">-</td></tr>
      </table>
    </section>

    <section class="xl:col-span-3 border border-gray-300 rounded-lg overflow-hidden">
      <div class="px-3 py-2 border-b bg-gray-50 text-sm font-semibold text-gray-700">주문 접수 리스트</div>
      <div class="max-h-56 overflow-auto">
        <table class="w-full data-table text-sm">
          <thead>
            <tr>
              <th class="w-14 text-center">번호</th>
              <th class="text-left">판매소</th>
              <th class="w-28 text-center">접수일</th>
              <th class="w-28 text-center">배달일</th>
              <th class="w-16 text-center">상태</th>
            </tr>
          </thead>
          <tbody id="order-list-body"></tbody>
        </table>
      </div>
    </section>
  </div>

  <section id="dev-saleable-panel" class="hidden border border-amber-400 bg-amber-50/50 p-3 rounded-sm">
    <p class="text-xs text-amber-900 mb-2 leading-relaxed">
      <strong class="text-amber-950">[개발용 임시]</strong>
      <strong>주문 접수 리스트</strong>에서 주문을 선택하면, 그 주문의 지정판매소(<code class="bg-amber-100 px-1 rounded">so_ds_idx</code>) 기준으로
      판매 테스트에 쓸 수 있는 바코드 후보를 표시합니다.
      (① 해당 판매소에 연결된 <code class="bg-amber-100 px-1 rounded">bag_sale_scan_code</code> 중 <code class="bg-amber-100 px-1 rounded">in_stock</code>,
      ② 같은 판매소의 <strong>전화·정상 주문</strong> 품목 봉투코드(수령완료 포함, 주문 리스트와 동일 범위) 및 <strong>선택한 주문</strong> 품목에 맞는 <code class="bg-amber-100 px-1 rounded">bag_receiving_pack_code</code> <code class="bg-amber-100 px-1 rounded">in_stock</code> 팩 코드.
      입고 행의 <strong>수량</strong>은 팩에 담긴 <code class="bg-amber-100 px-1 rounded">brpc_sheet_qty</code>(낱장 수)입니다.)
      <strong>개발 완료 후 이 블록과 API 라우트를 제거</strong>해 주세요.
    </p>
    <div class="max-h-52 overflow-auto border border-amber-300 bg-white">
      <table class="w-full data-table text-xs">
        <thead>
          <tr>
            <th class="w-28 text-left">출처</th>
            <th class="w-40 text-center">바코드(대표)</th>
            <th class="text-left">봉투 종류</th>
            <th class="w-16 text-center">포장</th>
            <th class="w-10 text-right">수량</th>
            <th class="w-12 text-center">주문</th>
            <th class="w-14 text-center">상태</th>
            <th class="text-left">비고(낱장범위 등)</th>
          </tr>
        </thead>
        <tbody id="dev-saleable-tbody">
          <tr><td colspan="8" class="text-center text-gray-400 py-4">주문을 선택하면 목록이 표시됩니다.</td></tr>
        </tbody>
      </table>
    </div>
  </section>

  <div class="grid grid-cols-1 xl:grid-cols-2 gap-3">
    <section class="border border-gray-300 rounded-lg overflow-hidden">
      <div class="px-3 py-2 border-b bg-gray-50 text-sm font-semibold text-gray-700">판매 내역</div>
      <div class="max-h-72 overflow-auto">
        <table class="w-full data-table text-sm">
          <thead>
            <tr>
              <th class="w-14 text-center">선택</th>
              <th class="text-left">봉투 종류</th>
              <th class="w-20 text-right">접수량</th>
              <th class="w-20 text-right">판매량</th>
              <th class="w-20 text-right">단가</th>
              <th class="w-24 text-right">판매금액</th>
            </tr>
          </thead>
          <tbody id="sale-items-body">
            <tr><td colspan="6" class="text-center text-gray-400 py-6">주문을 선택해 주세요.</td></tr>
          </tbody>
        </table>
      </div>
    </section>

    <section class="border border-gray-300 rounded-lg overflow-hidden">
      <div class="px-3 py-2 border-b bg-gray-50 text-sm font-semibold text-gray-700">판매 상세 내역</div>
      <div class="max-h-72 overflow-auto">
        <table class="w-full data-table text-sm">
          <thead>
            <tr>
              <th class="text-left">봉투 종류</th>
              <th class="w-28 text-center">봉투 코드</th>
              <th class="w-16 text-right">수량</th>
              <th class="w-16 text-center">포장단위</th>
            </tr>
          </thead>
          <tbody id="scan-detail-body">
            <tr><td colspan="4" class="text-center text-gray-400 py-6">바코드를 스캔해 주세요.</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </div>
</div>

<script>
(() => {
  const shops = <?= json_encode(array_map(static function ($s): array {
      return [
          'ds_idx' => (int) ($s->ds_idx ?? 0),
          'ds_shop_no' => (string) ($s->ds_shop_no ?? ''),
          'ds_name' => (string) ($s->ds_name ?? ''),
          'ds_rep_name' => (string) ($s->ds_rep_name ?? ''),
          'ds_tel' => (string) ($s->ds_tel ?? ''),
          'ds_addr' => trim((string) ($s->ds_addr ?? '') . ' ' . (string) ($s->ds_addr_detail ?? '')),
      ];
  }, $shops ?? []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
  const orders = <?= json_encode($orders ?? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
  const scanApi = '<?= base_url('bag/sale/designated/scan') ?>';
  const devSaleableApi = '<?= base_url('bag/sale/designated/dev-saleable-barcodes') ?>';
  const csrfName = '<?= csrf_token() ?>';
  const csrfHash = '<?= csrf_hash() ?>';

  const shopSearch = document.getElementById('shop-search');
  const shopSuggest = document.getElementById('shop-search-suggest');
  const barcodeInput = document.getElementById('barcode-input');
  const orderListBody = document.getElementById('order-list-body');
  const saleItemsBody = document.getElementById('sale-items-body');
  const scanDetailBody = document.getElementById('scan-detail-body');
  const saveForm = document.getElementById('sale-save-form');
  const saveSoIdx = document.getElementById('save-so-idx');
  const saveDsIdx = document.getElementById('save-ds-idx');
  const saveScansJson = document.getElementById('save-scans-json');
  const scanMessage = document.getElementById('scan-message');
  const devSaleablePanel = document.getElementById('dev-saleable-panel');
  const devSaleableTbody = document.getElementById('dev-saleable-tbody');

  const nf = (n) => new Intl.NumberFormat('ko-KR').format(n || 0);
  let selectedShop = null;
  let selectedOrder = null;
  let selectedBagCode = '';
  const pendingScans = [];

  const shopMap = new Map(shops.map((s) => [String(s.ds_idx), s]));

  function setMessage(msg, isError = false) {
    scanMessage.textContent = msg || '';
    scanMessage.className = isError ? 'text-sm text-red-600' : 'text-sm text-emerald-700';
  }

  function mergedShopText(shop) {
    return [shop.ds_shop_no, shop.ds_name, shop.ds_rep_name, shop.ds_tel, shop.ds_addr]
      .filter(Boolean)
      .join(' ');
  }

  function hideSuggest() {
    if (shopSuggest) {
      shopSuggest.classList.add('hidden');
      shopSuggest.innerHTML = '';
    }
  }

  function renderSuggest(query) {
    if (!shopSuggest) return;
    const q = String(query || '').trim().toLowerCase();
    const matched = (q
      ? shops.filter((s) => mergedShopText(s).toLowerCase().includes(q))
      : shops
    ).slice(0, 30);
    if (matched.length === 0) {
      hideSuggest();
      return;
    }
    shopSuggest.innerHTML = matched.map((s) => `
      <button type="button" class="shop-suggest-item w-full text-left px-2 py-1.5 hover:bg-blue-50 text-xs border-b border-gray-100 whitespace-normal break-all" data-ds-idx="${s.ds_idx}">
        ${mergedShopText(s)}
      </button>
    `).join('');
    shopSuggest.classList.remove('hidden');
  }

  function hideDevSaleablePanel() {
    if (devSaleablePanel) devSaleablePanel.classList.add('hidden');
    if (devSaleableTbody) {
      devSaleableTbody.innerHTML = '<tr><td colspan="8" class="text-center text-gray-400 py-4">주문을 선택하면 목록이 표시됩니다.</td></tr>';
    }
  }

  async function loadDevSaleableBarcodes(dsIdx) {
    if (!devSaleablePanel || !devSaleableTbody) return;
    const idx = Number(dsIdx || 0);
    if (!idx) {
      hideDevSaleablePanel();
      return;
    }
    devSaleablePanel.classList.remove('hidden');
    devSaleableTbody.innerHTML = '<tr><td colspan="8" class="text-center text-gray-400 py-4">불러오는 중…</td></tr>';
    try {
      let devUrl = `${devSaleableApi}?ds_idx=${encodeURIComponent(String(idx))}`;
      if (selectedOrder && Number(selectedOrder.so_idx || 0) > 0) {
        devUrl += `&so_idx=${encodeURIComponent(String(selectedOrder.so_idx))}`;
      }
      const res = await fetch(devUrl, { credentials: 'same-origin' });
      const data = await res.json();
      if (!data.ok) {
        devSaleableTbody.innerHTML = `<tr><td colspan="8" class="text-center text-red-600 py-4">${data.message || '조회 실패'}</td></tr>`;
        return;
      }
      const rows = Array.isArray(data.rows) ? data.rows : [];
      if (rows.length === 0) {
        devSaleableTbody.innerHTML = '<tr><td colspan="8" class="text-center text-gray-400 py-4">표시할 바코드가 없습니다.</td></tr>';
        return;
      }
      devSaleableTbody.innerHTML = rows.map((r) => `
        <tr>
          <td class="text-left pl-1">${r.source || ''}</td>
          <td class="text-center font-mono">${r.code || ''}</td>
          <td class="text-left pl-1">${r.bag_code || ''} ${r.bag_name || ''}</td>
          <td class="text-center">${r.unit || ''}</td>
          <td class="text-right pr-1">${nf(r.qty || 0)}</td>
          <td class="text-center">${r.so_idx ? String(r.so_idx) : '-'}</td>
          <td class="text-center">${r.state || ''}</td>
          <td class="text-left pl-1">${r.extra || ''}</td>
        </tr>
      `).join('');
    } catch {
      devSaleableTbody.innerHTML = '<tr><td colspan="8" class="text-center text-red-600 py-4">네트워크 오류</td></tr>';
    }
  }

  function updateShopInfo(shop) {
    document.getElementById('shop-info-code').textContent = shop?.ds_shop_no || '-';
    document.getElementById('shop-info-name').textContent = shop?.ds_name || '-';
    document.getElementById('shop-info-rep').textContent = shop?.ds_rep_name || '-';
    document.getElementById('shop-info-tel').textContent = shop?.ds_tel || '-';
    document.getElementById('shop-info-addr').textContent = shop?.ds_addr || '-';
  }

  function renderOrderList() {
    const rows = (selectedShop ? orders.filter((o) => Number(o.so_ds_idx) === Number(selectedShop.ds_idx)) : orders);
    if (rows.length === 0) {
      orderListBody.innerHTML = '<tr><td colspan="5" class="text-center py-6 text-gray-400">조건에 맞는 주문이 없습니다.</td></tr>';
      return;
    }
    orderListBody.innerHTML = rows.map((o) => `
      <tr class="order-row cursor-pointer hover:bg-blue-50 ${selectedOrder && Number(selectedOrder.so_idx) === Number(o.so_idx) ? 'bg-blue-100' : ''}" data-order-id="${o.so_idx}">
        <td class="text-center">${o.so_idx}</td>
        <td class="text-left pl-2">${o.so_ds_name || ''}</td>
        <td class="text-center">${o.so_order_date || ''}</td>
        <td class="text-center">${o.so_delivery_date || ''}</td>
        <td class="text-center">${o.so_status === 'cancelled' ? '주문 취소' : (Number(o.so_received || 0) === 1 ? '판매 완료' : '판매 진행')}</td>
      </tr>
    `).join('');
  }

  function pendingQtyForBag(code) {
    return pendingScans.filter((s) => s.bag_code === code).reduce((sum, s) => sum + (Number(s.qty) || 0), 0);
  }

  function renderSaleItems() {
    if (!selectedOrder) {
      saleItemsBody.innerHTML = '<tr><td colspan="6" class="text-center text-gray-400 py-6">주문을 선택해 주세요.</td></tr>';
      return;
    }
    const items = Array.isArray(selectedOrder.items) ? selectedOrder.items : [];
    if (items.length === 0) {
      saleItemsBody.innerHTML = '<tr><td colspan="6" class="text-center text-gray-400 py-6">품목 정보가 없습니다.</td></tr>';
      return;
    }
    saleItemsBody.innerHTML = items.map((it) => {
      const bagCode = String(it.soi_bag_code || '');
      const sold = Number(it.sold_qty || 0) + pendingQtyForBag(bagCode);
      const unitPrice = Number(it.soi_unit_price || 0);
      const amount = sold * unitPrice;
      const checked = selectedBagCode === bagCode ? 'checked' : '';
      return `
        <tr>
          <td class="text-center"><input type="radio" name="pick-bag" value="${bagCode}" ${checked}></td>
          <td class="text-left pl-2">${bagCode} ${it.soi_bag_name || ''}</td>
          <td class="text-right pr-2">${nf(it.soi_qty || 0)}</td>
          <td class="text-right pr-2">${nf(sold)}</td>
          <td class="text-right pr-2">${nf(unitPrice)}</td>
          <td class="text-right pr-2">${nf(amount)}</td>
        </tr>
      `;
    }).join('');
  }

  function renderScanDetails() {
    const rows = pendingScans.filter((s) => !selectedBagCode || s.bag_code === selectedBagCode);
    if (rows.length === 0) {
      scanDetailBody.innerHTML = '<tr><td colspan="4" class="text-center text-gray-400 py-6">바코드를 스캔해 주세요.</td></tr>';
      return;
    }
    scanDetailBody.innerHTML = rows.map((r) => `
      <tr>
        <td class="text-left pl-2">${r.bag_code} ${r.bag_name || ''}</td>
        <td class="text-center">${r.barcode}</td>
        <td class="text-right pr-2">${nf(r.qty)}</td>
        <td class="text-center">${r.unit}</td>
      </tr>
    `).join('');
  }

  function selectOrder(orderId) {
    selectedOrder = orders.find((o) => Number(o.so_idx) === Number(orderId)) || null;
    selectedBagCode = '';
    pendingScans.length = 0;
    saveSoIdx.value = selectedOrder ? String(selectedOrder.so_idx) : '';
    saveDsIdx.value = selectedOrder ? String(selectedOrder.so_ds_idx || '') : (selectedShop ? String(selectedShop.ds_idx) : '');
    saveScansJson.value = '[]';

    // 주문이 선택되면 그 주문의 지정판매소를 「지정판매소 정보」 표·검색 input 에도 자동 반영한다.
    if (selectedOrder) {
      const matchedShop = shopMap.get(String(selectedOrder.so_ds_idx)) || null;
      if (matchedShop) {
        selectedShop = matchedShop;
        if (shopSearch) shopSearch.value = mergedShopText(matchedShop);
        updateShopInfo(matchedShop);
      }
    }

    renderOrderList();
    renderSaleItems();
    renderScanDetails();
    if (selectedOrder && Number(selectedOrder.so_ds_idx || 0) > 0) {
      loadDevSaleableBarcodes(selectedOrder.so_ds_idx);
    } else {
      hideDevSaleablePanel();
    }
  }

  async function submitScan() {
    const code = (barcodeInput.value || '').trim();
    if (!code) return;
    if (!selectedOrder) {
      setMessage('주문 접수 리스트에서 주문을 먼저 선택해 주세요.', true);
      return;
    }

    const payload = new URLSearchParams();
    payload.set(csrfName, csrfHash);
    payload.set('so_idx', String(selectedOrder.so_idx));
    payload.set('barcode', code);

    const pendingByBag = {};
    pendingScans.forEach((s) => {
      const k = String(s.bag_code || '');
      pendingByBag[k] = (pendingByBag[k] || 0) + (Number(s.qty || 0));
    });
    payload.set('pending_by_bag', JSON.stringify(pendingByBag));

    const res = await fetch(scanApi, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
      body: payload.toString(),
    });
    const data = await res.json();
    if (!data.ok) {
      setMessage(data.message || '스캔 처리 실패', true);
      return;
    }

    if (!selectedBagCode) {
      selectedBagCode = String(data.bag_code || '');
    }
    pendingScans.push({
      barcode: code,
      bag_code: data.bag_code,
      bag_name: data.bag_name,
      qty: Number(data.qty || 0),
      unit: data.unit,
      pack_ids: Array.isArray(data.pack_ids) ? data.pack_ids : [],
    });
    saveScansJson.value = JSON.stringify(pendingScans);
    barcodeInput.value = '';
    setMessage(`등록 완료: ${data.bag_code} / ${data.unit} / 수량 ${nf(data.qty)}`);
    renderSaleItems();
    renderScanDetails();
  }

  shopSearch?.addEventListener('change', (e) => {
    const q = String(e.target.value || '').trim().toLowerCase();
    selectedShop = shops.find((s) => {
      const merged = [s.ds_shop_no, s.ds_name, s.ds_rep_name, s.ds_tel, s.ds_addr].join(' ').toLowerCase();
      return merged.includes(q);
    }) || null;
    selectedOrder = null;
    selectedBagCode = '';
    pendingScans.length = 0;
    saveSoIdx.value = '';
    saveDsIdx.value = selectedShop ? String(selectedShop.ds_idx) : '';
    saveScansJson.value = '[]';
    updateShopInfo(selectedShop);
    hideDevSaleablePanel();
    renderOrderList();
    renderSaleItems();
    renderScanDetails();
    setMessage('');
    hideSuggest();
  });

  shopSearch?.addEventListener('input', (e) => {
    renderSuggest(e.target.value || '');
  });

  shopSearch?.addEventListener('focus', (e) => {
    renderSuggest(e.target.value || '');
  });

  shopSearch?.addEventListener('click', (e) => {
    renderSuggest(e.target.value || '');
  });

  shopSuggest?.addEventListener('click', (e) => {
    const btn = e.target.closest('.shop-suggest-item');
    if (!btn) return;
    const dsIdx = Number(btn.dataset.dsIdx || 0);
    const shop = shops.find((s) => Number(s.ds_idx) === dsIdx) || null;
    if (!shop) return;
    shopSearch.value = mergedShopText(shop);
    selectedShop = shop;
    selectedOrder = null;
    selectedBagCode = '';
    pendingScans.length = 0;
    saveSoIdx.value = '';
    saveDsIdx.value = selectedShop ? String(selectedShop.ds_idx) : '';
    saveScansJson.value = '[]';
    updateShopInfo(selectedShop);
    hideDevSaleablePanel();
    renderOrderList();
    renderSaleItems();
    renderScanDetails();
    setMessage('');
    hideSuggest();
  });

  document.addEventListener('click', (e) => {
    if (!shopSuggest || !shopSearch) return;
    if (e.target === shopSearch || shopSuggest.contains(e.target)) return;
    hideSuggest();
  });

  barcodeInput?.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      submitScan();
    }
  });

  orderListBody?.addEventListener('click', (e) => {
    const tr = e.target.closest('.order-row');
    if (!tr) return;
    selectOrder(tr.dataset.orderId);
  });

  saleItemsBody?.addEventListener('change', (e) => {
    const radio = e.target.closest('input[name="pick-bag"]');
    if (!radio) return;
    selectedBagCode = radio.value || '';
    renderScanDetails();
  });

  saveForm?.addEventListener('submit', (e) => {
    if (!selectedOrder) {
      e.preventDefault();
      alert('주문을 먼저 선택해 주세요.');
      return;
    }
    if (pendingScans.length === 0) {
      e.preventDefault();
      alert('없는 바코드이거나 유효한 스캔 내역이 없습니다.');
      return;
    }
  });

  renderOrderList();
  renderSaleItems();
  renderScanDetails();
})();
</script>

<?= view('bag/_dev_all_sales_panel') ?>
