﻿/* =========================================================
   components.jsx — shared UI
   ========================================================= */

/* ---------- icons (simple line set) ---------- */
const ICONS = {
  shield:"M12 3l7 3v5c0 4.4-3 7.4-7 9-4-1.6-7-4.6-7-9V6l7-3z",
  shieldCheck:"M12 3l7 3v5c0 4.4-3 7.4-7 9-4-1.6-7-4.6-7-9V6l7-3zM9 11.5l2 2 4-4",
  lock:"M6 10V7a6 6 0 0112 0v3M5 10h14v10H5z",
  check:"M5 12l4.5 4.5L19 7",
  star:"M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 17l-5.2 2.6 1-5.8L3.5 9.7l5.9-.9z",
  search:"M11 4a7 7 0 105 12 7 7 0 00-5-12zM20 21l-4-4",
  calendar:"M4 6h16v15H4zM4 10h16M8 3v4M16 3v4",
  user:"M12 12a4 4 0 100-8 4 4 0 000 8zM5 21a7 7 0 0114 0",
  mapPin:"M12 21s-7-6-7-11a7 7 0 0114 0c0 5-7 11-7 11zM12 10a2 2 0 100-4 2 2 0 000 4z",
  arrowRight:"M5 12h14M13 5l7 7-7 7",
  wallet:"M3 7h15a2 2 0 012 2v8a2 2 0 01-2 2H4a1 1 0 01-1-1zM3 7l13-3v3M17 13h.01",
  chevron:"M9 6l6 6-6 6",
  chevronD:"M6 9l6 6 6-6",
  plus:"M12 5v14M5 12h14",
  minus:"M5 12h14",
  x:"M6 6l12 12M18 6L6 18",
  copy:"M9 9h11v11H9zM5 15H4V4h11v1",
  external:"M14 4h6v6M20 4l-9 9M18 14v5a1 1 0 01-1 1H5a1 1 0 01-1-1V7a1 1 0 011-1h5",
  sparkle:"M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z",
  clock:"M12 7v5l3 2M12 21a9 9 0 100-18 9 9 0 000 18z",
  alert:"M12 9v4M12 17h.01M10.3 3.9L2.4 18a2 2 0 001.7 3h15.8a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z",
  building:"M5 21V4h9v17M14 9h5v12M8 8h2M8 12h2M8 16h2",
  coins:"M9 13a5 5 0 100-10 5 5 0 000 10zM15 21a5 5 0 100-10M9 13c0 .7 0 2 0 2a5 5 0 005 5",
  logout:"M14 8V6a2 2 0 00-2-2H5v16h7a2 2 0 002-2v-2M9 12h12M18 9l3 3-3 3",
  info:"M12 16v-5M12 8h.01M12 21a9 9 0 100-18 9 9 0 000 18z",
  sliders:"M4 8h10M18 8h2M4 16h2M10 16h10M14 5v6M6 13v6",
  bolt:"M13 2L4 14h7l-1 8 9-12h-7z",
  gift:"M20 12v9H4v-9M2 7h20v5H2zM12 22V7M12 7S10 3 7 4s0 3 5 3zM12 7s2-4 5-3-0 3-5 3z",
  bed:"M3 18v-6h18v6M3 12V7a1 1 0 011-1h7v6M21 18v-2",
  key:"M14 7a4 4 0 11-4 4l-7 7v3h3l1-1v-2h2v-2h2l2-2",
};
function Icon({ name, size=18, sw=1.8, style, ...rest }){
  const d = ICONS[name] || "";
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round"
      style={{flex:"none", ...style}} {...rest}>
      {d.split("M").filter(Boolean).map((seg,i)=> <path key={i} d={"M"+seg} />)}
    </svg>
  );
}

/* ---------- photo: deterministic premium gradient + faint motif (no random images) ---------- */
const PHOTO_THEMES = [
  ["oklch(0.74 0.085 230)","oklch(0.43 0.12 252)"],  // ocean blue
  ["oklch(0.75 0.08 200)","oklch(0.45 0.10 212)"],   // teal
  ["oklch(0.72 0.095 162)","oklch(0.45 0.10 176)"],  // green
  ["oklch(0.78 0.075 92)","oklch(0.55 0.10 66)"],    // warm sand
  ["oklch(0.72 0.09 282)","oklch(0.43 0.13 286)"],   // indigo
  ["oklch(0.73 0.085 325)","oklch(0.46 0.11 335)"],  // plum
  ["oklch(0.76 0.08 52)","oklch(0.52 0.11 38)"],     // terra dawn
  ["oklch(0.74 0.085 250)","oklch(0.44 0.12 268)"],  // dusk
];
const PHOTO_MOTIFS = ["building","bed","key","mapPin"];
function seedHash(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 Photo({ seed, src, w=900, h=640, className="", style, children, rounded }){
  if(src){
    return (
      <div className={"photo "+className}
        style={{ backgroundImage:`url(${src})`, backgroundSize:"cover", backgroundPosition:"center", borderRadius:rounded||0, ...style }}>
        {children}
      </div>
    );
  }
  const hsh = seedHash(String(seed));
  const [a,b] = PHOTO_THEMES[hsh % PHOTO_THEMES.length];
  const motif = PHOTO_MOTIFS[(hsh>>3) % PHOTO_MOTIFS.length];
  const angle = 125 + (hsh % 60);
  return (
    <div className={"photo "+className}
      style={{ background:`linear-gradient(${angle}deg, ${a}, ${b})`, borderRadius:rounded||0, ...style }}>
      <div style={{position:"absolute",inset:0,zIndex:0,display:"grid",placeItems:"center",overflow:"hidden"}}>
        <Icon name={motif} size={Math.max(64, (typeof style?.height==="number"?style.height:h)*0.42)}
          sw={1} style={{color:"#fff",opacity:0.14,transform:`translate(14%,12%) rotate(-8deg)`}} />
      </div>
      {children}
    </div>
  );
}

/* ---------- stars ---------- */
function Stars({ rating, size=13 }){
  if(rating==null) return null;
  return (
    <span className="row gap-4">
      <Icon name="star" size={size} sw={0} style={{fill:"var(--amber)", stroke:"none"}} />
      <b style={{fontSize:size+1}}>{rating.toFixed(1)}</b>
    </span>
  );
}

/* ---------- status badge ---------- */
function StatusBadge({ status }){
  const s = STATUS[status] || STATUS.booked;
  return <span className={"badge "+s.badge}><span style={{width:7,height:7,borderRadius:"50%",background:s.dot}}></span>{s.label}</span>;
}

/* ---------- trust tier chip ---------- */
function TierChip({ ratio, withRatio }){
  const t = trustTier(ratio);
  return (
    <span className={"tier "+t.cls}>
      <span className="dot"></span>
      {t.level>=2 && <Icon name="shieldCheck" size={13} />}
      {t.label}
      {withRatio && <span className="mono" style={{opacity:.7,fontWeight:600}}>· {ratio}%</span>}
    </span>
  );
}

/* ---------- radial trust meter ---------- */
function TrustMeter({ ratio, size=132, stroke=12, showLabel=true }){
  const t = trustTier(ratio);
  const r = (size - stroke)/2;
  const c = 2*Math.PI*r;
  const frac = Math.min(ratio, 160)/160;
  const [off, setOff] = useState(c);
  useEffect(()=>{ const id=setTimeout(()=> setOff(c*(1-frac)), 60); return ()=>clearTimeout(id); },[c,frac]);
  return (
    <div className="meter" style={{width:size,height:size}}>
      <svg width={size} height={size}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--surface-3)" strokeWidth={stroke} />
        <circle className="meter-c" cx={size/2} cy={size/2} r={r} fill="none"
          stroke={t.color} strokeWidth={stroke} strokeLinecap="round"
          strokeDasharray={c} strokeDashoffset={off} />
      </svg>
      <div className="meter-label">
        <div className="serif" style={{fontSize:size*0.26, fontWeight:700, lineHeight:1}}>{ratio}<span style={{fontSize:size*0.12}}>%</span></div>
        {showLabel && <div className="xs" style={{color:t.color,fontWeight:700,marginTop:3}}>{t.label}</div>}
      </div>
    </div>
  );
}

/* ---------- deposit comparison viz ---------- */
function DepositViz({ ratio, amount }){
  const collateral = amount!=null ? amount*ratio/100 : null;
  const guestW = 100/(100+ratio)*100;
  const hotelW = ratio/(100+ratio)*100;
  return (
    <div className="col gap-16">
      <div className="col gap-8">
        <div className="row between small">
          <span className="row gap-6" style={{whiteSpace:"nowrap"}}><span style={{width:9,height:9,borderRadius:3,background:"var(--clay)"}}></span>회원 예약금</span>
          <b className="mono" style={{whiteSpace:"nowrap"}}>{amount!=null? fmtEth(amount)+" ETH":"100%"}</b>
        </div>
        <div className="dbar"><span style={{width:"100%",background:"linear-gradient(90deg,var(--clay),var(--blue))"}}></span></div>
      </div>
      <div className="col gap-8">
        <div className="row between small">
          <span className="row gap-6" style={{whiteSpace:"nowrap"}}><span style={{width:9,height:9,borderRadius:3,background:"var(--green)"}}></span>호텔 보증금 <span className="muted">담보</span></span>
          <b className="mono" style={{whiteSpace:"nowrap"}}>{collateral!=null? fmtEth(collateral)+" ETH":ratio+"%"}</b>
        </div>
        <div className="dbar"><span style={{width:Math.min(ratio,160)/160*100+"%",background:"linear-gradient(90deg,var(--green),oklch(0.62 0.12 168))"}}></span></div>
      </div>
      <div className="row gap-8 small muted" style={{lineHeight:1.5}}>
        <Icon name="info" size={15} style={{marginTop:1,color:"var(--green)"}} />
        <span>호텔이 회원님 예약금의 <b style={{color:"var(--green-deep)"}}>{ratio}%</b>를 담보로 함께 예치합니다. 문제 발생 시 이 보증금이 즉시 회원님께 지급됩니다.</span>
      </div>
    </div>
  );
}

/* ---------- hotel card ---------- */
function HotelCard({ hotel }){
  const t = trustTier(hotel.depositRatio);
  return (
    <button className="card fade-in" onClick={()=>navigate(`/hotels/${hotel.id}`)}
      style={{textAlign:"left", padding:0, overflow:"hidden", border:"1px solid var(--line)", background:"var(--surface)", cursor:"pointer", display:"flex", flexDirection:"column"}}>
      <Photo seed={hotel.seed} src={hotel.image} h={340} style={{height:188}}>
        <div className="row between" style={{position:"absolute",inset:0,padding:13,alignItems:"flex-start"}}>
          <TierChip ratio={hotel.depositRatio} />
          {hotel.rating
            ? <span className="badge" style={{background:"oklch(0.22 0.03 264 / .55)",color:"#fff",backdropFilter:"blur(4px)"}}>
                <Icon name="star" size={12} style={{fill:"var(--amber)",stroke:"none"}} />{hotel.rating.toFixed(1)}
              </span>
            : <span className="badge" style={{background:"oklch(0.22 0.03 264 / .55)",color:"#fff",backdropFilter:"blur(4px)"}}>
                <Icon name="sparkle" size={12} />신규
              </span>}
        </div>
      </Photo>
      <div className="col gap-10" style={{padding:"16px 17px 18px"}}>
        <div>
          <div className="row gap-6 muted xs" style={{marginBottom:4}}><Icon name="mapPin" size={13} />{hotel.city}</div>
          <div className="h-md" style={{lineHeight:1.3}}>{hotel.name}</div>
        </div>
        <div className="small muted" style={{minHeight:38, lineHeight:1.5}}>{hotel.tagline}</div>
        <hr className="hairline" />
        <div className="row between">
          <div className="row gap-6 xs" style={{color:"var(--green-deep)",fontWeight:700,whiteSpace:"nowrap"}}>
            <Icon name="shieldCheck" size={14} />보증금 {hotel.depositRatio}%
          </div>
          {(()=>{ const p=hotelPrice(hotel); return p!=null ? (
            <div className="row gap-4" style={{alignItems:"baseline",whiteSpace:"nowrap"}}>
              <b className="mono" style={{fontSize:16}}>{fmtEth(p)}</b>
              <span className="xs muted">ETH / 박</span>
            </div>
          ) : <span className="badge badge-gray xs">객실 준비중</span>; })()}
        </div>
      </div>
    </button>
  );
}

/* ---------- network pill ---------- */
function NetworkPill(){
  const { network, setNetwork } = useStore();
  const ok = network==="sepolia";
  return (
    <button className={"net-pill "+(ok?"net-ok":"net-bad")} onClick={()=> setNetwork(ok?"wrong":"sepolia")}
      title="클릭하여 네트워크 상태 전환 (데모)">
      <span className="dot"></span>{ok? "Sepolia 테스트넷":"네트워크 전환 필요"}
    </button>
  );
}

/* ---------- wallet chip / connect ---------- */
function WalletButton({ compact }){
  const { wallet, connectWallet, disconnect } = useStore();
  const [open, setOpen] = useState(false);
  if(!wallet){
    return <button className="btn btn-dark btn-sm" onClick={connectWallet}><Icon name="wallet" size={16}/>지갑 연결</button>;
  }
  return (
    <div style={{position:"relative"}}>
      <button className="wallet-chip" onClick={()=>setOpen(o=>!o)}>
        <span className="avatar"></span>
        <span className="mono">{shortAddr(wallet.address)}</span>
        <Icon name="chevronD" size={14} style={{color:"var(--muted)"}} />
      </button>
      {open && (
        <>
          <div style={{position:"fixed",inset:0,zIndex:70}} onClick={()=>setOpen(false)}></div>
          <div className="card" style={{position:"absolute",right:0,top:"calc(100% + 8px)",width:248,zIndex:71,padding:14,borderRadius:16}}>
            <div className="xs muted">연결된 지갑</div>
            <div className="mono small" style={{wordBreak:"break-all",margin:"4px 0 10px"}}>{wallet.address}</div>
            <div className="panel" style={{padding:"10px 12px",marginBottom:10}}>
              <div className="xs muted">잔액</div>
              <div className="row gap-6" style={{alignItems:"baseline"}}><b className="mono" style={{fontSize:18}}>{fmtEth(wallet.balance)}</b><span className="xs muted">SepoliaETH</span></div>
            </div>
            <button className="btn btn-line btn-sm btn-block" onClick={()=>{setOpen(false);disconnect();}}><Icon name="logout" size={15}/>연결 해제</button>
          </div>
        </>
      )}
    </div>
  );
}

/* ---------- header ---------- */
function Header({ route }){
  const { wallet, role } = useStore();
  const nav = [
    { to:"/hotels", label:"호텔 둘러보기" },
    { to:"/my-bookings", label:"내 예약" },
  ];
  if(role==="hotel" || true) nav.push({ to:"/hotel/dashboard", label:"호텔 관리자" });
  return (
    <header className="hdr">
      <div className="wrap wrap-wide hdr-inner">
        <a className="logo" onClick={()=>navigate("/")} style={{cursor:"pointer"}}>
          <span className="logo-mark"><Icon name="shieldCheck" size={18} style={{color:"#fff"}} /></span>
          BlockStay
        </a>
        <nav className="nav" style={{flex:1}}>
          {nav.map(n=>(
            <a key={n.to} className={route===n.to||(n.to!=="/"&&route.startsWith(n.to))?"active":""} onClick={()=>navigate(n.to)} style={{cursor:"pointer"}}>{n.label}</a>
          ))}
        </nav>
        <div className="row gap-12">
          <NetworkPill />
          <WalletButton />
        </div>
      </div>
    </header>
  );
}

/* ---------- footer ---------- */
function Footer(){
  return (
    <footer className="foot">
      <div className="wrap wrap-wide row between wrap-row gap-16">
        <div className="row gap-10">
          <span className="logo-mark" style={{width:26,height:26}}><Icon name="shieldCheck" size={15} style={{color:"#fff"}}/></span>
          <span><b className="serif">BlockStay</b> · 신뢰를 예치하는 호텔 예약 프로토콜</span>
        </div>
        <div className="row gap-16 xs">
          <span className="mono">Contract 0x9f…Es</span>
          <span>Sepolia Testnet · 데모 시뮬레이션</span>
        </div>
      </div>
    </footer>
  );
}

/* ---------- modal shell ---------- */
function Modal({ children, onClose, wide }){
  useEffect(()=>{
    const h = e=> e.key==="Escape" && onClose && onClose();
    window.addEventListener("keydown",h); return ()=>window.removeEventListener("keydown",h);
  },[onClose]);
  return (
    <div className="overlay" onClick={onClose}>
      <div className={"modal "+(wide?"modal-lg":"")} onClick={e=>e.stopPropagation()}>{children}</div>
    </div>
  );
}

/* ---------- transaction modal ---------- */
function TxModal(){
  const { tx, closeTx } = useStore();
  if(!tx) return null;
  const stages = tx.kind==="connect"
    ? [["request","MetaMask에서 연결 승인"],["pending","연결 중"],["done","연결 완료"]]
    : [["request","지갑에서 승인하기"],["pending","처리 중"],["done","완료"]];
  const order = { request:0, pending:1, done:2 };
  const cur = order[tx.stage];
  const done = tx.stage==="done";
  return (
    <Modal onClose={ done? closeTx : undefined }>
      <div style={{padding:"22px 24px 14px", borderBottom:"1px solid var(--line)"}}>
        <div className="row between">
          <div className="row gap-10">
            <span className="logo-mark" style={{background:done?"var(--green)":"var(--clay)"}}>
              <Icon name={done?"check":"shieldCheck"} size={18} style={{color:"#fff"}} />
            </span>
            <div>
              <div className="h-md">{tx.title}</div>
            </div>
          </div>
          {done && <button className="btn btn-line btn-sm" onClick={closeTx} style={{padding:8}}><Icon name="x" size={16}/></button>}
        </div>
        {tx.subtitle && <div className="small muted" style={{marginTop:12,lineHeight:1.55}}>{tx.subtitle}</div>}
      </div>

      <div style={{padding:"16px 24px"}}>
        {stages.map(([key,label],i)=>{
          const st = i<cur?"done":i===cur?"active":"";
          return (
            <div key={key}>
              <div className={"txstep "+st}>
                <span className="txdot">
                  {i<cur ? <Icon name="check" size={15}/> : i===cur && !done ? <span className="spin" style={{width:15,height:15,borderWidth:2}}></span> : i===cur&&done? <Icon name="check" size={15}/> : i+1}
                </span>
                <div className="grow">
                  <div style={{fontWeight:600, fontSize:14, color: st?"var(--ink)":"var(--muted)"}}>{label}</div>
                  {key==="pending" && i===cur && !done && <div className="mono xs muted" style={{marginTop:2}}>네트워크 수수료 ~ 0.00021 ETH</div>}
                </div>
              </div>
              {i<stages.length-1 && <div className={"txline "+(i<cur?"done":"")}></div>}
            </div>
          );
        })}
      </div>

      {tx.kind==="contract" && (
        <div style={{padding:"4px 24px 22px"}}>
          <div className="panel" style={{padding:"11px 14px"}}>
            <div className="row between">
              <span className="xs muted">거래 번호</span>
              {done && <a className="link-clay xs row gap-4" href={`https://sepolia.etherscan.io/tx/${tx.hash}`} target="_blank" rel="noreferrer">Etherscan<Icon name="external" size={12}/></a>}
            </div>
            <div className="mono xs" style={{wordBreak:"break-all",marginTop:3,opacity:done?1:.5}}>{shortHash(tx.hash)}</div>
          </div>
          {done && <button className="btn btn-primary btn-block" style={{marginTop:14}} onClick={closeTx}>확인</button>}
        </div>
      )}
    </Modal>
  );
}

/* ---------- toast ---------- */
function Toast(){
  const { toast } = useStore();
  if(!toast) return null;
  return <div className="toast"><Icon name="check" size={16} style={{color:"var(--green)"}}/>{toast}</div>;
}

/* ---------- empty / guard ---------- */
function ConnectGate({ title, sub }){
  const { connectWallet } = useStore();
  return (
    <div className="wrap" style={{padding:"90px 0"}}>
      <div className="card card-pad col center gap-16" style={{maxWidth:440,margin:"0 auto",textAlign:"center",padding:"48px 36px"}}>
        <span className="logo-mark" style={{width:52,height:52,borderRadius:16}}><Icon name="wallet" size={26} style={{color:"#fff"}}/></span>
        <div>
          <div className="h-lg">{title||"지갑 연결이 필요해요"}</div>
          <div className="muted small" style={{marginTop:6}}>{sub||"예약 내역은 지갑 주소를 기준으로 조회됩니다."}</div>
        </div>
        <button className="btn btn-dark btn-lg" onClick={connectWallet}><Icon name="wallet" size={18}/>MetaMask 연결</button>
        <a className="link-clay small" onClick={()=>navigate("/connect")} style={{cursor:"pointer"}}>처음이신가요? 온보딩 가이드 보기</a>
      </div>
    </div>
  );
}

/* ---------- step header (for booking flow) ---------- */
function FlowSteps({ step }){
  const steps = ["예약 정보","예치 서명","예약 완료"];
  return (
    <div className="row gap-8" style={{justifyContent:"center"}}>
      {steps.map((s,i)=>(
        <React.Fragment key={s}>
          <div className="row gap-8">
            <span className="txdot" style={{width:26,height:26,fontSize:12,
              background:i<=step?"var(--clay)":"var(--surface-3)", color:i<=step?"#fff":"var(--muted)", borderColor:i<=step?"var(--clay)":"var(--line-2)"}}>
              {i<step? <Icon name="check" size={14}/> : i+1}
            </span>
            <span className="small" style={{fontWeight:600,color:i<=step?"var(--ink)":"var(--muted)"}}>{s}</span>
          </div>
          {i<steps.length-1 && <span style={{width:28,height:1,background:"var(--line-2)"}}></span>}
        </React.Fragment>
      ))}
    </div>
  );
}

Object.assign(window, {
  Icon, Photo, Stars, StatusBadge, TierChip, TrustMeter, DepositViz, HotelCard,
  NetworkPill, WalletButton, Header, Footer, Modal, TxModal, Toast, ConnectGate, FlowSteps,
});
