// Shared UI primitives — Button, Badge, Tag, Card, Input, etc.
const { useState, useRef, useEffect } = React;

const useTokens = () => {
  const [, force] = useState(0);
  useEffect(() => {
    const handler = () => force(x => x + 1);
    window.addEventListener('haolin-tokens-changed', handler);
    return () => window.removeEventListener('haolin-tokens-changed', handler);
  }, []);
  return window.HAOLIN_TOKENS.colors;
};

// Responsive breakpoint hook — true when viewport <= 768px
const useIsMobile = (breakpoint = 768) => {
  const [isMobile, setIsMobile] = useState(() =>
    typeof window !== 'undefined' ? window.innerWidth <= breakpoint : false
  );
  useEffect(() => {
    const onResize = () => setIsMobile(window.innerWidth <= breakpoint);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [breakpoint]);
  return isMobile;
};

// === Button ===
const Button = ({ children, variant='primary', size='md', icon, iconRight, onClick, disabled, style, ...rest }) => {
  const c = useTokens();
  const [hover, setHover] = useState(false);
  const [press, setPress] = useState(false);
  const sizeMap = {
    sm: { padY:'8px',  padX:'14px', fs:'14px', gap:'6px' },
    md: { padY:'12px', padX:'20px', fs:'15px', gap:'8px' },
    lg: { padY:'16px', padX:'28px', fs:'17px', gap:'10px' },
  };
  const s = sizeMap[size];
  const radiusMd = window.getComputedStyle(document.documentElement).getPropertyValue('--hl-radius-md').trim() || '14px';

  const base = {
    display:'inline-flex', alignItems:'center', justifyContent:'center', gap:s.gap,
    padding:`${s.padY} ${s.padX}`, fontSize:s.fs, fontWeight:600,
    borderRadius: radiusMd, border:'1px solid transparent',
    cursor: disabled ? 'not-allowed' : 'pointer',
    opacity: disabled ? 0.5 : 1,
    transition:'transform 180ms ease, box-shadow 180ms ease, background 160ms ease, border-color 160ms ease',
    fontFamily:'var(--hl-font-body)',
    transform: press ? 'translateY(1px)' : 'translateY(0)',
    letterSpacing:'0.02em',
  };

  const variants = {
    primary: {
      background: hover ? c.primaryDark : c.primary,
      color:'#fff',
      boxShadow: hover ? '0 6px 18px rgba(184, 90, 54, 0.28)' : '0 2px 6px rgba(184, 90, 54, 0.18)',
    },
    secondary: {
      background: hover ? c.bgAlt : c.paper,
      color: c.ink,
      border:`1px solid ${c.line}`,
      boxShadow: hover ? '0 4px 12px rgba(80,50,25,0.06)' : 'none',
    },
    ghost: {
      background: hover ? c.bgAlt : 'transparent',
      color: c.ink,
    },
    accent: {
      background: hover ? '#7A9D6B' : c.accent,
      color:'#fff',
    },
    danger: {
      background: hover ? '#AF5A4B' : 'transparent',
      color: hover ? '#fff' : c.danger,
      border:`1px solid ${c.danger}`,
    },
  };

  return (
    <button
      style={{...base, ...variants[variant], ...style}}
      onMouseEnter={()=>setHover(true)}
      onMouseLeave={()=>{setHover(false); setPress(false);}}
      onMouseDown={()=>setPress(true)}
      onMouseUp={()=>setPress(false)}
      onClick={onClick}
      disabled={disabled}
      {...rest}
    >
      {icon}
      {children}
      {iconRight}
    </button>
  );
};

// === Tag ===
const Tag = ({ children, tone='neutral', style }) => {
  const c = useTokens();
  const toneMap = {
    neutral: { bg:c.bgAlt, color:c.inkSoft, border:c.line },
    primary: { bg:c.primarySoft, color:c.primaryDark, border:'transparent' },
    accent:  { bg:c.accentSoft, color:'#4D6D41', border:'transparent' },
    warm:    { bg:'#F7E3D2', color:'#9C5B39', border:'transparent' },
    info:    { bg:'#E2EBF1', color:'#3E5A6C', border:'transparent' },
  };
  const t = toneMap[tone] || toneMap.neutral;
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:'4px',
      padding:'3px 10px', fontSize:'12px', fontWeight:500,
      borderRadius:'999px', background:t.bg, color:t.color,
      border:`1px solid ${t.border}`, whiteSpace:'nowrap',
      fontFamily:'var(--hl-font-body)',
      ...style,
    }}>{children}</span>
  );
};

// === Badge (status) ===
const StatusBadge = ({ status }) => {
  const c = useTokens();
  const map = {
    // 三色交替：霧綠 / 霧藍 / 淺米（絕無紅黄綠交通燈）
    '支持中':   { bg: c.bgAlt, color: c.gold, dot: c.gold },
    '已開團':   { bg: '#E2EBF1', color: c.info, dot: c.info },
    '活躍':     { bg: c.accentSoft, color:'#4D6D41', dot: c.accent },
    '休眠':     { bg: c.lineSoft, color: c.inkMuted, dot: c.inkMuted },
    '報名中':   { bg: c.primarySoft, color: c.primaryDark, dot: c.primary },
    '待審核':   { bg: '#F6E5C9', color:'#8B6830', dot:'#D9A84A' },
    '已發佈':   { bg: c.accentSoft, color:'#4D6D41', dot: c.accent },
  };
  const m = map[status] || map['休眠'];
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:'6px',
      padding:'3px 10px 3px 8px', fontSize:'12px', fontWeight:500,
      borderRadius:'999px', background:m.bg, color:m.color,
      fontFamily:'var(--hl-font-body)',
    }}>
      <span style={{width:6, height:6, borderRadius:'50%', background:m.dot}}/>
      {status}
    </span>
  );
};

// === Card ===
const Card = ({ children, hoverable, style, onClick, padding = true, ...rest }) => {
  const c = useTokens();
  const [hover, setHover] = useState(false);
  const radiusXl = 'var(--hl-radius-xl)';
  return (
    <div
      onClick={onClick}
      onMouseEnter={()=>setHover(true)}
      onMouseLeave={()=>setHover(false)}
      style={{
        background: c.paper,
        borderRadius: radiusXl,
        border: `1px solid ${c.line}`,
        padding: padding ? 'calc(20px * var(--hl-density))' : 0,
        transition:'transform 220ms ease, box-shadow 220ms ease',
        transform: hoverable && hover ? 'translateY(-4px)' : 'translateY(0)',
        boxShadow: hoverable && hover
          ? '0 18px 44px rgba(90,55,30,0.13)'
          : '0 1px 2px rgba(64,40,20,0.04)',
        cursor: onClick || hoverable ? 'pointer' : 'default',
        ...style,
      }}
      {...rest}
    >{children}</div>
  );
};

// === Input / TextArea ===
const Input = ({ label, icon, style, containerStyle, ...rest }) => {
  const c = useTokens();
  const [focus, setFocus] = useState(false);
  return (
    <div style={{display:'flex', flexDirection:'column', gap:6, ...containerStyle}}>
      {label && <label style={{fontSize:13, color:c.inkSoft, fontWeight:500}}>{label}</label>}
      <div style={{
        display:'flex', alignItems:'center', gap:10,
        padding:'10px 14px',
        background: c.paper,
        border: `1px solid ${focus ? c.primary : c.line}`,
        borderRadius:'var(--hl-radius-md)',
        transition:'border-color 140ms ease, box-shadow 140ms ease',
        boxShadow: focus ? `0 0 0 3px ${c.primarySoft}55` : 'none',
      }}>
        {icon && <span style={{color: c.inkMuted, display:'flex'}}>{icon}</span>}
        <input
          onFocus={()=>setFocus(true)}
          onBlur={()=>setFocus(false)}
          style={{
            border:'none', outline:'none', background:'transparent',
            flex:1, fontSize:15, color: c.ink, fontFamily:'var(--hl-font-body)',
            ...style,
          }}
          {...rest}
        />
      </div>
    </div>
  );
};

// === Divider ===
const Divider = ({ style }) => {
  const c = useTokens();
  return <div style={{height:1, background:c.line, width:'100%', ...style}}/>;
};

// === Section title ===
const SectionTitle = ({ eyebrow, title, subtitle, align='left' }) => {
  const c = useTokens();
  return (
    <div style={{textAlign:align, display:'flex', flexDirection:'column', gap:8, alignItems: align==='center' ? 'center' : 'flex-start'}}>
      {eyebrow && <span style={{fontSize:13, color:c.primary, fontWeight:600, letterSpacing:'0.1em'}}>{eyebrow}</span>}
      <h2 style={{
        fontFamily:'var(--hl-font-heading)',
        fontSize:'clamp(28px, 3.2vw, 40px)',
        fontWeight: 500,
        color:c.ink, margin:0, lineHeight:1.25,
        letterSpacing:'0.01em',
      }}>{title}</h2>
      {subtitle && <p style={{color:c.inkSoft, fontSize:16, margin:0, lineHeight:1.7, maxWidth: align==='center' ? 620 : 'none'}}>{subtitle}</p>}
    </div>
  );
};

// === Category pill (for category explore row) ===
const CategoryPill = ({ cat, Icon, onClick, active }) => {
  const c = useTokens();
  const [hover, setHover] = useState(false);
  return (
    <button
      onClick={onClick}
      onMouseEnter={()=>setHover(true)}
      onMouseLeave={()=>setHover(false)}
      style={{
        display:'flex', flexDirection:'column', alignItems:'center', gap:10,
        padding:'22px 16px',
        borderRadius:'var(--hl-radius-xl)',
        background: active ? c.primarySoft : (hover ? c.bgAlt : c.paper),
        border: `1px solid ${active ? c.primary : c.line}`,
        cursor:'pointer',
        transition:'all 180ms ease',
        transform: hover ? 'translateY(-2px)' : 'none',
        minWidth:120, flex:1,
        fontFamily:'var(--hl-font-body)',
      }}>
      <div style={{
        width:48, height:48, borderRadius:'50%',
        background: cat.color, color:'#fff',
        display:'flex', alignItems:'center', justifyContent:'center',
      }}>
        <Icon size={22} stroke="#fff"/>
      </div>
      <span style={{fontSize:14, fontWeight:600, color:c.ink}}>{cat.label}</span>
    </button>
  );
};

// === Group Card (list variant) ===
const GroupCard = ({ group, onClick, variant='list' }) => {
  const c = useTokens();
  const cats = window.HAOLIN_DATA.categories;
  const cat = cats.find(x => x.key === group.cat);
  const [hover, setHover] = useState(false);
  return (
    <div
      onClick={onClick}
      onMouseEnter={()=>setHover(true)}
      onMouseLeave={()=>setHover(false)}
      style={{
        background: c.paper,
        borderRadius:'var(--hl-radius-xl)',
        border: `1px solid ${c.line}`,
        overflow:'hidden',
        cursor:'pointer',
        transition:'transform 240ms ease, box-shadow 240ms ease',
        transform: hover ? 'translateY(-4px)' : 'none',
        boxShadow: hover ? '0 20px 50px rgba(90,55,30,0.14)' : '0 1px 2px rgba(64,40,20,0.04)',
        display:'flex', flexDirection:'column',
      }}>
      <div style={{height:140, background: cat.color + '20', position:'relative'}}>
        <PhotoPlaceholder width={400} height={140} label={group.name} src={group.cover}/>
        <div style={{position:'absolute', top:12, left:12}}>
          <Tag tone="primary">{cat.label}</Tag>
        </div>
      </div>
      <div style={{padding:'18px 20px 20px', display:'flex', flexDirection:'column', gap:10, flex:1}}>
        <h3 style={{
          fontFamily:'var(--hl-font-heading)',
          fontSize:19, fontWeight:500, color:c.ink,
          margin:0, letterSpacing:'0.01em',
        }}>{group.name}</h3>
        <p style={{margin:0, fontSize:14, color:c.inkSoft, lineHeight:1.6, flex:1}}>{group.tagline}</p>
        <div style={{display:'flex', gap:6, flexWrap:'wrap'}}>
          {group.tags.map(t => <Tag key={t}>{t}</Tag>)}
        </div>
        <div style={{display:'flex', justifyContent:'space-between', alignItems:'center', fontSize:13, color:c.inkMuted, marginTop:4}}>
          <span style={{display:'inline-flex', alignItems:'center', gap:4}}>
            <IconPin size={14}/> {group.region}
          </span>
          <span>下次 {group.next.split(' ')[0]}</span>
        </div>
      </div>
    </div>
  );
};

// === Six support facets (shared between admin + neighbor views) ===
const SUPPORT_FACETS = [
  { key:'marketing',  label:'行銷宣傳', short:'行銷', icon:'FacetMegaphone',   color:'#D4704A', soft:'#F5D9C8', bg:'#FBF0E4' },
  { key:'admin',      label:'開團行政', short:'行政', icon:'FacetClipboard',   color:'#C89968', soft:'#F2E6D2', bg:'#FAF3E8' },
  { key:'ai',         label:'AI 工具',   short:'AI',   icon:'FacetGear',        color:'#7A96A8', soft:'#E2EBF1', bg:'#EEF3F7' },
  { key:'emotional',  label:'情感支持', short:'情感', icon:'FacetTwoChairs',   color:'#8BAE7C', soft:'#D8E6CF', bg:'#E9F0E1' },
  { key:'peer',       label:'夥伴同行', short:'夥伴', icon:'FacetThreePeople', color:'#E8A87C', soft:'#F7E3D2', bg:'#FBEFE2' },
  { key:'spirit',     label:'信仰靈性', short:'靈性', icon:'FacetCandle',      color:'#B58B5A', soft:'#EBE0CE', bg:'#F5EDDC' },
];

// Radar chart for six facets. scores keyed by facet.key, values 0..3
const RadarChart = ({ scores, size = 220, tone = 'accent', labels = true, interactive = false, onFacetHover }) => {
  const c = window.HAOLIN_TOKENS.colors;
  const max = 3;
  const cx = size / 2, cy = size / 2;
  const radius = size * 0.36;
  const n = SUPPORT_FACETS.length;
  // Tones: accent (霧綠), info (霧藍)
  const fillColor = tone === 'info' ? '#8AA8BC' : '#8FAB8A';
  const strokeColor = tone === 'info' ? '#5E7D92' : '#6A8B5E';

  const angleFor = i => (-Math.PI / 2) + (i / n) * Math.PI * 2;
  const pointAt = (i, r) => {
    const a = angleFor(i);
    return [cx + Math.cos(a) * r, cy + Math.sin(a) * r];
  };

  // Grid rings
  const rings = [1, 2, 3].map(level => {
    const r = (level / max) * radius;
    const pts = SUPPORT_FACETS.map((_, i) => pointAt(i, r).join(',')).join(' ');
    return <polygon key={level} points={pts} fill="none" stroke={c.line} strokeWidth={level===max?1.5:1} strokeDasharray={level===max?'none':'2 3'}/>;
  });

  // Spokes
  const spokes = SUPPORT_FACETS.map((_, i) => {
    const [x, y] = pointAt(i, radius);
    return <line key={i} x1={cx} y1={cy} x2={x} y2={y} stroke={c.lineSoft} strokeWidth="1"/>;
  });

  // Data polygon
  const dataPts = SUPPORT_FACETS.map((f, i) => {
    const v = scores[f.key] || 0;
    return pointAt(i, (v / max) * radius);
  });
  const dataPoly = dataPts.map(p => p.join(',')).join(' ');

  // Labels
  const labelR = radius + 22;
  return (
    <svg viewBox={`0 0 ${size} ${size + (labels ? 8 : 0)}`} width={size} height={size + (labels ? 8 : 0)} style={{display:'block'}}>
      {rings}
      {spokes}
      <polygon points={dataPoly} fill={fillColor} fillOpacity="0.55" stroke={strokeColor} strokeWidth="1.8" strokeLinejoin="round"/>
      {dataPts.map((p, i) => (
        <circle key={i} cx={p[0]} cy={p[1]} r={size > 140 ? 3.5 : 2.2} fill={strokeColor} stroke={c.paper} strokeWidth="1.2"/>
      ))}
      {labels && SUPPORT_FACETS.map((f, i) => {
        const [x, y] = pointAt(i, labelR);
        const anchor = Math.abs(x - cx) < 4 ? 'middle' : (x > cx ? 'start' : 'end');
        return (
          <text key={f.key} x={x} y={y + 4} fontSize={size > 220 ? 13 : 11} fill={c.inkSoft} textAnchor={anchor}
                style={{cursor: interactive ? 'pointer' : 'default', fontFamily:'var(--hl-font-body)'}}
                onMouseEnter={interactive && onFacetHover ? (()=>onFacetHover(f.key)) : undefined}
                onMouseLeave={interactive && onFacetHover ? (()=>onFacetHover(null)) : undefined}>
            {f.label}
          </text>
        );
      })}
    </svg>
  );
};

Object.assign(window, {
  Button, Tag, StatusBadge, Card, Input, Divider,
  SectionTitle, CategoryPill, GroupCard, useTokens, useIsMobile,
  SUPPORT_FACETS, RadarChart,
});
