﻿/* =========================================================
   data.jsx — hotels, rooms, escrow & trust helpers, copy
   ========================================================= */

/* ETH formatting */
function fmtEth(v){
  if(v==null||isNaN(v)) return "0";
  const n = Number(v);
  const digits = n > 0 && n < 0.0001 ? 6 : 4;
  let s = n.toFixed(digits);
  s = s.replace(/0+$/,"").replace(/\.$/,"");
  return s;
}
function shortAddr(a){ return a ? a.slice(0,6)+"…"+a.slice(-4) : ""; }
function shortHash(h){ return h ? h.slice(0,10)+"…"+h.slice(-8) : ""; }

/* trust tier from deposit ratio (%) */
function trustTier(ratio){
  if(ratio>=140) return { level:3, label:"최고 신뢰", cls:"tier-3", short:"S", color:"var(--green)" };
  if(ratio>=110) return { level:2, label:"높은 신뢰", cls:"tier-2", short:"A", color:"var(--green)" };
  if(ratio>=85)  return { level:1, label:"신뢰", cls:"tier-1", short:"B", color:"var(--clay)" };
  return { level:0, label:"기본", cls:"tier-0", short:"C", color:"var(--faint)" };
}

/* refund schedule for guest cancellation */
function refundSchedule(checkInIso){
  const days = Math.ceil((new Date(checkInIso).setHours(0,0,0,0) - new Date().setHours(0,0,0,0)) / 86400000);
  let pct = 0, tierLabel="당일";
  if(days >= 30){ pct=100; tierLabel="D-30 이전"; }
  else if(days >= 7){ pct=70; tierLabel="D-7 이전"; }
  else if(days >= 1){ pct=50; tierLabel="D-1 이전"; }
  else { pct=0; tierLabel="당일"; }
  return { days, pct, tierLabel };
}
const REFUND_RULES = [
  { k:"D-30 이전", v:"100%" },
  { k:"D-7 이전",  v:"70%" },
  { k:"D-1 이전",  v:"50%" },
  { k:"당일 / 노쇼", v:"0%" },
];

/* booking status meta */
const STATUS = {
  booked:    { label:"예약중",    badge:"badge-amber", dot:"var(--amber)" },
  checkedin: { label:"체크인 완료", badge:"badge-blue",  dot:"var(--blue)" },
  completed: { label:"이용 완료",   badge:"badge-green", dot:"var(--green)" },
  cancelled: { label:"취소됨",     badge:"badge-gray",  dot:"var(--faint)" },
  disputed:  { label:"보상 완료",   badge:"badge-red",   dot:"var(--red)" },
};

const FEE_RATE = 0.005; // 0.5% protocol fee

/* date helpers */
function fmtDate(iso){
  const d = new Date(iso);
  return `${d.getMonth()+1}월 ${d.getDate()}일`;
}
function fmtDateFull(iso){
  const d=new Date(iso); const wd=["일","월","화","수","목","금","토"][d.getDay()];
  return `${d.getFullYear()}.${String(d.getMonth()+1).padStart(2,"0")}.${String(d.getDate()).padStart(2,"0")} (${wd})`;
}
function nightsBetween(a,b){ return Math.max(1, Math.round((new Date(b)-new Date(a))/86400000)); }
function isoPlusDays(n){ const d=new Date(); d.setDate(d.getDate()+n); d.setHours(15,0,0,0); return d.toISOString().slice(0,10); }
function fmtAgo(ms){
  const s=Math.floor((Date.now()-ms)/1000);
  if(s<60) return "방금";
  if(s<3600) return Math.floor(s/60)+"분 전";
  if(s<86400) return Math.floor(s/3600)+"시간 전";
  return Math.floor(s/86400)+"일 전";
}

/* photo: deterministic image over a cool gradient fallback (picsum is reliable) */
function hashCode(str=""){ let h=0; for(let i=0;i<str.length;i++){ h=(h<<5)-h+str.charCodeAt(i); h|=0; } return Math.abs(h); }
function photoUrl(seed, w=900, h=640){
  return `https://picsum.photos/seed/${encodeURIComponent(seed)}/${w}/${h}`;
}

/* ---- hotels: created at runtime, mirrored on window.__HOTELS ---- */
if(!window.__HOTELS) window.__HOTELS = [];
function getHotel(id){ return (window.__HOTELS||[]).find(h=>h.id===id); }
function hotelName(id){ const h=getHotel(id); return h?h.name:id; }

/* build a full hotel object from the register form */
let __hotelSeq = 1;
function slugify(s){
  return (s||"hotel").trim().toLowerCase()
    .replace(/[^a-z0-9가-힣]+/g,"-").replace(/^-+|-+$/g,"") || "hotel";
}
function makeHotel({ name, city, tagline, ratio, depositRatio, roomAddress, pricePerNightEth, image }){
  const id = "h-" + slugify(name) + "-" + (Date.now().toString(36)) + (__hotelSeq++);
  const seed = slugify(name) + "-" + Math.floor(Math.random()*9000+1000);
  return {
    id, seed,
    image: image || "",
    name: name || "내 호텔",
    city: city || "대한민국",
    area: city || "",
    tagline: tagline || "신뢰 보증금으로 안심하고 묵는 숙소",
    desc: tagline || "회원님의 예약금만큼 보증금을 함께 예치하는 신뢰 호텔입니다.",
    depositRatio: depositRatio ?? ratio,
    roomAddress: roomAddress || null,
    pricePerNightEth: pricePerNightEth || null,
    reviews: 0,
    rating: null,
    amenities: ["무료 Wi-Fi", "조식 가능", "예약금 에스크로 보호"],
    rooms: [],
    photos: [seed, seed+"-2", seed+"-3", seed+"-4"],
  };
}

/* 1박 대표가 — 판매 가능(판매기간 안 지난) 객실 중 최저가 (없으면 null) */
function hotelPrice(h){
  const rooms = (h && h.rooms) || [];
  const pool = rooms.filter(roomListable);
  const use = pool.length ? pool : rooms;
  return use.length ? Math.min(...use.map(r=>r.price)) : null;
}

/* 날짜 구간 겹침 판정 — [aFrom,aTo) 와 [bFrom,bTo) 가 겹치는가 */
function rangesOverlap(aFrom, aTo, bFrom, bTo){
  return new Date(aFrom) < new Date(bTo) && new Date(bFrom) < new Date(aTo);
}
/* 선택한 체크인~체크아웃이 이미 예약된 구간과 겹치는가 */
function roomHasConflict(room, checkIn, checkOut){
  const rs = (room && room.bookedRanges) || [];
  return rs.some(r=> rangesOverlap(checkIn, checkOut, r.from, r.to));
}
/* 몇 개의 예약 구간이 있는가 */
function roomBookedCount(room){ return ((room&&room.bookedRanges)||[]).length; }
/* 판매 기간이 아직 끝나지 않은 객실인가 (목록 노출 조건) */
function roomListable(room){
  if(!room) return false;
  if(room.isAvailable === false) return false;
  if(!room.availTo) return true;
  return new Date(room.availTo) >= new Date(new Date().setHours(0,0,0,0));
}

Object.assign(window, {
  fmtEth, shortAddr, shortHash, trustTier, refundSchedule, REFUND_RULES,
  STATUS, FEE_RATE, fmtDate, fmtDateFull, nightsBetween, fmtAgo, photoUrl,
  getHotel, hotelName, makeHotel, hotelPrice, isoPlusDays,
  rangesOverlap, roomHasConflict, roomBookedCount, roomListable,
});
