// Componentes compartidos: chips, badges, score ring, monogram, etc.

const fmt = {
  cop(n) {
    if (n >= 1_000_000_000) return '$' + (n / 1_000_000_000).toFixed(2) + ' MM';
    if (n >= 1_000_000)     return '$' + (n / 1_000_000).toFixed(0) + ' M';
    if (n >= 1_000)         return '$' + (n / 1_000).toFixed(0) + ' k';
    return '$' + n;
  },
  copFull(n) {
    return '$ ' + n.toLocaleString('es-CO');
  },
  m2(n)  { return n + ' m²'; },
  pct(n) { return (n > 0 ? '+' : '') + n + '%'; },
  dist(m) { return m < 1000 ? m + ' m' : (m / 1000).toFixed(1) + ' km'; },
};

// Tonos del sistema
function useTheme() {
  const t = window.__bi_theme || {};
  return {
    bg:     t.dark ? '#13110F' : '#F2ECE0',
    surf:   t.dark ? '#1F1C18' : '#FFFFFF',
    surf2:  t.dark ? '#2A2620' : '#F8F3E8',
    ink:    t.dark ? '#F5EFE3' : '#1A1714',
    ink2:   t.dark ? 'rgba(245,239,227,0.62)' : 'rgba(26,23,20,0.58)',
    ink3:   t.dark ? 'rgba(245,239,227,0.32)' : 'rgba(26,23,20,0.32)',
    line:   t.dark ? 'rgba(245,239,227,0.10)' : 'rgba(26,23,20,0.08)',
    accent: t.accent || '#5A6B3F',
    warn:   '#C76E4A',
    good:   '#3F7A4E',
    bad:    '#B5482E',
    serif:  '"Instrument Serif", "Times New Roman", serif',
    sans:   '"Geist", -apple-system, system-ui, sans-serif',
    mono:   '"Geist Mono", "JetBrains Mono", ui-monospace, monospace',
    radius: t.dense ? 14 : 18,
    dense:  !!t.dense,
  };
}

// Monogram visual del inmueble (gradiente con id encima)
function PropertyImage({ p, height = 180, showBadge = true }) {
  const T = useTheme();
  const [c1, c2] = p.images;
  return (
    <div style={{
      height, borderRadius: 14, overflow: 'hidden', position: 'relative',
      background: `linear-gradient(135deg, ${c1} 0%, ${c2} 100%)`,
    }}>
      {/* striped texture overlay */}
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: `repeating-linear-gradient(135deg, rgba(255,255,255,0.06) 0 2px, transparent 2px 14px)`,
      }} />
      {/* tipografía monogramática */}
      <div style={{
        position: 'absolute', left: 14, bottom: 12,
        fontFamily: T.serif, fontSize: 28, fontWeight: 400,
        color: 'rgba(255,255,255,0.95)', lineHeight: 1, letterSpacing: 0.4,
      }}>
        {p.type[0]}{p.id.slice(-2)}
      </div>
      {showBadge && (
        <div style={{
          position: 'absolute', right: 10, top: 10,
          fontFamily: T.mono, fontSize: 10,
          padding: '4px 8px', borderRadius: 999,
          background: 'rgba(0,0,0,0.45)', color: '#fff',
          backdropFilter: 'blur(8px)', letterSpacing: 0.4,
        }}>
          {p.type.toUpperCase()}
        </div>
      )}
    </div>
  );
}

// Score ring SVG
function ScoreRing({ score, size = 56, stroke = 5, label = true }) {
  const T = useTheme();
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const off = c * (1 - score / 100);
  const col = score >= 85 ? T.accent : score >= 70 ? '#8B7B3F' : score >= 55 ? T.warn : T.bad;
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={T.line} strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={col} strokeWidth={stroke}
          strokeLinecap="round" strokeDasharray={c} strokeDashoffset={off}
          transform={`rotate(-90 ${size/2} ${size/2})`} style={{ transition: 'stroke-dashoffset 0.6s' }}/>
      </svg>
      {label && (
        <div style={{
          position: 'absolute', inset: 0, display: 'flex',
          alignItems: 'center', justifyContent: 'center',
          fontFamily: T.mono, fontSize: size * 0.32, fontWeight: 500, color: T.ink,
        }}>{score}</div>
      )}
    </div>
  );
}

// Chip
function Chip({ children, tone = 'neutral', icon }) {
  const T = useTheme();
  const map = {
    neutral: { bg: T.surf2, fg: T.ink2, bd: T.line },
    accent:  { bg: 'rgba(90,107,63,0.10)', fg: T.accent, bd: 'rgba(90,107,63,0.20)' },
    good:    { bg: 'rgba(63,122,78,0.10)', fg: T.good,   bd: 'rgba(63,122,78,0.20)' },
    warn:    { bg: 'rgba(199,110,74,0.10)', fg: T.warn,  bd: 'rgba(199,110,74,0.22)' },
    bad:     { bg: 'rgba(181,72,46,0.10)',  fg: T.bad,   bd: 'rgba(181,72,46,0.22)' },
  };
  const s = map[tone] || map.neutral;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      padding: '4px 9px', borderRadius: 999, fontSize: 11.5,
      fontFamily: T.sans, fontWeight: 500, letterSpacing: 0.1,
      background: s.bg, color: s.fg, border: `0.5px solid ${s.bd}`,
      whiteSpace: 'nowrap',
    }}>
      {icon && <span style={{ fontSize: 12 }}>{icon}</span>}
      {children}
    </span>
  );
}

// Indicador de mercado (descuento/sobreprecio)
function MarketBadge({ market, compact = false }) {
  const T = useTheme();
  if (!market) return null;
  const tone = market.pct <= -5 ? 'good' : market.pct <= 2 ? 'neutral' : market.pct <= 8 ? 'warn' : 'bad';
  const cmap = {
    good:    { fg: T.good, bg: 'rgba(63,122,78,0.10)' },
    neutral: { fg: T.ink2, bg: T.surf2 },
    warn:    { fg: T.warn, bg: 'rgba(199,110,74,0.12)' },
    bad:     { fg: T.bad,  bg: 'rgba(181,72,46,0.12)' },
  };
  const s = cmap[tone];
  const labelMap = {
    'ganga':       'Ganga',
    'descuento':   'Descuento',
    'justo':       'Precio justo',
    'sobreprecio': 'Sobreprecio',
    'caro':        'Caro',
  };
  if (compact) {
    return (
      <div style={{
        display: 'inline-flex', alignItems: 'center', gap: 4,
        padding: '3px 8px', borderRadius: 6,
        background: s.bg, color: s.fg,
        fontFamily: T.mono, fontSize: 11, fontWeight: 500,
      }}>
        {market.pct < 0 ? '▼' : market.pct > 0 ? '▲' : '='} {fmt.pct(market.pct)}
      </div>
    );
  }
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      padding: '8px 12px', borderRadius: 10,
      background: s.bg, border: `0.5px solid ${s.fg}33`,
    }}>
      <div style={{
        fontFamily: T.mono, fontSize: 16, fontWeight: 600, color: s.fg,
      }}>{fmt.pct(market.pct)}</div>
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        <div style={{ fontFamily: T.sans, fontSize: 12, fontWeight: 600, color: s.fg }}>
          {labelMap[market.verdict]}
        </div>
        <div style={{ fontFamily: T.sans, fontSize: 10.5, color: T.ink2 }}>
          vs. mercado de la zona
        </div>
      </div>
    </div>
  );
}

// Pestaña tipo segmento
function Segment({ options, value, onChange }) {
  const T = useTheme();
  return (
    <div style={{
      display: 'inline-flex', padding: 3, borderRadius: 999,
      background: T.surf2, border: `0.5px solid ${T.line}`,
    }}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)} style={{
          appearance: 'none', border: 'none', cursor: 'pointer',
          padding: '7px 16px', borderRadius: 999,
          background: o.value === value ? T.ink : 'transparent',
          color: o.value === value ? T.bg : T.ink2,
          fontFamily: T.sans, fontSize: 13, fontWeight: 500,
          letterSpacing: 0.1,
          transition: 'background 0.15s, color 0.15s',
        }}>{o.label}</button>
      ))}
    </div>
  );
}

// Botón pill
function Pill({ children, onClick, primary = false, full = false, icon }) {
  const T = useTheme();
  return (
    <button onClick={onClick} style={{
      appearance: 'none', cursor: 'pointer',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
      padding: '11px 18px', borderRadius: 999,
      width: full ? '100%' : undefined,
      background: primary ? T.ink : 'transparent',
      color: primary ? T.bg : T.ink,
      border: primary ? 'none' : `0.5px solid ${T.line}`,
      fontFamily: T.sans, fontSize: 14, fontWeight: 500, letterSpacing: 0.2,
    }}>
      {icon}{children}
    </button>
  );
}

// Mini map placeholder con pins
function MiniMap({ properties, current, onSelect, height = 280 }) {
  const T = useTheme();
  return (
    <div style={{
      position: 'relative', height, borderRadius: T.radius, overflow: 'hidden',
      background: T.surf2, border: `0.5px solid ${T.line}`,
    }}>
      {/* "calles" — líneas decorativas */}
      <svg width="100%" height="100%" style={{ position: 'absolute', inset: 0, opacity: 0.35 }}>
        <defs>
          <pattern id="grid" width="36" height="36" patternUnits="userSpaceOnUse">
            <path d="M 36 0 L 0 0 0 36" fill="none" stroke={T.ink3} strokeWidth="0.5"/>
          </pattern>
        </defs>
        <rect width="100%" height="100%" fill="url(#grid)" />
        {/* avenidas principales */}
        <line x1="0" y1="50%" x2="100%" y2="50%" stroke={T.ink3} strokeWidth="2" />
        <line x1="50%" y1="0" x2="50%" y2="100%" stroke={T.ink3} strokeWidth="2" />
        <line x1="0" y1="30%" x2="100%" y2="30%" stroke={T.ink3} strokeWidth="1" />
        <line x1="20%" y1="0" x2="20%" y2="100%" stroke={T.ink3} strokeWidth="1" />
      </svg>
      {/* TransMilenio overlay */}
      <svg width="100%" height="100%" style={{ position: 'absolute', inset: 0 }}>
        <line x1="50%" y1="0" x2="50%" y2="100%" stroke={T.warn} strokeWidth="2.5" strokeDasharray="6 4" opacity="0.6"/>
        <line x1="0" y1="50%" x2="100%" y2="50%" stroke={T.warn} strokeWidth="2.5" strokeDasharray="6 4" opacity="0.6"/>
      </svg>
      {/* pins */}
      {properties.map((entry, i) => {
        const p = entry.p || entry;
        const score = entry.score ? entry.score.total : null;
        const isActive = current === p.id;
        return (
          <button key={p.id} onClick={() => onSelect && onSelect(p.id)} style={{
            position: 'absolute',
            left: `${p.coords.x * 100}%`,
            top:  `${p.coords.y * 100}%`,
            transform: 'translate(-50%, -100%)',
            border: 'none', background: 'transparent', cursor: 'pointer', padding: 0,
            zIndex: isActive ? 10 : 1,
          }}>
            <div style={{
              padding: '4px 8px', borderRadius: 999,
              background: isActive ? T.ink : T.surf,
              color: isActive ? T.bg : T.ink,
              border: `1px solid ${isActive ? T.ink : T.line}`,
              fontFamily: T.mono, fontSize: 11, fontWeight: 600,
              boxShadow: '0 2px 6px rgba(0,0,0,0.12)',
              whiteSpace: 'nowrap',
            }}>{score !== null ? score : '•'}</div>
            <div style={{
              width: 0, height: 0, margin: '0 auto',
              borderLeft: '4px solid transparent',
              borderRight: '4px solid transparent',
              borderTop: `5px solid ${isActive ? T.ink : T.surf}`,
            }} />
          </button>
        );
      })}
      {/* leyenda */}
      <div style={{
        position: 'absolute', left: 8, bottom: 8,
        display: 'flex', gap: 6, alignItems: 'center',
        padding: '4px 8px', borderRadius: 6, background: 'rgba(255,255,255,0.85)',
        fontFamily: T.mono, fontSize: 9.5, color: T.ink2,
      }}>
        <span style={{ width: 10, height: 2, background: T.warn, display: 'inline-block' }}/>
        TransMilenio
      </div>
    </div>
  );
}

// Slider mini
function MiniSlider({ value, min, max, step = 1, onChange, label, format }) {
  const T = useTheme();
  return (
    <div style={{ width: '100%' }}>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
        marginBottom: 6,
      }}>
        <span style={{ fontFamily: T.sans, fontSize: 12, color: T.ink2 }}>{label}</span>
        <span style={{ fontFamily: T.mono, fontSize: 12, color: T.ink, fontWeight: 500 }}>
          {format ? format(value) : value}
        </span>
      </div>
      <input type="range" min={min} max={max} step={step} value={value}
        onChange={(e) => onChange(+e.target.value)}
        style={{ width: '100%', accentColor: T.accent }}/>
    </div>
  );
}

Object.assign(window, {
  fmt, useTheme, PropertyImage, ScoreRing, Chip, MarketBadge,
  Segment, Pill, MiniMap, MiniSlider,
});
