<?php
$selectedDate = $_GET['date'] ?? date('Y-m-d');
$canViewAllDrivers = ($_SESSION['ss_LEVEL'] <= 5 || $_SESSION['ss_GROUP'] == 1);
$selectedDriver = $_GET['driver_uid'] ?? ($canViewAllDrivers ? 0 : $_SESSION['ss_DRUID']);

$isAdmin = $canViewAllDrivers;

// driver filter
$whereDriver = "";
if(!$isAdmin){
  $driver_uid = $_SESSION['ss_DRUID'];
  $whereDriver = " AND di_driver_uid = '{$driver_uid}'";
}else{
  $driver_uid = (int)($_GET['driver_uid'] ?? 0);

  if($driver_uid > 0){
    $whereDriver = " AND di_driver_uid = '{$driver_uid}'";
  }
}

// driver list
$driverList = [];
$sql_member = "SELECT dr_uid, dr_initial FROM tbl_driver WHERE dr_type = 'INSTALL' ORDER BY dr_initial";
$res_member = $jdb->nQuery($sql_member, "Load driver list error");
while($row = mysqli_fetch_assoc($res_member)){
  $driverList[] = $row;
}

$driverInitialMap = [];
foreach($driverList as $d){
  $driverInitialMap[(int)$d['dr_uid']] = $d['dr_initial'];
}

// daily install data
$installData = [];
$sql_order = "
  SELECT di.*,
    n.n_note AS di_additional_note,
    EXISTS(
      SELECT 1
      FROM tbl_customer_image ci
      WHERE ci.i_sourceuid = di.di_uid
      LIMIT 1
    ) AS has_image
  FROM tbl_daily_install di
  LEFT JOIN tbl_note n 
    ON n.n_dailyuid = CONCAT('i_', di.di_uid)
  WHERE di_install_date = '{$selectedDate}'
  {$whereDriver}
  ORDER BY di_driver_uid, di_order_seq ASC
";
$res_order = $jdb->nQuery($sql_order, "Load daily install error");

// install container
while($row = mysqli_fetch_assoc($res_order)){

  // 컨테이너 불러오기
  $containers = [];
  $sql2 = "
    SELECT *
    FROM tbl_daily_install_container
    WHERE dic_di_uid = {$row['di_uid']}
  ";
  $r2 = $jdb->nQuery($sql2,"Load container error");

  while($c = mysqli_fetch_assoc($r2)){
    $containers[] = $c;
  }

  $row['containers'] = $containers;
  $installData[] = $row;
}

// image
if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') {
  if (ob_get_length()) ob_clean();
  header('Content-Type: application/json; charset=utf-8');

  $type = $_GET['type'] ?? '';          // 'install' or 'install_order'
  $sourceuid = (int)($_GET['sourceuid'] ?? 0);

  // type 화이트리스트
  if (!in_array($type, ['install', 'install_order', 'clean_before', 'clean_after'], true)) {
      echo json_encode(['ok' => false, 'msg' => 'Invalid type']);
      exit;
  }

  $qry = "
      SELECT tci.*
      FROM tbl_customer_image tci
      WHERE tci.i_type = '".addslashes($type)."'
        AND tci.i_sourceuid = {$sourceuid}
        AND tci.i_status = 'A'
      ORDER BY tci.i_uid DESC
      LIMIT 1
  ";
  $rt = $jdb->nQuery($qry, "work image list error");
  $img = mysqli_fetch_assoc($rt);

  // 없으면 빈
  if (!$img) {
      echo json_encode(['ok' => true, 'data' => null]);
      exit;
  }

  // filepath + filename split
  $files = array_filter(array_map('trim', explode(',', $img['i_filename'] ?? '')));
  $first = $files ? $files[0] : '';

  $imgPath = '';
  if ($first !== '') {
      $imgPath = ($img['i_filepath'] ?? '') . $first;
  }

  echo json_encode([
      'ok' => true,
      'data' => [
          'i_uid' => $img['i_uid'],
          'i_type' => $img['i_type'],
          'i_sourceuid' => $img['i_sourceuid'],
          'i_note' => $img['i_note'],
          'i_createddate' => $img['i_createddate'],
          'imgPath' => $imgPath,
          'filename' => $first
      ]
  ]);
  exit;
}
?>

<main id="main" class="main" style="padding-bottom:25px;">

  <!-- ======= Breadcrumbs ======= -->
  <div class="breadcrumbs">
    <div class="container">
      <div class="d-flex justify-content-between align-items-center">
        <h2>INSTALL ORDER</h2>
        <ol>
          <li><a href="index_intranet.php">HOME</a></li>
          <li>ORDER</li>
          <li>INSTALL ORDER</li>
        </ol>
      </div>
    </div>
  </div>

  <div id="installOrderContext"
        data-member-uid="<?=$_SESSION['ss_UID']?>"
        data-driver-uid="<?=$_SESSION['ss_DRUID']?>">
  </div>

  <section class="page">
    <div class="container-fluid">

      <div class="row">

        <!-- ===== LEFT PANEL ===== -->
        <div class="col-md-2">

          <!-- CONTROL -->
          <div class="card mb-3">
            <div class="card-body d-flex flex-column align-items-center">

              <!-- DATE -->
              <div class="mb-3 w-100 d-flex flex-column align-items-center">

                <input type="text" id="installDate"
                  class="form-control form-control-sm text-center"
                  style="width:100%; padding:0px; margin:0px;"
                  value="<?=$selectedDate?>" readonly>

                <div class="d-flex mt-1" style="width:100%;">
                  <button class="btn btn-sm btn-outline-secondary w-50" id="prevDay">
                    <i class="bi bi-chevron-left"></i>
                  </button>
                  <button class="btn btn-sm btn-outline-secondary w-50" id="nextDay">
                    <i class="bi bi-chevron-right"></i>
                  </button>
                </div>

              </div>

              <!-- DRIVER -->
              <div class="mb-3 w-100 d-flex justify-content-center">
                <select id="driverSelect"
                  class="form-select form-select-sm text-center"
                  style="width:100%;"
                  <?=(!$isAdmin ? 'disabled' : '')?>>

                  <?php if($isAdmin): ?>
                    <option value="0">ALL</option>
                  <?php endif; ?>

                  <?php foreach($driverList as $d): ?>
                    <option value="<?=$d['dr_uid']?>"
                      <?=($selectedDriver == $d['dr_uid'])?'selected':''?>>
                      <?=$d['dr_initial']?>
                    </option>
                  <?php endforeach; ?>

                </select>
              </div>

              <!-- TOGGLE -->
              <div class="radio-segment d-flex" style="width:100%;">
                <label class="w-50 text-center">
                  <input type="radio" name="view_mode" value="list" checked>
                  <span>LIST</span>
                </label>
                <label class="w-50 text-center">
                  <input type="radio" name="view_mode" value="map">
                  <span>MAP</span>
                </label>
              </div>

            </div>
          </div>

          <!-- LOAD BEFORE -->
          <div class="card mb-3">
            <div class="card-body">
              <h6 class="mb-2">Load Before Start</h6>
              <div id="summaryInstall"></div>
            </div>
          </div>

          <!-- LOAD AFTER -->
          <div class="card">
            <div class="card-body">
              <h6 class="mb-2">Expected Return</h6>
              <div id="summaryPickup"></div>
            </div>
          </div>

        </div>

        <!-- ===== RIGHT PANEL ===== -->
        <div class="col-md-10">

          <!-- LIST -->
          <div id="listSection">
            <div id="installList"></div>
          </div>

          <!-- MAP -->
          <div id="mapSection" class="card d-none">
            <div class="card-body p-0">
              <div id="installMap" style="height:80vh;"></div>

              <div id="installMapLegend" class="install-map-legend"></div>
            </div>
          </div>

        </div>

      </div>

    </div>
  </section>
</main>

<!-- =============================== -->
<!-- WORK MODAL (TR CLICK) -->
<!-- =============================== -->
<div class="modal fade" id="workModal" tabindex="-1" aria-labelledby="workModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-lg modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header">
        <div>
          <h5 class="modal-title" id="workModalLabel">Work</h5>
        </div>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>

      <div class="modal-body" style="padding: 1.25rem;">

        <!-- Summary -->
        <div class="mb-3">
          <div class="fw-bold" id="wm_customer"></div>
          <div class="small text-muted" id="wm_address"></div>
          <div class="small text-muted" id="wm_phone"></div>
        </div>

        <div class="d-flex align-items-start justify-content-between mb-2" id="wm_note_row">
          <div id="wm_note_area" class="small text-muted flex-grow-1"></div>

          <div class="ms-2 flex-shrink-0">
            <button type="button" class="btn btn-sm btn-outline-secondary" id="wm_instruction_photos_btn">
              <i class="bi bi-images"></i>
              Instruction
            </button>
          </div>
        </div>

        <div id="wm_action_area"></div>

        <hr>

        <div class="row g-3">
          <!-- Left: Comment -->
          <div class="col-md-7">
            <table class="tb-info-box">
              <colgroup>
                <col style="width:20%">
                <col style="width:80%">
              </colgroup>
              <tr>
                <td class="td-title-info">Result</td>
                <td class="td-text-info">
                  <input type="radio" class="btn-check" name="wm_result" id="wm_result_asplanned" value="AS_PLANNED" autocomplete="off" checked>
                  <label class="btn" for="wm_result_asplanned">As planned</label>

                  <input type="radio" class="btn-check" name="wm_result" id="wm_result_modified" value="MODIFIED" autocomplete="off">
                  <label class="btn" for="wm_result_modified">Modified</label>

                  <input type="radio" class="btn-check" name="wm_result" id="wm_result_cancelled" value="CANCELLED" autocomplete="off">
                  <label class="btn" for="wm_result_cancelled">Cancelled</label>
                </td>
              </tr>
              <tr>
                <td class="td-title-info">Install Note</td>
                <td class="td-text-info"><textarea class="form-control" id="wm_comment" rows="2" style="margin-bottom:0px;"></textarea></td>
              </tr>
              <tr>
                <td class="td-title-info">Additional Note</td>
                <td class="td-text-info"><textarea class="form-control" id="wm_add_comment" rows="2" style="margin-bottom:0px;"></textarea></td>
              </tr>
              <tr>
                <td class="td-title-info">Oil Quantity</td>
                <td class="td-text-info"><input type="number" id="wm_quantity" minlength="1" maxlength="10" style="width:100%;"></td>
              </tr>
              <tr>
                <td class="td-title-info">Sludge</td>
                <td class="td-text-info"><input type="number" id="wm_sludge" minlength="1" maxlength="10" style="width:100%;"></td>
              </tr>
            </table>
          </div>

          <!-- Right: After Photos -->
          <div class="col-md-5">
            <div id="wm_photo_section" class="row g-2">

              <!-- BEFORE -->
              <div id="wm_before_wrap" class="col-6" style="display:none;">
                <div class="photo-card before">
                  <div class="photo-header">Before</div>

                  <div id="wm_before_photo_list" class="photo-body"></div>

                  <input type="file" class="form-control form-control-sm mt-2" id="wm_photos_before" accept="image/*">
                </div>
              </div>

              <!-- AFTER -->
              <div id="wm_after_wrap" class="col-12">
                <div class="photo-card after">
                  <div class="photo-header">After</div>

                  <div id="wm_after_photo_list" class="photo-body"></div>

                  <input type="file" class="form-control form-control-sm mt-2" id="wm_photos_after" accept="image/*">
                </div>
              </div>

            </div>
          </div>
        </div>

      </div>

      <div class="modal-footer">
        <button type="button" class="btn btn-primary" id="wm_save">Save</button>
      </div>

    </div>
  </div>
</div>

<!-- =============================== -->
<!-- IMAGE MODAL  -->
<!-- =============================== -->
<div class="modal fade" id="customerImageModal" tabindex="-1">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header">
        <h5 class="modal-title">
          <i class="bi bi-image"></i> Customer Images
        </h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body" id="customerImageModalBody">
        <div class="text-center text-muted py-5">
          Loading images...
        </div>
      </div>

    </div>
  </div>
</div>

<!-- =============================== -->
<!-- MESSAGE MODAL  -->
<!-- =============================== -->
<div class="modal fade" id="myModalPopup" tabindex="-1" role="dialog" aria-labelledby="myModalPopup" style="opacity: 0.5; padding-right: 0px !important;">
  <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
      <div class="modal-content" style="background-color:#2A9B56 !important; max-width:260px; margin: 0 auto;">
        <div class="myModalPopup-body" style="text-align: center; border-radius: 5px; max-height:60px;	font-size:18px; background-color:#2A9B56; color: #FFFFFF; font-weight: bold;padding:0.5em 1em; ">
        </div>     	
      </div>
  </div>
</div>

<!-- =============================== -->
<!-- JAVASCRIPT -->
<!-- =============================== -->
<script>
let installData = <?=json_encode($installData)?>;
let driverInitialMap = <?=json_encode($driverInitialMap)?>;
let reorderModeDriverUid = null;
let reorderSelectedRow = null; // currently selected for reorder
const selectedDate = "<?= $selectedDate ?>";

document.addEventListener("DOMContentLoaded", function () {
  renderList();
  renderSummary();
  initWorkModal();

  $('#installDate').datepicker({
    dateFormat: 'yy-mm-dd',
    changeMonth: true,
    changeYear: true,
    onSelect: function(dateText) {
      reloadPage();
    }
  });

  // installList 안의 tr 클릭
  document.getElementById('installList').addEventListener('click', function(e){

    // Reorder 버튼
    const btn = e.target.closest('.btn-reorder');
    if(btn){
      const driverUid = btn.dataset.driverUid;
      toggleReorderMode(driverUid, btn);
      return; // 여기서 끝
    }

    // ▲ 이동
    const btnUp = e.target.closest('.btn-move-up');
    if(btnUp){
      moveUp();
      return;
    }

    // ▼ 이동
    const btnDown = e.target.closest('.btn-move-down');
    if(btnDown){
      moveDown();
      return;
    }

    const btnRoute = e.target.closest('.btn-route');
    if(btnRoute){
      openRoute(btnRoute.dataset.driverUid);
      return;
    }

    // Row 클릭
    const tr = e.target.closest('tr[data-uid]');
    if(!tr) return;

    // =========================
    // reorder 모드일 때
    // =========================
    if (reorderModeDriverUid) {

      const tbody = tr.closest('tbody[id^="tbody_"]');
      if (!tbody || tbody.id !== `tbody_${reorderModeDriverUid}`) {
        return;
      }

      // status-A만 선택 가능
      if (!tr.classList.contains('status-A')) return;

      selectReorderRow(tr);
      updateMoveButtons(reorderModeDriverUid);

      return; // 모달 열지 않음
    }

    // =========================
    // 일반 모드
    // =========================
    openWorkModal(tr.dataset.uid);
  });
});

function selectReorderRow(tr){

  // 기존 선택 제거
  document.querySelectorAll('.reorder-selected-row').forEach(r=>{
    r.classList.remove('reorder-selected-row');
  });

  // 현재 선택
  tr.classList.add('reorder-selected-row');
  reorderSelectedRow = tr;
}

function updateMoveButtons(driverUid){

  // 해당 드라이버 카드의 버튼 영역 가져오기
  const controls = document.querySelector(`.reorder-controls[data-driver-uid="${driverUid}"]`);
  if(!controls) return; // 없으면 종료

  // 위/아래 버튼 가져오기
  const upBtn = controls.querySelector('.btn-move-up');
  const downBtn = controls.querySelector('.btn-move-down');

  // 선택된 row가 없으면 둘 다 비활성
  if(!reorderSelectedRow){
    upBtn.disabled = true;
    downBtn.disabled = true;
    return;
  }

  // 이전 형제가 없으면 (맨 위) 비활성
  upBtn.disabled = !reorderSelectedRow.previousElementSibling;

  // 다음 형제가 없으면 (맨 아래) 비활성
  downBtn.disabled = !reorderSelectedRow.nextElementSibling;
}

function moveUp(){

  // 선택된 row가 없으면 아무것도 안 함
  if(!reorderSelectedRow) return;

  // 현재 row의 바로 위 row 가져오기
  const prev = reorderSelectedRow.previousElementSibling;

  // 이미 맨 위면 이동 불가
  if(!prev) return;

  // 부모 tbody 가져오기
  const tbody = reorderSelectedRow.parentNode;

  // 현재 row를 prev 앞에 넣는다 (한 칸 위로 이동)
  tbody.insertBefore(reorderSelectedRow, prev);

  // 이동 후 순서 다시 계산
  renumberActiveRowsFromDOM(tbody);

  // 버튼 상태 갱신 (맨 위/아래 체크)
  updateMoveButtons(reorderModeDriverUid);
}

function moveDown(){

  // 선택된 row 없으면 종료
  if(!reorderSelectedRow) return;

  // 현재 row의 바로 아래 row 가져오기
  const next = reorderSelectedRow.nextElementSibling;

  // 이미 맨 아래면 이동 불가
  if(!next) return;

  // 부모 tbody 가져오기
  const tbody = reorderSelectedRow.parentNode;

  // next를 현재 row 앞으로 이동시킨다 (한 칸 아래로 이동)
  tbody.insertBefore(next, reorderSelectedRow);

  // 순번 다시 계산
  renumberActiveRowsFromDOM(tbody);

  // 버튼 상태 갱신
  updateMoveButtons(reorderModeDriverUid);
}

function renumberActiveRowsFromDOM(tbody){

  let maxSeq = 0;

  // 기존 완료된 row들(P/M/X)에서 최대 seq 찾기
  tbody.querySelectorAll('tr').forEach(tr => {

    if(tr.classList.contains('status-A')) return; // A는 제외

    const firstCell = tr.children[0];
    if(!firstCell) return;

    const val = parseInt(firstCell.textContent, 10);
    if(!isNaN(val) && val > maxSeq){
      maxSeq = val;
    }
  });

  // A row는 maxSeq 다음부터 순번 부여
  let seq = maxSeq + 1;

  tbody.querySelectorAll('tr.status-A').forEach(tr => {

    const firstCell = tr.children[0];
    if(firstCell){
      firstCell.textContent = seq;
    }

    seq++;
  });
}

/* ===============================
  Modal
=================================*/
let workModal;          // bootstrap modal instance
let selectedRow = null; // currently opened row data

function initWorkModal(){
  const el = document.getElementById('workModal');
  if(!el) return;
  workModal = new bootstrap.Modal(el, {
    backdrop: true,
    keyboard: true
  });

  bindPhotoInput('wm_photos_after', 'wm_after_photo_list');
  bindPhotoInput('wm_photos_before', 'wm_before_photo_list');

  // Save 버튼
  document.getElementById('wm_save').addEventListener('click', function(){

    if(!selectedRow) return;
    const ctx = document.getElementById('installOrderContext');
    const memberUid = ctx ? (ctx.dataset.memberUid || '') : '';
    const result = document.querySelector('input[name="wm_result"]:checked')?.value || 'AS_PLANNED';
    const status = mapResultToStatus(result);
    const install_note = (document.getElementById('wm_comment').value || '').trim();
    const additional_note = (document.getElementById('wm_add_comment').value || '').trim();
    const oil_qty = parseInt(document.getElementById('wm_quantity').value || '0', 10) || 0;
    const sludge = parseInt(document.getElementById('wm_sludge').value || '0', 10) || 0;
    
    if(result !== 'AS_PLANNED' && !install_note){
      alert('Please enter a comment.');
      return;
    }


    api('daily_install_update_status', {
      di_uid: selectedRow.di_uid,
      member_uid: memberUid,
      status: status,
      install_note,
      additional_note,
      oil_qty,
      sludge
    }, (res) => {

      if(!res || res.ok != 1){
        //alert(res?.msg || 'Save failed');
        showPopupMessage(res?.msg || 'Save failed', 'error', 1500);
        return;
      }

      const workType = selectedRow.di_work_type;
      const afterFileInput = document.getElementById('wm_photos_after');
      const beforeFileInput = document.getElementById('wm_photos_before');
      const afterFile = afterFileInput?.files?.[0] || null;
      const beforeFile = beforeFileInput?.files?.[0] || null;

      let uploads = [];

      // AFTER
      if(afterFile){
        const type = (workType === 'CLEAN') ? 'clean_after' : 'install';
        uploads.push(uploadPhotoPromise(selectedRow, afterFile, type));
      }

      // BEFORE (CLEAN만)
      if(workType === 'CLEAN' && beforeFile){
        uploads.push(uploadPhotoPromise(selectedRow, beforeFile, 'clean_before'));
      }

      if(uploads.length > 0){
        Promise.all(uploads).then(results => {

          const hasError = results.some(r => !r || r.ok != 1);

          if(hasError){
            showPopupMessage('Saved (photo partial fail)', 'error', 1500);
          }else{
            showPopupMessage('Successfully Saved', 'success', 1000);
          }

          location.reload();
        });
      }else{
        showPopupMessage('Successfully Saved', 'success', 1000);
        location.reload();
      }
    });

  });

  function mapResultToStatus(result){
    if(result === 'AS_PLANNED') return 'P';
    if(result === 'MODIFIED') return 'M';
    if(result === 'CANCELLED') return 'X';
    return 'P';
  }

  const btn = document.getElementById('wm_instruction_photos_btn');
  if(btn){
    btn.addEventListener('click', function(){
      if(!selectedRow) return;

      const customerUid = selectedRow.di_customer_uid;
      openCustomerImages(customerUid, 'install_order');
    });
  }

  document.querySelectorAll('input[name="wm_result"]').forEach(radio => {
    radio.addEventListener('change', updateCommentReadonlyByResult);
  });

  // 모달이 닫힐 때 입력값 초기화
  el.addEventListener('hidden.bs.modal', function(){
    selectedRow = null;
    document.getElementById('wm_comment').value = '';
    document.getElementById('wm_add_comment').value = '';
    document.getElementById('wm_note_area').innerHTML = '';
    resetPhotoBlocks();
  });
}

function findRowByUid(di_uid){
  di_uid = String(di_uid);
  return (installData || []).find(r => String(r.di_uid) === di_uid) || null;
}

async function openWorkModal(di_uid){
  const row = findRowByUid(di_uid);
  if(!row){
    //alert('Row not found: ' + di_uid);
    showPopupMessage('Row not found: ' + di_uid, 'error', 1500);
    return;
  }
  selectedRow = row;

  // ready
  const address = `${row.di_address || ''}, ${row.di_city || ''}, ${row.di_postal || ''}`;
  const phone = formatPhone(row.di_phone || '');

  // basic info
  document.getElementById('workModalLabel').textContent = `#${row.di_order_seq || ''} - ${row.di_work_type || 'WORK'}`;
  document.getElementById('wm_customer').textContent = `${row.di_customer_name || ''} (${row.di_accountno || ''})`;
  document.getElementById('wm_address').innerHTML = `${escapeHtml(address)} ${phone ? ` <span class="text-muted">· ${escapeHtml(phone)}</span>` : ''}`;
  document.getElementById('wm_comment').value = row.di_install_note || '';
  document.getElementById('wm_add_comment').value = row.di_additional_note || '';
  document.getElementById('wm_quantity').value = row.di_oil_pickup || '';
  document.getElementById('wm_sludge').value = row.di_sludge || '';

  // 상태 세팅
  setResultRadioByStatus(row.di_status);
  updateCommentReadonlyByResult();

  // note
  renderWorkNotes(row);

  // container
  renderWorkActionBoxes();
  fillWorkModalContainers(row);

  // photos
  togglePhotoSection(row.di_work_type);
  await loadAfterPhoto(row);
  if(row.di_work_type === 'CLEAN'){
    await loadBeforePhoto(row);
  }

  // open
  workModal.show();
}

function renderWorkActionBoxes(){

  const area = document.getElementById('wm_action_area');
  area.innerHTML = `
    <div class="row g-3">
      <div class="col-md-6">
        ${renderWorkActionBox('PICKUP')}
      </div>
      <div class="col-md-6">
        ${renderWorkActionBox('INSTALL')}
      </div>
    </div>
  `;
}

function renderWorkActionBox(action){

  const icon = {
    PICKUP:  'bi-dash-circle',
    INSTALL: 'bi-plus-circle'
  }[action] || 'bi-box';

  const colorClass =
    action === 'PICKUP'  ? 'pickup'
  : action === 'INSTALL' ? 'install'
  : '';

  return `
    <div class="mb-3 task-action-box" data-action="${action}">
      <div class="task-action-title ${colorClass}">
        <i class="bi ${icon}"></i> ${action}
      </div>

      <div class="mt-2 container-chips" data-action="${action}"></div>
    </div>
  `;
}

function renderContainerChipsForAction(containers, action){

  const list = (containers || []).filter(c => String(c.dic_action || '').toUpperCase() === action);
  if(list.length === 0){
    return `<div class="text-muted small">No ${action.toLowerCase()} containers</div>`;
  }

  return list.map(c => {

    // chip class
    const isRestaurantOwned = (c.dic_owner_type === 'O');
    const chipClass = isRestaurantOwned ? 'chip chip-restaurant' : 'chip chip-company';

    // icon
    const icon = getContainerIcon(c.dic_type);

    return `
      <span class="${chipClass}">
        <i class="bi ${icon}"></i>
        ${isRestaurantOwned ? '<span class="ms-1 fw-bold">O</span>' : ''}
        ${c.dic_is_used === 'Y' ? '<span class="ms-1">Used</span>' : ''}
        <span class="ms-1">${escapeHtml(c.dic_type || '')}</span>
        ${c.dic_has_lock === 'Y' ? '<i class="bi bi-lock-fill ms-1"></i>' : ''}
        ${c.dic_has_wheel === 'Y' ? '<i class="bi bi-gear-fill ms-1"></i>' : ''}
        ${c.dic_has_woodframe === 'Y' ? '<i class="bi bi-bounding-box-circles ms-1"></i>' : ''}
      </span>
    `;
  }).join('');
}

function fillWorkModalContainers(row){

  const area = document.getElementById('wm_action_area');
  if(!area) return;

  const containers = row?.containers || [];

  const pickupWrap = area.querySelector('.container-chips[data-action="PICKUP"]');
  if(pickupWrap){
    pickupWrap.innerHTML = renderContainerChipsForAction(containers, 'PICKUP');
  }

  const installWrap = area.querySelector('.container-chips[data-action="INSTALL"]');
  if(installWrap){
    installWrap.innerHTML = renderContainerChipsForAction(containers, 'INSTALL');
  }
}

function renderWorkNotes(row){

  const area = document.getElementById('wm_note_area');
  if(!area) return;

  const req  = (row.di_request_note || '').trim();
  const work = (row.di_work_note || '').trim();

  let html = '';

  if(req){
    html += `
      <div class="small text-muted mb-1">
        <strong>Request:</strong>
        ${escapeHtml(req)}
      </div>
    `;
  }

  if(work){
    html += `
      <div class="small text-muted mb-1">
        <strong>Work:</strong>
        ${escapeHtml(work)}
      </div>
    `;
  }

  area.innerHTML = html;
}

function setResultRadioByStatus(status){

  // 기본 초기화
  document.querySelectorAll('input[name="wm_result"]').forEach(r => r.checked = false);

  if(status === 'P') document.getElementById('wm_result_asplanned').checked = true;
  else if(status === 'M') document.getElementById('wm_result_modified').checked = true;
  else if(status === 'X') document.getElementById('wm_result_cancelled').checked = true;
  else document.getElementById('wm_result_asplanned').checked = true;
}

function updateCommentReadonlyByResult(){

  const result = document.querySelector('input[name="wm_result"]:checked')?.value;
  const textarea = document.getElementById('wm_comment');

  if(!textarea) return;

  if(result === 'AS_PLANNED'){
    textarea.setAttribute('readonly', 'readonly');
    textarea.classList.add('bg-light');

    // 이미 저장된 노트가 있으면 그걸 우선 사용
    if (selectedRow && (selectedRow.di_install_note || '').trim()) {
      textarea.value = selectedRow.di_install_note;
      return;
    }

    // 저장된 노트가 없을 때만 자동 생성
    if(selectedRow){
      const mapped = (selectedRow.containers || []).map(c => ({
        action: (c.dic_action || '').toUpperCase(),
        type: c.dic_type,
        used: c.dic_is_used === 'Y',
        wheel: c.dic_has_wheel === 'Y',
        lock: c.dic_has_lock === 'Y',
        frame: c.dic_has_woodframe === 'Y'
      }));

      textarea.value = generateAutoComment(mapped);
    }

  }else{
    textarea.removeAttribute('readonly');
    textarea.classList.remove('bg-light');
  }
}

function generateAutoComment(containers){

  let install = {};
  let pickup = {};

  containers.forEach(c=>{

    const key = buildContainerLabel(c);

    if(c.action === 'INSTALL'){
      install[key] = (install[key] || 0) + 1;
    }

    if(c.action === 'PICKUP'){
      pickup[key] = (pickup[key] || 0) + 1;
    }
  });

  let parts = [];

  Object.entries(install).forEach(([k,v])=>{
    parts.push(`Installed ${v} ${k}`);
  });

  Object.entries(pickup).forEach(([k,v])=>{
    parts.push(`Picked up ${v} ${k}`);
  });

  if(parts.length === 0){
    return 'Completed as planned.';
  }

  return parts.join(', ') + ' as planned.';
}

function buildContainerLabel(c){

  let label = '';

  if(c.used){
    label += 'Used ';
  }

  // 기본 타입
  label += c.type;

  const suffix = [];

  if(c.wheel) suffix.push('W');
  if(c.lock) suffix.push('L');
  if(c.frame) suffix.push('F');

  if(suffix.length > 0){
    label += '/' + suffix.join('/');
  }

  return label;
}

/* ===============================
  Image
=================================*/
async function fetchWorkImage(type, sourceuid){
  const qs = new URLSearchParams({
    view: 'install_order',
    ajax: 'work_images',
    type,
    sourceuid
  });

  const res = await fetch(`index_intranet.php?${qs.toString()}`);
  const json = await res.json();
  if(!json || json.ok !== true) return null;
  return json.data || null;
}

async function loadAfterPhoto(row){
  const workType = row.di_work_type;
  let type = 'install';
  if(workType === 'CLEAN'){
    type = 'clean_after';
  }

  const data = await fetchWorkImage(type, row.di_uid);
  row._afterPhoto = data;
  renderAfterPhoto(data);
}

async function loadBeforePhoto(row){

  if(row.di_work_type !== 'CLEAN') return;

  const data = await fetchWorkImage('clean_before', row.di_uid);
  row._beforePhoto = data;
  renderBeforePhoto(data);
}

function renderAfterPhoto(photo){

  const wrap = document.getElementById('wm_after_photo_list');
  if(!wrap) return;

  if(!photo || !photo.imgPath){
    wrap.innerHTML = `<div class="small text-muted">No after photo.</div>`;
    return;
  }

  const url = photo.imgPath;

  wrap.innerHTML = `
    <div style="width:100%;">
      <img src="${escapeHtml(url)}"
           style="width:100%; height:160px; object-fit:cover; border-radius:8px; border:1px solid #ddd; cursor:pointer;"
           class="after-photo-thumb"
           data-img-url="${escapeHtml(url)}">
    </div>
  `;

  // 클릭 이벤트 연결
  const imgEl = wrap.querySelector('.after-photo-thumb');
  if(imgEl){
    imgEl.addEventListener('click', function(){

      const modalEl = document.getElementById('customerImageModal');
      const body = document.getElementById('customerImageModalBody');

      if(!modalEl || !body) return;

      body.innerHTML = `
        <div class="text-center">
          <img src="${escapeHtml(url)}"
               style="max-width:100%; max-height:75vh; border-radius:10px;">
        </div>
      `;

      const modal = new bootstrap.Modal(modalEl);
      modal.show();
    });
  }
}

function renderBeforePhoto(photo){

  const wrap = document.getElementById('wm_before_photo_list');
  if(!wrap) return;

  if(!photo || !photo.imgPath){
    wrap.innerHTML = `<div class="small text-muted">No before photo.</div>`;
    return;
  }

  const url = photo.imgPath;

  wrap.innerHTML = `
    <div style="width:100%;">
      <img src="${escapeHtml(url)}"
           style="width:100%; height:160px; object-fit:cover; border-radius:8px; border:1px solid #ddd; cursor:pointer;">
    </div>
  `;
}

function resetPhotoBlocks(){

  // AFTER
  const afterList = document.getElementById('wm_after_photo_list');
  if(afterList) afterList.innerHTML = '';

  const afterInput = document.getElementById('wm_photos_after');
  if(afterInput) afterInput.value = '';

  // BEFORE
  const beforeList = document.getElementById('wm_before_photo_list');
  if(beforeList) beforeList.innerHTML = '';

  const beforeInput = document.getElementById('wm_photos_before');
  if(beforeInput) beforeInput.value = '';

  if(selectedRow){
    selectedRow._afterPhoto = null;
    selectedRow._beforePhoto = null;
  }
}

function openCustomerImages(customerUid, iType = 'install_order') {
  
  const modalEl = document.getElementById('customerImageModal');
  if(!modalEl){
    console.error('customerImageModal not found');
    return;
  }

  const modal = new bootstrap.Modal(modalEl);
  const body = document.getElementById('customerImageModalBody');

  body.innerHTML = '<div class="text-center text-muted py-5">Loading images...</div>';
  modal.show();

  const params = new URLSearchParams({
    customer_uid: customerUid,
    i_type: iType
  });

  fetch('/lib/customer_image.php?' + params.toString(), {
    credentials: 'same-origin'
  })
    .then(res => res.text())
    .then(html => {
      body.innerHTML = html;
    })
    .catch(err => {
      console.error(err);
      body.innerHTML = '<div class="text-danger text-center py-5">Failed to load images.</div>';
    });
}

function bindPhotoInput(inputId, targetWrapId){

  const input = document.getElementById(inputId);
  if(!input) return;

  input.addEventListener('change', function(e){

    const file = e.target.files[0];
    if(!file) return;

    if(!file.type.startsWith('image/')){
      alert('Please select an image file.');
      return;
    }

    const reader = new FileReader();

    reader.onload = function(ev){
      renderPreviewImage(ev.target.result, targetWrapId);
    };

    reader.readAsDataURL(file);
  });
}

function renderPreviewImage(base64, target){

  const wrap = document.getElementById(target);
  if(!wrap) return;

  wrap.innerHTML = `
    <div style="width:100%; position:relative;">
      <img src="${base64}"
           style="width:100%; height:160px; object-fit:cover; border-radius:8px;">
      
      <div style="
        position:absolute;
        top:6px;
        left:6px;
        background:#000000aa;
        color:#fff;
        font-size:11px;
        padding:2px 6px;
        border-radius:4px;
      ">
        Preview
      </div>
    </div>
  `;
}

function togglePhotoSection(workType){

  const beforeWrap = document.getElementById('wm_before_wrap');
  const afterWrap  = document.getElementById('wm_after_wrap');

  if(workType === 'CLEAN'){
    // BEFORE 보이기
    beforeWrap.style.display = '';
    beforeWrap.classList.remove('col-12');
    beforeWrap.classList.add('col-6');
    afterWrap.classList.remove('col-12');
    afterWrap.classList.add('col-6');

  }else{
    // BEFORE 숨김
    beforeWrap.style.display = 'none';
    afterWrap.classList.remove('col-6');
    afterWrap.classList.add('col-12');
  }
}

function uploadPhotoPromise(row, file, type){

  return new Promise((resolve) => {

    const ctx = document.getElementById('installOrderContext');
    const memberUid = ctx ? (ctx.dataset.memberUid || '') : '';

    const fd = new FormData();
    fd.append('di_uid', row.di_uid);
    fd.append('member_uid', memberUid);
    fd.append('note', (document.getElementById('wm_comment').value || '').trim());
    fd.append('i_type', type);
    fd.append('photo', file);

    fetch('/assets/internal_api.php?func=upload_after_photo', {
      method: 'POST',
      body: fd
    })
    .then(r => r.json())
    .then(json => resolve(json))
    .catch(err => {
      console.error(err);
      resolve({ ok:0 });
    });

  });
}

/* ===============================
  Date
=================================*/
document.getElementById('installDate').addEventListener('change', reloadPage);

function parseDate(str) {
  const [y, m, d] = (str || '').split('-').map(Number);
  return new Date(y, m - 1, d);   // ✅ 로컬 날짜로 생성
}

function formatDate(d) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;      // ✅ 로컬 날짜로 문자열
}

function moveBusinessDate(date, diffDays) {
  const d = new Date(date);
  let moved = 0;

  while (moved < Math.abs(diffDays)) {
    d.setDate(d.getDate() + Math.sign(diffDays));
    const day = d.getDay();
    if (day !== 0 && day !== 6) moved++;
  }
  return d;
}

function adjustDate(diff) {
  const input = document.getElementById('installDate');
  let val = input.value;

  if (!val) return; // 또는 기본값 세팅 원하면 여기서 처리

  const current = parseDate(val);
  const next = moveBusinessDate(current, diff);

  input.value = formatDate(next);
  input.dispatchEvent(new Event('change'));
}

document.getElementById('prevDay').onclick = () => adjustDate(-1);
document.getElementById('nextDay').onclick = () => adjustDate(1);

/* ===============================
  List
=================================*/
function renderList(){

  const container = document.getElementById('installList');
  container.innerHTML = '';

  // ===== 전체 데이터 없음 =====
  if(!installData || installData.length === 0){
    installData = [];
  }

  // ===== driver 목록 확보 (ALL일 때 빈 driver도 보여주기) =====
  const grouped = {};

  // 기존 데이터 그룹핑
  installData.forEach(row => {
    const d = row.di_driver_uid;
    if(!grouped[d]) grouped[d] = [];
    grouped[d].push(row);
  });

  // ALL 모드일 경우 driverInitialMap 기준으로 전체 driver 보장
  const driverSelect = document.getElementById('driverSelect');
  const selectedDriver = driverSelect ? String(driverSelect.value) : '0';
  let driverUids;
  if(selectedDriver !== '0'){
    driverUids = [selectedDriver];
  }else{
    driverUids = Object.keys(driverInitialMap).filter(uid => String(uid) !== '0');
  }
  driverUids.forEach(driverUid => {

    const driverInitial = driverInitialMap[driverUid] || driverUid;
    const rows = grouped[driverUid] || [];

    let html = `
      <div class="card mb-4 install-driver-card" data-driver-uid="${driverUid}">
        <div class="fw-bold d-flex justify-content-between align-items-center iw-header" style="padding: 8px 16px;">
          <div>${driverInitial}</div>

          <div class="d-flex align-items-center gap-2 reorder-controls" data-driver-uid="${driverUid}">
            <button type="button"
                    class="btn btn-sm btn-light btn-move-down d-none"
                    data-driver-uid="${driverUid}"
                    disabled>
              <i class="bi bi-chevron-down"></i>
            </button>

            <button type="button"
                    class="btn btn-sm btn-light btn-move-up d-none"
                    data-driver-uid="${driverUid}"
                    disabled>
              <i class="bi bi-chevron-up"></i>
            </button>

            <button type="button"
                    class="btn btn-sm btn-outline-light btn-reorder"
                    data-driver-uid="${driverUid}">
              <i class="bi bi-arrow-down-up"></i> Reorder
            </button>

            <button type="button"
                    class="btn btn-sm btn-outline-light btn-route"
                    data-driver-uid="${driverUid}">
              <i class="bi bi-geo-alt"></i> Route
            </button>
          </div>
        </div>
        <div class="card-body p-0">
          <table class="table table-sm table-hover mb-0 install-order-table" style="table-layout: fixed; width:100%;">
            <colgroup>
              <col style="width:2%">
              <col style="width:10%">
              <col style="width:12%">
              <col style="width:26%">
              <col style="width:24%">
              <col style="width:26%">
            </colgroup>
            <tbody id="tbody_${driverUid}">
    `;

    // ===== 데이터 없을 때 =====
    if(rows.length === 0){
      html += `
        <tr>
          <td colspan="6" class="text-center text-muted py-3">
            No orders.
          </td>
        </tr>
      `;
    }else{

      rows.forEach(row => {
        const req = (row.di_request_note || '').trim();
        const work = (row.di_work_note || '').trim();

        html += `
          <tr data-uid="${row.di_uid}" class="status-${row.di_status}">
            <td class="fw-bold">${row.di_order_seq}</td>
            <td>${renderWorkCell(row)}</td>
            <td>
              <div>
                <span class="badge bg-light text-dark border">
                  ${escapeHtml(row.di_accountno || '')}
                </span>
              </div>
              <div class="small fw-bold text-truncate" title="${escapeHtml(row.di_customer_name || '')}" style="max-width:140px;">
                ${escapeHtml(row.di_customer_name || '')}
              </div>
            </td>
            <td>${renderContainers(row.containers)}</td>
            <td class="small text-muted">
              <div>
                ${escapeHtml(row.di_address)}, 
                ${escapeHtml(row.di_city)}
              </div>
              <div>
                ${escapeHtml(row.di_postal)} 
                ${formatPhone(row.di_phone)}
              </div>
            </td>
            <td class="small text-muted">
              ${req ? `
                <div class="small text-muted mb-1">
                  <strong>Request:</strong> ${escapeHtml(req)}
                </div>
              ` : ''}

              ${work ? `
                <div class="small text-muted">
                  <strong>Work:</strong> ${escapeHtml(work)}
                </div>
              ` : ''}
            </td>
          </tr>
        `;
      });
    }

    html += `
            </tbody>
          </table>
        </div>
      </div>
    `;

    container.innerHTML += html;

  });
}

function renderWorkCell(row){

  const status = row.di_status;

  // 기본 텍스트
  let main = '';

  if(status === 'A'){
    main = `${renderWorkType(row.di_work_type)}`;
  }else if(status === 'P'){
    main = `<span class="fw-bold small"> Done</span>`;
  }else if(status === 'M'){
    main = `<span class="fw-bold small"> Modified</span>`;
  }else if(status === 'X'){
    main = `<span class="fw-bold small"> Cancelled</span>`;
  }

  // 보조 아이콘
  const icons = [];

  const applied = String(row.di_container_applied || '0') === '1';
  if(applied > 0){
    icons.push(`<i class="bi bi-database-check" title="Container applied"></i>`);
  }

  const note = (row.di_additional_note || '').trim();
  if(note.length > 0){
    icons.push(`<i class="bi bi-journal-text" title="Additional note"></i>`);
  }

  const oil = parseInt(row.di_oil_pickup || '0', 10) || 0;
  if(oil > 0){
    icons.push(`<i class="bi bi-droplet-fill" title="Oil pickup: ${oil}"></i>`);
  }

  const hasImage = String(row.has_image || '0') === '1';
  if(hasImage){
    icons.push(`<i class="bi bi-image" title="Has image"></i>`);
  }

  const iconRow = icons.length
    ? `<div class="mt-1 small text-muted">${icons.join('<span class="ms-2"></span>')}</div>`
    : '';

  // 두 줄 구조
  return `
    <div>
      <div>${main}</div>
      ${iconRow}
    </div>
  `;
}

function renderWorkType(type){
  let badgeClass = 'bg-secondary';
  switch(type){
    case 'INSTALL':
      badgeClass = 'bg-success text-white';
      break;
    case 'PICKUP':
      badgeClass = 'bg-danger text-white';
      break;
    case 'EXCHANGE':
      badgeClass = 'bg-warning text-dark';
      break;
    case 'RELOCATE':
      badgeClass = 'bg-info text-dark';
      break;
    case 'CLEAN':
      badgeClass = 'bg-primary text-white';
      break;
  }
  return `<span class="badge ${badgeClass}">${type || '-'}</span>`;
}

function renderContainers(containers){

  if(!containers || containers.length === 0) return '';

  let installChips = '';
  let pickupChips = '';

  containers.forEach(c => {

    let chipClass = 'chip chip-company';
    if(c.dic_owner_type === 'O'){
      chipClass = 'chip chip-restaurant';
    }

    const icon = getContainerIcon(c.dic_type);

    const chip = `
      <span class="${chipClass}">
        <i class="bi ${icon}"></i>
        ${c.dic_owner_type === 'O' ? '<span class="ms-1 fw-bold">O</span>' : ''}
        ${c.dic_is_used === 'Y' ? '<span class="ms-1">Used</span>' : ''}
        <span class="ms-1">${c.dic_type}</span>
        ${c.dic_has_lock === 'Y' ? '<i class="bi bi-lock-fill ms-1"></i>' : ''}
        ${c.dic_has_wheel === 'Y' ? '<i class="bi bi-gear-fill ms-1"></i>' : ''}
        ${c.dic_has_woodframe === 'Y' ? '<i class="bi bi-bounding-box-circles ms-1"></i>' : ''}
      </span>
    `;

    if(c.dic_action === 'INSTALL'){
      installChips += chip;
    } else {
      pickupChips += chip;
    }
  });

  let html = `<div class="container-chips inline-chips"">`;

  if(installChips){
    html += `
      <div class="task-action-title install">
        <i class="bi bi-plus-circle fs-6"></i>
      </div>
      ${installChips}
    `;
  }

  if(pickupChips){
    html += `
      ${installChips ? '<span class="mx-1"></span>' : ''}
      <div class="task-action-title pickup">
        <i class="bi bi-dash-circle fs-6"></i>
      </div>
      ${pickupChips}
    `;
  }

  html += `</div>`;

  return html;
}

function toggleReorderMode(driverUid, btn){

  const controls = document.querySelector(`.reorder-controls[data-driver-uid="${driverUid}"]`);
  if(!controls) return;

  const upBtn = controls.querySelector('.btn-move-up');
  const downBtn = controls.querySelector('.btn-move-down');

  // 현재 상태 확인
  const isActive = !upBtn.classList.contains('d-none');

  // OFF → ON
  if(!isActive){

    reorderModeDriverUid = driverUid;

    upBtn.classList.remove('d-none');
    downBtn.classList.remove('d-none');

    // 초기에는 비활성
    upBtn.disabled = true;
    downBtn.disabled = true;

    btn.classList.add('btn-success');   // 활성 표시
    btn.classList.remove('btn-outline-light');

    // 
    btn.classList.remove('btn-outline-secondary');
    btn.classList.add('btn-secondary');
    btn.innerHTML = `<i class="bi bi-check2"></i> Done`;
    // 

  }else{
    // reorder 종료 → 저장
    saveDriverOrder(driverUid);

    // ON → OFF
    reorderModeDriverUid = null;

    upBtn.classList.add('d-none');
    downBtn.classList.add('d-none');

    btn.classList.remove('btn-success');
    btn.classList.add('btn-outline-light');

    // 선택 초기화 (다음 단계 대비)
    clearReorderSelectedRow();
  }
}

function clearReorderSelectedRow(){
  document.querySelectorAll('.reorder-selected-row').forEach(tr=>{
    tr.classList.remove('reorder-selected-row');
  });
  reorderSelectedRow = null;
}

function renumberActiveRows(driverUid){
  const $tbody = $(`#tbody_${driverUid}`);
  const $rowsA = $tbody.find('tr.status-A');

  // 완료(P/M/X)가 위에 있다면 그 개수만큼 offset
  const doneCnt = $tbody.find('tr:not(.status-A)').length;
  let seq = doneCnt + 1;

  $rowsA.each(function(){
    $(this).find('td').first().text(seq);
    seq++;
  });
}

function saveDriverOrder(driverUid){

  const tbody = document.getElementById(`tbody_${driverUid}`);
  if(!tbody) return;

  const rows = tbody.querySelectorAll("tr.status-A");
  if(!rows.length){
    //alert("No active rows to reorder.");
    showPopupMessage('No rows to reorder.', 'error', 1500);
    return;
  }

  const orderList = [];
  rows.forEach((tr, index) => {

    const diUid = tr.dataset.uid;
    const newSeq = index + 1; // 화면상 순서
    if(!diUid) return;
    
    orderList.push({
      di_uid: diUid,
      di_order_seq: newSeq
    });
  });

  api('daily_install_reorder', {
    driver_uid: driverUid,
    install_date: selectedDate,
    order_list: JSON.stringify(orderList)
  }, (res) => {

    if(!res || res.ok != 1){
      //alert(res?.msg || 'Reorder save failed');
      showPopupMessage('Save failed', 'error', 1500);
      return;
    }
    showPopupMessage('Successfully Saved', 'success', 800);
    setTimeout(function(){
      location.reload();
    }, 1500);
  });

}
/* ===============================
   SUMMARY
=================================*/
function renderSummary(){

  const install = {};
  const pickup = {};

  const optionInstall = { lock:0, wheel:0, wood:0 };
  const optionPickup  = { lock:0, wheel:0, wood:0 };

  (installData || []).forEach(row => {

    (row.containers || []).forEach(c => {

      // ===== 고유 key 구성 =====
      let key = `${c.dic_type}|${c.dic_is_used}|${c.dic_owner_type}`;

      if(c.dic_action === 'INSTALL'){
        install[key] = (install[key] || 0) + 1;

        if(c.dic_has_lock === 'Y') optionInstall.lock++;
        if(c.dic_has_wheel === 'Y') optionInstall.wheel++;
        if(c.dic_has_woodframe === 'Y') optionInstall.wood++;

      } else {

        pickup[key] = (pickup[key] || 0) + 1;

        if(c.dic_has_lock === 'Y') optionPickup.lock++;
        if(c.dic_has_wheel === 'Y') optionPickup.wheel++;
        if(c.dic_has_woodframe === 'Y') optionPickup.wood++;
      }

    });

  });

  document.getElementById('summaryInstall').innerHTML =
    `
    <div class="container-chips inline-chips mt-1">
      ${buildTypeChips(install)}
    </div>
    <div class="container-chips inline-chips mt-1">
      ${buildOptionChips(optionInstall)}
    </div>
    `;

  document.getElementById('summaryPickup').innerHTML =
    `
    <div class="container-chips inline-chips mt-1">
      ${buildTypeChips(pickup)}
    </div>
    <div class="container-chips inline-chips mt-1">
      ${buildOptionChips(optionPickup)}
    </div>
    `;

}

function getContainerIcon(type){
  if(type === 'D'){
    return 'bi-database-fill';
  }

  if(type && type.endsWith('B')){
    return 'bi-archive-fill';
  }
  return 'bi-box';
}

function buildTypeChips(typeCounts){

  let html = '';

  Object.keys(typeCounts).sort().forEach(key => {

    const [type, used, owner] = key.split('|');

    const isUsed = (used === 'Y');
    const isOwner = (owner === 'O');

    const icon = getContainerIcon(type);

    let chipClass = 'chip chip-company';
    if(isOwner){
      chipClass = 'chip chip-restaurant';
    }

    html += `
      <span class="${chipClass} me-2 mb-2" >
        <i class="bi ${icon}"></i>
        ${isOwner ? '<span class="ms-1 fw-bold">O</span>' : ''}
        ${isUsed ? '<span class="ms-1">Used</span>' : ''}
        <span class="ms-1">${type}</span>
        <strong class="ms-2">x ${typeCounts[key]}</strong>
      </span>
    `;
  });

  return html || `<span class="text-muted small">-</span>`;
}

function buildOptionChips(optionCounts){

  let html = '';

  if(optionCounts.lock > 0){
    html += `
      <span class="chip me-2 mb-2">
        <i class="bi bi-lock-fill"></i>
        <strong class="ms-1">x ${optionCounts.lock}</strong>
      </span>
    `;
  }

  if(optionCounts.wheel > 0){
    html += `
      <span class="chip me-2 mb-2">
        <i class="bi bi-gear-fill"></i>
        <strong class="ms-1">x ${optionCounts.wheel}</strong>
      </span>
    `;
  }

  if(optionCounts.wood > 0){
    html += `
      <span class="chip me-2 mb-2">
        <i class="bi bi-bounding-box-circles"></i>
        <strong class="ms-1">x ${optionCounts.wood}</strong>
      </span>
    `;
  }

  return html; // 옵션 없으면 그냥 빈칸 (줄 자체가 없어짐)
}

function reloadPage(){

  const date = document.getElementById('installDate').value;
  const driver = document.getElementById('driverSelect').value;

  const url = new URL(window.location.href);

  url.searchParams.set('view', 'install_order');
  url.searchParams.set('date', date);
  url.searchParams.set('driver_uid', driver);

  window.location.href = url.toString();
}

document.getElementById('driverSelect').onchange = reloadPage;

/* ===============================
   MAP
=================================*/
let installMap;
let installMarkers = [];
let installInfo;

async function initMap(){

  const { Map, InfoWindow } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

  installInfo = new InfoWindow();

  installMap = new Map(
    document.getElementById("installMap"),
    {
      center: { lat: 43.7, lng: -79.4 },
      zoom: 11,
      mapId: "4504f8b37365c3d0", // waitlist와 동일
      disableDefaultUI: true   // Map/Satellite 제거
    }
  );

  renderMap();
}

const driverPalette = [
  "#4275c1",
  "#91744fff",
  "#198754",
  "#dc3545",
  "#e97517ff",
  "#7443cfff",
  "#20c997",
  "#0dcaf0"
];

function getDriverColor(driverUid) {
  return driverPalette[driverUid % driverPalette.length];
}

function renderMap(){

  installMarkers.forEach(m => m.map = null);
  installMarkers = [];

  if(!installData || !installData.length) return;

  const bounds = new google.maps.LatLngBounds();

  installData.forEach(row => {

    if(!row.di_lat || !row.di_lng) return;

    const pos = {
      lat: parseFloat(row.di_lat),
      lng: parseFloat(row.di_lng)
    };

    bounds.extend(pos);

    const baseColor = getDriverColor(row.di_driver_uid);
    const driverColor = row.di_status === 'A' ? baseColor : "#7c7c7cff";
    const marker = new google.maps.marker.AdvancedMarkerElement({
      map: installMap,
      position: pos,
      content: createFlagMarker({
        order: row.di_order_seq,
        jobType: row.di_work_type,
        color: driverColor
      })
    });

    marker.__di_uid = row.di_uid;

    marker.addListener('gmp-click', () => {
      openWorkModal(row.di_uid);
    });

    installMarkers.push(marker);
  });

  installMap.fitBounds(bounds);
  renderMapLegend(installData);
}

function renderMapLegend(rows){
  const el = document.getElementById('installMapLegend');
  if(!el) return;

  const seen = new Map();

  (rows || []).forEach(row => {
    const driverUid = parseInt(row.di_driver_uid, 10);
    if(!driverUid || seen.has(driverUid)) return;

    seen.set(driverUid, {
      uid: driverUid,
      name: driverInitialMap[driverUid] || `Driver ${driverUid}`,
      color: getDriverColor(driverUid)
    });
  });

  const items = Array.from(seen.values()).sort((a, b) =>
    a.name.localeCompare(b.name)
  );

  if(items.length === 0){
    el.innerHTML = `
      <div class="install-map-legend-title">Driver</div>
      <div class="text-muted small">No routes</div>
    `;
    return;
  }

  el.innerHTML = `
    <div class="install-map-legend-title">Driver</div>
    ${items.map(item => `
      <div class="install-map-legend-item">
        <span class="install-map-legend-swatch" style="background:${item.color}"></span>
        <span>${escapeHtml(item.name)}</span>
      </div>
    `).join('')}
  `;
}

function createFlagMarker({ order, jobType, color }) {
    
  const bg =  color;
  const border = color;
  const textColor = "#ffffff";
  const iconClass = getJobBiIcon(jobType);

  const wrap = document.createElement('div');
  wrap.className = 'flag-marker';

  wrap.style.background = bg;
  wrap.style.border = `2px solid ${border}`;
  wrap.style.color = textColor;
  wrap.style.borderRadius = "8px";
  wrap.style.padding = "4px 6px";
  wrap.style.fontWeight = "600";
  wrap.style.fontSize = "12px";
  wrap.style.setProperty('--flag-bg', bg);

  wrap.innerHTML = `
    <div class="flag-body d-flex align-items-center gap-1">
      <span class="flag-order">${order}</span>
      ${iconClass ? `<i class="bi ${iconClass}"></i>` : ``}
    </div>
    <div class="flag-tail"></div>
  `;

  return wrap;
}

function getJobBiIcon(type){
  switch(type){
    case 'INSTALL':   return 'bi-plus-lg';
    case 'PICKUP':    return 'bi-dash-lg';
    case 'EXCHANGE':  return 'bi-arrow-left-right';
    case 'RELOCATE':  return 'bi-arrows-move';
    case 'CLEAN':     return 'bi-brush';
    default:          return '';
  }
}

/* ===============================
   Link
=================================*/
function openRoute(driverUid){

  // 하드코딩
  const OFFICE = "4490 Chesswood Dr, North York, ON M3J 2B9";

  const rows = installData
    .filter(r => r.di_driver_uid == driverUid)
    .sort((a,b)=>a.di_order_seq - b.di_order_seq);

  if(rows.length === 0){
    alert('No active orders.');
    return;
  }

  // 시작/종료는 사무실
  const origin = OFFICE;
  const destination = OFFICE;

  const waypoints = rows.map(r =>
    `${r.di_address}, ${r.di_city}`
  ).join('|');

  let url = `https://www.google.com/maps/dir/?api=1`;
  url += `&origin=${encodeURIComponent(origin)}`;
  url += `&destination=${encodeURIComponent(destination)}`;

  if(waypoints){
    url += `&waypoints=${encodeURIComponent(waypoints)}`;
  }

  window.open(url, '_blank');
}

/* ===============================
   UTIL
=================================*/
function escapeHtml(str){
  return String(str ?? '')
    .replaceAll('&','&amp;')
    .replaceAll('<','&lt;')
    .replaceAll('>','&gt;')
    .replaceAll('"','&quot;')
    .replaceAll("'","&#039;");
}

function formatPhone(phone){
  if(!phone) return '';
  const digits = phone.replace(/\D/g,'');
  if(digits.length === 10){
    return `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`;
  }
  return phone;
}

function showPopupMessage(message, type = 'success', duration = 1200) {

  const body = document.querySelector('#myModalPopup .myModalPopup-body');
  if (!body) return;

  body.innerHTML = message;

  if (type === 'success') {
    body.style.backgroundColor = '#2A9B56';   // green
  } else {
    body.style.backgroundColor = '#FF8205';   // orange
  }

  $('#myModalPopup').modal('show');

  setTimeout(function () {
    $('#myModalPopup').modal('hide');
  }, duration);
}

/* ===============================
   TOGGLE
=================================*/
document.querySelectorAll('input[name="view_mode"]').forEach(radio => {
  radio.addEventListener('change', function () {
    document.getElementById('mapSection')
      .classList.toggle('d-none', this.value !== 'map');

    document.getElementById('listSection')
      .classList.toggle('d-none', this.value !== 'list');

    if (this.value === 'map') {
      if (!installMap) {
        initMap();
      } else {
        setTimeout(() => google.maps.event.trigger(installMap, 'resize'), 50);
      }
    }
  });
});
</script>

<script>
  // map.php에서 쓰는 동일한 로더
  (g=>{
    var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;
    b=b[c]||(b[c]={});
    var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{
      await (a=m.createElement("script"));
      e.set("libraries",[...r]+"");
      for(k in g) e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);
      e.set("callback",c+".maps."+q);
      a.src=`https://maps.${c}apis.com/maps/api/js?`+e;
      d[q]=f;
      a.onerror=()=>h=n(Error(p+" could not load."));
      a.nonce=m.querySelector("script[nonce]")?.nonce||"";
      m.head.append(a);
    }));
    d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))
  })({key:"AIzaSyDg9u03mGrBhyOisp7VGc27CTPI9QXp8sY", v:"weekly"});
</script>
