<?php
declare(strict_types=1);
/**
 * 메인 대시보드 카카오 지도 패널 — 지도(좌) + 지정판매소 목록(우, 스크롤).
 * 주소→좌표는 카카오 지오코딩(services)으로 클라이언트 변환. 목록 클릭 시 해당 위치로 이동.
 *
 * @var string $kakaoJsKey
 * @var string $lgLabel
 * @var array<int,array{name:string,addr:string}> $mapShops
 */
$kakaoJsKey = (string) ($kakaoJsKey ?? '');
$lgLabel    = (string) ($lgLabel ?? '');
$mapShops   = is_array($mapShops ?? null) ? $mapShops : [];
$mapId      = 'mainKakaoMap';
?>
<div class="rounded-xl bg-white border border-gray-200 shadow-sm overflow-hidden">
  <div class="flex items-center justify-between px-4 py-2.5 border-b border-gray-100">
    <h2 class="text-sm font-bold text-gray-900"><i class="fa-solid fa-map-location-dot text-[#243a5e] mr-1"></i>지정판매소 위치<?= $lgLabel !== '' ? ' · ' . esc($lgLabel) : '' ?> <span class="text-[11px] font-normal text-gray-400">(<?= count($mapShops) ?>곳)</span></h2>
  </div>

  <div class="grid grid-cols-1 md:grid-cols-[1fr_240px]">
    <!-- 지도 -->
    <div id="<?= $mapId ?>" style="width:100%;height:200px;background:#eef2f7;" role="application" aria-label="<?= esc($lgLabel, 'attr') ?> 지정판매소 지도"></div>

    <!-- 판매소 목록 (스크롤) -->
    <div class="border-t md:border-t-0 md:border-l border-gray-100 overflow-y-auto" style="height:200px;">
      <?php if ($mapShops === []): ?>
      <p class="p-3 text-[12px] text-gray-400">표시할 지정판매소가 없습니다.</p>
      <?php else: ?>
      <ul id="shopList" class="divide-y divide-gray-50">
        <?php foreach ($mapShops as $i => $shop): ?>
        <li>
          <button type="button" data-idx="<?= (int) $i ?>"
                  class="shop-item w-full text-left px-3 py-2 hover:bg-blue-50/60 transition flex gap-2 items-start">
            <span class="shop-dot mt-1 inline-block w-2 h-2 rounded-full bg-gray-300 shrink-0"></span>
            <span class="min-w-0">
              <span class="block text-[12px] font-semibold text-gray-800 truncate"><?= esc($shop['name'] !== '' ? $shop['name'] : '(이름없음)') ?></span>
              <span class="block text-[11px] text-gray-500 truncate"><?= esc($shop['addr']) ?></span>
            </span>
          </button>
        </li>
        <?php endforeach; ?>
      </ul>
      <?php endif; ?>
    </div>
  </div>

  <?php if ($kakaoJsKey === ''): ?>
  <div class="px-4 py-2 text-[11px] text-amber-700 bg-amber-50 border-t border-amber-200">카카오맵 키가 설정되지 않아 지도를 표시할 수 없습니다.</div>
  <?php endif; ?>
</div>

<?php if ($kakaoJsKey !== ''): ?>
<script>
(function () {
  var APP_KEY = <?= json_encode($kakaoJsKey, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
  var SHOPS   = <?= json_encode($mapShops, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS) ?>;
  var MAP_ID  = <?= json_encode($mapId, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
  var DEFAULT_CENTER = { lat: 35.8714, lng: 128.6014 };

  var markers = {}; // idx -> kakao.maps.Marker
  var positions = {}; // idx -> kakao.maps.LatLng
  var mapRef = null, infowindow = null, geocoder = null, places = null;

  function ensureScript(cb) {
    if (typeof kakao !== 'undefined' && kakao.maps && kakao.maps.services) { cb(); return; }
    var s = document.createElement('script');
    s.charset = 'UTF-8'; s.async = true;
    s.src = 'https://dapi.kakao.com/v2/maps/sdk.js?appkey=' + encodeURIComponent(APP_KEY) + '&libraries=services&autoload=false';
    s.onload = function () {
      if (typeof kakao === 'undefined' || !kakao.maps || typeof kakao.maps.load !== 'function') { return; }
      kakao.maps.load(cb);
    };
    document.head.appendChild(s);
  }

  // "대구광역시 북구 검단동 칠곡중앙대로 21" → "대구광역시 북구 칠곡중앙대로 21" (행정동 토큰 제거)
  function roadVariant(addr) {
    var p = String(addr || '').trim().split(/\s+/);
    if (p.length < 4) return '';
    var roadIdx = -1;
    for (var i = 2; i < p.length; i++) { if (/(로|길)$/.test(p[i])) { roadIdx = i; break; } }
    if (roadIdx < 3) return '';
    var out = [];
    p.forEach(function (tok, i) {
      if (i >= 2 && i < roadIdx && /(동|가|리)$/.test(tok)) return; // 행정동 제거
      out.push(tok);
    });
    var joined = out.join(' ');
    return joined !== addr ? joined : '';
  }

  // "대구광역시 북구 검단동 ..." → "대구광역시 북구 검단동" (시도 구군 동 — 행정구역 폴백)
  function regionVariant(addr) {
    var p = String(addr || '').trim().split(/\s+/);
    if (p.length < 3) return '';
    for (var i = 2; i < p.length; i++) {
      if (/(동|가|리)$/.test(p[i])) { return p[0] + ' ' + p[1] + ' ' + p[i]; }
    }
    return p[0] + ' ' + p[1]; // 동을 못 찾으면 구·군까지
  }

  // 여러 후보를 순서대로 시도(정밀주소 → 도로명변형 → 지번 → 키워드 → 행정동 → 행정동 키워드)
  function geocodeChain(shop, cb) {
    var tries = [];
    if (shop.addr) tries.push(['addr', shop.addr]);
    var rv = roadVariant(shop.addr);
    if (rv) tries.push(['addr', rv]);
    if (shop.jibun) tries.push(['addr', shop.jibun]);
    if (rv) tries.push(['kw', rv]);
    else if (shop.addr) tries.push(['kw', shop.addr]);
    var region = regionVariant(shop.addr || shop.jibun);
    if (region) { tries.push(['addr', region]); tries.push(['kw', region]); }

    (function next(i) {
      if (i >= tries.length) { cb(null); return; }
      var mode = tries[i][0], q = tries[i][1];
      try {
        if (mode === 'addr') {
          geocoder.addressSearch(q, function (result, status) {
            if (status === kakao.maps.services.Status.OK && result && result[0]) {
              cb(new kakao.maps.LatLng(result[0].y, result[0].x));
            } else { next(i + 1); }
          });
        } else {
          places.keywordSearch(q, function (data, status) {
            if (status === kakao.maps.services.Status.OK && data && data[0]) {
              cb(new kakao.maps.LatLng(data[0].y, data[0].x));
            } else { next(i + 1); }
          });
        }
      } catch (e) { cb(null); }
    })(0);
  }

  function openInfo(idx) {
    var name = (SHOPS[idx] && SHOPS[idx].name) || '판매소';
    infowindow.setContent('<div style="padding:5px 8px;font-size:12px;font-weight:600;white-space:nowrap;">' + name + '</div>');
    if (markers[idx]) infowindow.open(mapRef, markers[idx]);
  }

  function focusShop(idx) {
    var pos = positions[idx];
    if (!pos || !mapRef) return;
    mapRef.setCenter(pos);
    mapRef.setLevel(3); // 줌인
    openInfo(idx);
  }

  function initMap() {
    var el = document.getElementById(MAP_ID);
    if (!el || typeof kakao === 'undefined' || !kakao.maps) return;
    var map = new kakao.maps.Map(el, { center: new kakao.maps.LatLng(DEFAULT_CENTER.lat, DEFAULT_CENTER.lng), level: 8 });
    mapRef = map;
    infowindow = new kakao.maps.InfoWindow({ zIndex: 1 });
    geocoder = new kakao.maps.services.Geocoder();
    places = new kakao.maps.services.Places();
    var bounds = new kakao.maps.LatLngBounds();
    var placed = 0, pending = SHOPS.length;

    // 컨테이너 크기에 맞춰 지도를 다시 그리고 영역을 재설정한다.
    function refit() {
      if (!mapRef) return;
      mapRef.relayout();
      if (placed > 0) { mapRef.setBounds(bounds); }
      else { mapRef.setCenter(new kakao.maps.LatLng(DEFAULT_CENTER.lat, DEFAULT_CENTER.lng)); }
    }
    var refitScheduled = false;
    function scheduleRefit() {
      if (refitScheduled) return;
      refitScheduled = true;
      (window.requestAnimationFrame || window.setTimeout)(function () { refitScheduled = false; refit(); });
    }

    // 탭(iframe) 안에서 컨테이너 크기가 늦게 확정되거나 바뀌면(표시 전환·창 크기 변경 등)
    // 지도가 반만 그려지거나 엉뚱한 위치(일본 등)로 보이므로, 크기 변화 때마다 다시 맞춘다.
    try {
      if (typeof ResizeObserver !== 'undefined') { new ResizeObserver(scheduleRefit).observe(el); }
    } catch (e) {}
    window.addEventListener('resize', scheduleRefit);
    window.addEventListener('pageshow', function () { setTimeout(refit, 50); });

    function done() {
      refit();
      setTimeout(refit, 150);
      setTimeout(refit, 600);
    }
    if (pending === 0) { done(); return; }

    SHOPS.forEach(function (shop, idx) {
      geocodeChain(shop, function (pos) {
        pending--;
        try {
          if (pos) {
            var marker = new kakao.maps.Marker({ position: pos, map: map });
            markers[idx] = marker;
            positions[idx] = pos;
            bounds.extend(pos); placed++;
            kakao.maps.event.addListener(marker, 'click', function () { openInfo(idx); });
            var dot = document.querySelector('.shop-item[data-idx="' + idx + '"] .shop-dot');
            if (dot) { dot.style.background = '#243a5e'; }
          }
        } catch (e) {}
        if (pending === 0) done();
      });
    });

    // 목록 클릭 → 해당 판매소로 줌인
    document.querySelectorAll('.shop-item').forEach(function (btn) {
      btn.addEventListener('click', function () { focusShop(parseInt(btn.getAttribute('data-idx'), 10)); });
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () { ensureScript(initMap); });
  } else {
    ensureScript(initMap);
  }
})();
</script>
<?php endif; ?>
