'use client';

import { useState, useEffect, useRef, useCallback } from 'react';

type Image = { id: number; filename: string; data: string; category: string; room_id: number | null; location_target: string; uploaded_at: string };
type Slide = { id: number; title: string; subtitle: string; image_url: string | null; image_id: number | null; active: boolean; sort_order: number };
type Room = { id: number; name: string; description: string; price: string; photos: string[]; featured_photo: string | null; active: boolean; sort_order: number };
type CalendarEvent = { id: number; date: string; title: string; type: string; color: string; description: string | null; active: boolean };
type SocialEvent = { id: number; name: string; description: string; price: string | null; date: string | null; photos: string[]; featured_photo: string | null; active: boolean; sort_order: number };
type MenuItem = { id: number; category: string; name: string; description: string; price: string; is_daily_special: boolean; active: boolean; sort_order: number };
type Place = { id: number; name: string; description: string; photos: string[]; featured_photo: string | null; distance_km: string; visit_time: string; suggestion: string; active: boolean; sort_order: number };
type Review = { id: number; author_name: string; author_email: string | null; rating: number; text: string; approved: boolean };
type FooterConfig = { logo: string; favicon: string; tagline: string; facebook_url: string; instagram_url: string; whatsapp_url: string; address: string; phone: string; email: string };
type SocialRes = { id: number; event_id: number; username: string; event_name: string; guests: number; notes: string; status: string; created_at: string };

const C = {
  gold: '#D4A853', goldLight: 'rgba(212,168,83,0.12)', navy: '#010D1E',
  warm: '#7A5A3A', bg: '#F7F4EF', card: '#FFFFFF', border: 'rgba(1,13,30,0.08)',
  text: '#444444', textLight: '#888888', danger: '#D32F2F', success: '#388E3C',
  shadow: '0 1px 4px rgba(1,13,30,0.06)', shadowHover: '0 6px 20px rgba(1,13,30,0.12)',
};

const NAV = [
  { id: 'brand', label: 'Brand', icon: '🎨' },
  { id: 'gallery', label: 'Images', icon: '🖼️' },
  { id: 'slides', label: 'Slideshow', icon: '🎞️' },
  { id: 'calendar', label: 'Calendar', icon: '📅' },
  { id: 'social', label: 'Social Events', icon: '🎪' },
  { id: 'rooms', label: 'Rooms', icon: '🏨' },
  { id: 'trips', label: 'Trips', icon: '✈️' },
  { id: 'messages', label: 'Messages', icon: '💬' },
  { id: 'menu', label: 'Menu', icon: '🍽️' },
  { id: 'places', label: 'Places', icon: '🗺️' },
  { id: 'reviews', label: 'Reviews', icon: '⭐' },
  { id: 'users', label: 'Users', icon: '👥' },
  { id: 'weather', label: 'Weather', icon: '🌤️' },
];

function I({ label, value, onChange, type = 'text', placeholder, style }: any) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
      {label && <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>{label}</label>}
      <input type={type} value={value ?? ''} onChange={e => onChange(e.target.value)} placeholder={placeholder}
        style={{ padding: '8px 12px', borderRadius: 8, border: `1px solid ${C.border}`, fontSize: '14px', outline: 'none', background: '#FAFAFA', ...style }}
        onFocus={e => { (e.target.style as any).borderColor = C.gold; (e.target.style as any).background = '#FFFFFF'; }}
        onBlur={e => { (e.target.style as any).borderColor = C.border; (e.target.style as any).background = '#FAFAFA'; }} />
    </div>
  );
}

function TA({ label, value, onChange, rows = 3 }: any) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
      {label && <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>{label}</label>}
      <textarea value={value ?? ''} onChange={e => onChange(e.target.value)} rows={rows}
        style={{ padding: '8px 12px', borderRadius: 8, border: `1px solid ${C.border}`, fontSize: '14px', outline: 'none', background: '#FAFAFA', resize: 'vertical', fontFamily: 'inherit' }}
        onFocus={e => { (e.target.style as any).borderColor = C.gold; (e.target.style as any).background = '#FFFFFF'; }}
        onBlur={e => { (e.target.style as any).borderColor = C.border; (e.target.style as any).background = '#FAFAFA'; }} />
    </div>
  );
}

function S({ label, value, onChange, options, style }: any) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
      {label && <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>{label}</label>}
      <select value={value ?? ''} onChange={e => onChange(e.target.value)}
        style={{ padding: '8px 12px', borderRadius: 8, border: `1px solid ${C.border}`, fontSize: '14px', outline: 'none', background: '#FAFAFA' }}>
        {options.map((o: any) => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
    </div>
  );
}

function Tgl({ label, checked, onChange }: any) {
  return (
    <label style={{ display: 'flex', alignItems: 'center', gap: '10px', cursor: 'pointer', fontSize: '14px', color: C.text }}>
      <input type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)}
        style={{ width: 18, height: 18, accentColor: C.gold, cursor: 'pointer' }} />
      {label}
    </label>
  );
}

function Btn({ children, onClick, variant = 'primary', size = 'md', disabled }: any) {
  const sz = size === 'sm' ? { padding: '5px 10px', fontSize: '12px' } : { padding: '8px 16px', fontSize: '14px' };
  const bg = variant === 'danger' ? C.danger : variant === 'secondary' ? '#E8E4DF' : C.gold;
  const color = variant === 'secondary' ? C.text : '#fff';
  return (
    <button onClick={onClick} disabled={disabled} style={{ ...sz, borderRadius: 8, border: 'none', cursor: disabled ? 'default' : 'pointer',
      background: bg, color, fontWeight: 600, opacity: disabled ? 0.5 : 1, transition: 'all 200ms' }}
      onMouseEnter={e => { if (!disabled) { e.currentTarget.style.opacity = '0.85'; e.currentTarget.style.transform = 'translateY(-1px)'; } }}
      onMouseLeave={e => { if (!disabled) { e.currentTarget.style.opacity = '1'; e.currentTarget.style.transform = 'translateY(0)'; } }}>
      {children}
    </button>
  );
}

function Badge({ children, color: c }: any) {
  return (
    <span style={{ padding: '2px 10px', borderRadius: 20, fontSize: '12px', fontWeight: 600,
      background: c || C.goldLight, color: c ? '#fff' : C.gold }}>
      {children}
    </span>
  );
}

function Toast({ message, type, onClose }: any) {
  useEffect(() => { const t = setTimeout(onClose, 3500); return () => clearTimeout(t); }, [onClose]);
  return (
    <div style={{ position: 'fixed', top: '20px', right: '20px', padding: '12px 20px', borderRadius: 12,
      background: type === 'success' ? C.success : type === 'error' ? C.danger : C.gold,
      color: '#fff', boxShadow: C.shadowHover, zIndex: 9999, fontSize: '14px', fontWeight: 500,
      display: 'flex', alignItems: 'center', gap: '10px' }}>
      {message}
      <button onClick={onClose} style={{ background: 'transparent', border: 'none', color: '#fff', cursor: 'pointer', fontSize: '18px', lineHeight: 1 }}>×</button>
    </div>
  );
}

function StatCard({ icon, value, label }: any) {
  return (
    <div style={{ background: C.card, borderRadius: 14, padding: '16px 20px', boxShadow: C.shadow,
      display: 'flex', alignItems: 'center', gap: '14px', minWidth: '160px' }}>
      <span style={{ fontSize: '28px' }}>{icon}</span>
      <div>
        <div style={{ fontSize: '22px', fontWeight: 700, color: C.navy }}>{value}</div>
        <div style={{ fontSize: '12px', color: C.textLight }}>{label}</div>
      </div>
    </div>
  );
}

function Empty({ icon, title, desc }: any) {
  return (
    <div style={{ textAlign: 'center', padding: '40px 20px', color: C.textLight }}>
      <div style={{ fontSize: '48px', marginBottom: '8px' }}>{icon}</div>
      <div style={{ fontSize: '16px', fontWeight: 600, color: C.text, marginBottom: '4px' }}>{title}</div>
      {desc && <div style={{ fontSize: '13px' }}>{desc}</div>}
    </div>
  );
}

function SecHead({ title, count, action }: any) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px', flexWrap: 'wrap', gap: '10px' }}>
      <h2 style={{ margin: 0, fontSize: '20px', fontWeight: 700, color: C.navy }}>
        {title} <span style={{ fontSize: '14px', fontWeight: 400, color: C.textLight }}>({count})</span>
      </h2>
      {action}
    </div>
  );
}

/* ─── Image helpers ─── */
function readFileBase64(file: File): Promise<string> {
  return new Promise((res, rej) => {
    const r = new FileReader();
    r.onload = () => res(r.result as string);
    r.onerror = rej;
    r.readAsDataURL(file);
  });
}

/* ─── Entity thumbnail ─── */
function Thumb({ urls, w = 200, h = 140 }: { urls: string[]; w?: number; h?: number }) {
  if (!urls?.length) return <div style={{ width: w, height: h, background: '#EEE', borderRadius: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#BBB' }}>No image</div>;
  return <img src={urls[0]} alt="" style={{ width: w, height: h, objectFit: 'cover', borderRadius: 12 }} />;
}

/* ─── Thumbnail grid (inline, small) ─── */
function MiniThumbs({ urls, max = 3 }: { urls: string[]; max?: number }) {
  if (!urls?.length) return null;
  return (
    <div style={{ display: 'flex', gap: '6px', marginTop: '8px' }}>
      {urls.slice(0, max).map((u, i) => (
        <img key={i} src={u} alt="" style={{ width: 70, height: 50, objectFit: 'cover', borderRadius: 8, cursor: 'pointer', border: '1px solid #eee' }} />
      ))}
      {urls.length > max && <span style={{ padding: '8px', background: '#EEE', borderRadius: 8, fontSize: '12px', color: '#999' }}>+{urls.length - max}</span>}
    </div>
  );
}

/* ─── Section uploader (per-section image upload) ─── */
function SectionUploader({ category, room_id, label, onUploaded }: { category: string; room_id: number | null; label: string; onUploaded?: () => void }) {
  const ref = useRef<HTMLInputElement>(null);
  return (
    <>
      <Btn onClick={() => ref.current?.click()} size="sm">{label}</Btn>
      <input ref={ref} type="file" accept="image/*" multiple style={{ display: 'none' }}
        onChange={async (e) => {
          for (const file of Array.from(e.target.files || [])) {
            const b64 = await readFileBase64(file);
            try {
              const res = await fetch('/api/admin/images', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ filename: file.name, data: b64, category, room_id, location_target: category }),
              });
              if (res.ok) onUploaded?.();
            } catch (err) { console.error(err); }
          }
          e.target.value = '';
        }} />
    </>
  );
}

/* ─── Organized image gallery with sections and borders ─── */
function ImageGallery({ images, onDelete }: { images: Image[]; onDelete: (id: number) => void }) {
  const [selectedCategory, setSelectedCategory] = useState<string>('all');
  const [hoveredCard, setHoveredCard] = useState<number | null>(null);

  const sectionCategories = [
    { key: 'slides', label: '🎞️ Slideshow Gallery', filter: (i: Image) => i.category === 'slides' || i.location_target === 'slides' },
    { key: 'calendar', label: '📅 Calendar Events Gallery', filter: (i: Image) => i.category === 'calendar' || i.location_target === 'calendar' },
    { key: 'social', label: '🎪 Social Events Gallery', filter: (i: Image) => i.category === 'social' || i.location_target === 'social' },
  ];

  // Group room images by room location_target (e.g. "room-1", "room-2")
  const roomImages = images.filter(
    (i) => i.category === 'rooms' || i.location_target?.startsWith('room-')
  );
  const roomsByNumber: Record<string, Image[]> = roomImages.reduce((acc, img) => {
    const key = img.location_target?.replace('room-', '') || 'uncategorized';
    if (!acc[key]) acc[key] = [];
    acc[key].push(img);
    return acc;
  }, {} as Record<string, Image[]>);

  const filteredImages = images.filter((img) => {
    if (selectedCategory === 'all') return true;
    if (selectedCategory === 'rooms') return img.category === 'rooms' || img.location_target?.startsWith('room-');
    return img.category === selectedCategory || img.location_target === selectedCategory;
  });

  const ImageCard = ({ img }: { img: Image }) => {
    const isHov = hoveredCard === img.id;
    return (
      <div
        style={{
          position: 'relative', borderRadius: '10px', overflow: 'hidden',
          boxShadow: isHov ? C.shadowHover : C.shadow,
          border: `1px solid ${isHov ? C.gold : C.border}`,
          transform: isHov ? 'translateY(-2px)' : 'none',
          transition: 'all 200ms ease',
          cursor: 'default',
        }}
        onMouseEnter={() => setHoveredCard(img.id)}
        onMouseLeave={() => setHoveredCard(null)}
      >
        <img
          src={img.data}
          alt={img.filename}
          style={{
            width: '100%', height: '110px', objectFit: 'cover', display: 'block',
          }}
        />
        <div style={{
          padding: '6px 8px', fontSize: '11px', color: C.text,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          background: C.card,
        }}>
          {img.filename}
        </div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', padding: '4px' }}>
          <button
            onClick={(e) => { e.stopPropagation(); onDelete(img.id); }}
            style={{
              width: '24px', height: '24px', borderRadius: '6px',
              border: '1px solid rgba(211,47,47,0.2)',
              background: isHov ? 'rgba(211,47,47,0.15)' : 'transparent',
              color: C.danger, fontSize: '14px', cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              transition: 'all 200ms',
            }}
          >
            ×
          </button>
        </div>
        {/* Category label overlay on hover */}
        {isHov && img.location_target && (
          <div style={{
            position: 'absolute', bottom: '30px', left: '4px', right: '4px',
            padding: '3px 6px', fontSize: '10px', color: '#fff',
            background: 'rgba(1,13,30,0.75)', borderRadius: '4px',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            textAlign: 'center',
          }}>
            {img.location_target}
          </div>
        )}
      </div>
    );
  };

  const SectionBox = ({ title, count, children }: { title: string; count: number; children: React.ReactNode }) => (
    <div style={{
      borderRadius: '12px', overflow: 'hidden',
      border: `1px solid ${C.border}`, background: '#fff',
      boxShadow: C.shadow,
    }}>
      <div style={{
        padding: '10px 16px',
        background: C.goldLight,
        borderBottom: `1px solid ${C.border}`,
        fontWeight: 700, color: C.navy, fontSize: '14px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <span>{title}</span>
        <span style={{
          fontSize: '11px', padding: '2px 10px', borderRadius: '999px',
          background: C.success, color: '#fff', fontWeight: 600,
        }}>{count}</span>
      </div>
      <div style={{ padding: '16px' }}>
        {children}
      </div>
    </div>
  );

  return (
    <div>
      {/* Category filter bar with borders */}
      <div style={{
        display: 'flex', gap: '8px', marginBottom: '20px', flexWrap: 'wrap',
        padding: '12px 16px', borderRadius: '12px',
        border: `1px solid ${C.border}`, background: '#fff',
        boxShadow: C.shadow,
      }}>
        {['all', 'slides', 'calendar', 'social', 'rooms', 'other'].map((cat) => (
          <Btn
            key={cat}
            onClick={() => setSelectedCategory(cat)}
            variant={selectedCategory === cat ? 'primary' : 'secondary'}
            size="sm"
          >
            {cat === 'all' ? 'All Images' : cat.charAt(0).toUpperCase() + cat.slice(1)}
          </Btn>
        ))}
      </div>

      {selectedCategory === 'all' ? (
        <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
          {/* Static sections */}
          {sectionCategories.map((section) => {
            const imgs = images.filter(section.filter);
            if (imgs.length === 0) return null;
            return (
              <SectionBox key={section.key} title={section.label} count={imgs.length}>
                <div style={{
                  display: 'grid',
                  gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',
                  gap: '12px',
                }}>
                  {imgs.map((img) => <ImageCard key={img.id} img={img} />)}
                </div>
              </SectionBox>
            );
          })}

          {/* Rooms section with room number subdivision */}
          {Object.keys(roomsByNumber).length > 0 && (
            <SectionBox title="🏨 Rooms Gallery" count={roomImages.length}>
              <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
                {Object.entries(roomsByNumber).map(([roomKey, imgs]) => (
                  <div key={roomKey}>
                    <div style={{
                      display: 'flex', alignItems: 'center', gap: '8px',
                      marginBottom: '10px', padding: '8px 12px',
                      background: '#FAFAFA', borderRadius: '8px',
                      border: `1px solid ${C.border}`,
                    }}>
                      <span style={{ fontSize: '13px', fontWeight: 600, color: C.navy }}>
                        🛏️ Room {roomKey}
                      </span>
                      <span style={{
                        fontSize: '11px', padding: '2px 8px', borderRadius: '999px',
                        background: C.goldLight, color: C.gold, fontWeight: 600,
                      }}>{imgs.length} photo{imgs.length !== 1 ? 's' : ''}</span>
                    </div>
                    <div style={{
                      display: 'grid',
                      gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',
                      gap: '12px',
                    }}>
                      {imgs.map((img) => <ImageCard key={img.id} img={img} />)}
                    </div>
                  </div>
                ))}
              </div>
            </SectionBox>
          )}

          {/* Uncategorized/other */}
          {(() => {
            const otherImages = images.filter(
              (i) => !sectionCategories.some(s => s.filter(i)) &&
                     !(i.category === 'rooms' || i.location_target?.startsWith('room-'))
            );
            if (otherImages.length === 0) return null;
            return (
              <SectionBox title="📁 Uncategorized" count={otherImages.length}>
                <div style={{
                  display: 'grid',
                  gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',
                  gap: '12px',
                }}>
                  {otherImages.map((img) => <ImageCard key={img.id} img={img} />)}
                </div>
              </SectionBox>
            );
          })()}
        </div>
      ) : (
        <SectionBox title={
          selectedCategory === 'rooms' ? '🏨 Rooms' :
          selectedCategory === 'other' ? '📁 Other' :
          selectedCategory.charAt(0).toUpperCase() + selectedCategory.slice(1)
        } count={filteredImages.length}>
          {filteredImages.length === 0 ? (
            <div style={{ padding: '40px 20px', textAlign: 'center', color: C.textLight }}>
              No images in this category
            </div>
          ) : (
            <div style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',
              gap: '12px',
            }}>
              {filteredImages.map((img) => <ImageCard key={img.id} img={img} />)}
            </div>
          )}
        </SectionBox>
      )}
    </div>
  );
}

/* ─── Entity card ─── */

/* ─── Entity card ─── */
function EntityCard({ title, desc, meta, thumb, actions, photoUrls }: any) {
  return (
    <div style={{ background: C.card, borderRadius: 16, overflow: 'hidden', boxShadow: C.shadow, transition: 'all 200ms', border: `1px solid ${C.border}` }}
      onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = C.shadowHover; }}
      onMouseLeave={e => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = C.shadow; }}>
      {thumb ? (
        <img src={thumb} alt="" style={{ width: '100%', height: 140, objectFit: 'cover' }} />
      ) : photoUrls?.length ? <Thumb urls={photoUrls} /> : <div style={{ height: 100, background: '#EEE', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#CCC' }}>📷</div>}
      <div style={{ padding: '14px 16px' }}>
        <div style={{ fontWeight: 700, color: C.navy, fontSize: '15px', marginBottom: '4px' }}>{title}</div>
        {desc && <div style={{ fontSize: '13px', color: C.text, lineHeight: 1.4, marginBottom: '6px', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{desc}</div>}
        {meta && <div style={{ fontSize: '12px', color: C.textLight, marginBottom: '10px' }}>{meta}</div>}
        {photoUrls?.length ? <MiniThumbs urls={photoUrls} /> : null}
        {actions && <div style={{ display: 'flex', gap: '8px', marginTop: '12px' }}>{actions}</div>}
      </div>
    </div>
  );
}

/* ─── Confirm dialog ─── */
function Confirm({ message, onConfirm, onCancel }: any) {
  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 360, width: '90%', boxShadow: '0 20px 60px rgba(0,0,0,0.2)' }}>
        <p style={{ margin: '0 0 20px', fontSize: '15px', color: C.text }}>{message}</p>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={onConfirm} variant="danger">Delete</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Slides Section ─── */
function SlidesSection({ slides, setSlides, images, onToast, onRefreshImages }: any) {
  const [editing, setEditing] = useState<Slide | null>(null);
  const [confirmDel, setConfirmDel] = useState<number | null>(null);

  const saveSlide = async (slide: Slide) => {
    try {
      const url = slide.id ? `/api/slides/${slide.id}` : '/api/slides';
      const res = await fetch(url, {
        method: slide.id ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(slide),
      });
      if (res.ok) {
        const data = await res.json();
        setEditing(null);
        setSlides((s: any) => slide.id ? s.map((x: Slide) => x.id === slide.id ? data.data : x) : [...s, data.data]);
        onToast('Slide saved!', 'success');
      }
    } catch { onToast('Error saving slide', 'error'); }
  };

  const delSlide = async (id: number) => {
    try {
      await fetch(`/api/slides/${id}`, { method: 'DELETE' });
      setSlides((s: any) => s.filter((x: Slide) => x.id !== id));
      onToast('Slide deleted', 'success');
    } catch { onToast('Error deleting slide', 'error'); }
    setConfirmDel(null);
  };

  return (
    <div>
      <SecHead title="🎞️ Slideshow" count={slides.length}
        action={<Btn onClick={() => setEditing({ id: 0, title: '', subtitle: '', image_url: null, image_id: null, active: true, sort_order: slides.length })} size="sm">+ New Slide</Btn>} />
      {slides.length === 0 ? <Empty icon="🎞️" title="No slides yet" /> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '16px' }}>
          {slides.map((s: Slide) => (
            <EntityCard key={s.id} title={s.title} desc={s.subtitle} meta={s.active ? 'Active' : 'Inactive'}
              thumb={s.image_url || s.image_id ? (images.find((i: Image) => i.id === s.image_id)?.data) : null}
              actions={
                <>
                  <Btn size="sm" variant="secondary" onClick={() => setEditing(s)}>Edit</Btn>
                  <Btn size="sm" variant="danger" onClick={() => setConfirmDel(s.id)}>Del</Btn>
                </>
              } />
          ))}
        </div>
      )}
      {editing && (
        <SlideEditor slide={editing} setSlide={setEditing} images={images} onRefreshImages={onRefreshImages} onSave={saveSlide} onCancel={() => setEditing(null)} />
      )}
      {confirmDel !== null && <Confirm message="Delete this slide?" onCancel={() => setConfirmDel(null)} onConfirm={() => delSlide(confirmDel)} />}
    </div>
  );
}

function SlideEditor({ slide, setSlide, images, onRefreshImages, onSave, onCancel }: any) {
  const [showPicker, setShowPicker] = useState(false);
  const [uploading, setUploading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const s = { ...slide };
  
  const handleUpload = async (files: FileList) => {
    setUploading(true);
    try {
      for (const file of Array.from(files)) {
        const b64 = await readFileBase64(file);
        const res = await fetch('/api/admin/images', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ filename: file.name, data: b64, category: 'slides', room_id: null, location_target: 'slides' }),
        });
        if (res.ok) {
          const data = await res.json();
          onRefreshImages?.();
          setSlide({ ...s, image_id: data.data.id, image_url: data.data.data });
        }
      }
    } catch (err) {
      console.error('Upload failed:', err);
    } finally {
      setUploading(false);
    }
  };
  
  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 500, width: '90%', maxHeight: '90vh', overflowY: 'auto' }}>
        <h3 style={{ margin: '0 0 20px', fontSize: '18px', fontWeight: 700, color: C.navy }}>{s.id ? 'Edit Slide' : 'New Slide'}</h3>
        <div style={{ display: 'grid', gap: '14px' }}>
          <I label="Title" value={s.title} onChange={(v: string) => setSlide({ ...s, title: v })} />
          <I label="Subtitle" value={s.subtitle} onChange={(v: string) => setSlide({ ...s, subtitle: v })} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
            <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>Image</label>
            <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
              <Btn onClick={() => setShowPicker(!showPicker)} size="sm" variant="secondary">{showPicker ? 'Hide picker' : 'Pick from gallery'}</Btn>
              <input ref={fileInputRef} type="file" accept="image/*" style={{ display: 'none' }} onChange={(e) => { if (e.target.files?.length) handleUpload(e.target.files); e.target.value = ''; }} />
              <Btn size="sm" variant="secondary" disabled={uploading} onClick={() => fileInputRef.current?.click()}>{uploading ? 'Uploading...' : 'Upload from computer'}</Btn>
              {s.image_id && images.find((i: Image) => i.id === s.image_id) && (
                <img src={images.find((i: Image) => i.id === s.image_id)!.data} style={{ width: 80, height: 56, objectFit: 'cover', borderRadius: 8, border: `2px solid ${C.gold}` }} />
              )}
            </div>
            {showPicker && (
              <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap', padding: '8px', background: '#FAFAFA', borderRadius: 8 }}>
                {images.filter((i: Image) => i.category === 'slides').map((img: Image) => (
                  <img key={img.id} src={img.data} alt="" onClick={() => { setSlide({ ...s, image_id: img.id, image_url: img.data }); setShowPicker(false); }}
                    style={{ width: 64, height: 48, objectFit: 'cover', borderRadius: 6, cursor: 'pointer', border: s.image_id === img.id ? `2px solid ${C.gold}` : '1px solid #eee' }} />
                ))}
                {images.filter((i: Image) => i.category === 'slides').length === 0 && <span style={{ fontSize: '12px', color: C.textLight, padding: '8px' }}>No images uploaded. Use "Upload from computer" above.</span>}
              </div>
            )}
          </div>
          <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
            <Tgl label="Active" checked={s.active} onChange={(v: boolean) => setSlide({ ...s, active: v })} />
            <I label="Sort Order" type="number" value={s.sort_order} onChange={(v: string) => setSlide({ ...s, sort_order: Number(v) })} style={{ width: 80 }} />
          </div>
        </div>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '24px' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={() => onSave(s)}>Save</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Calendar Section ─── */
function CalendarSection({ events, setEvents, images, onToast }: any) {
  const [editing, setEditing] = useState<CalendarEvent | null>(null);
  const [confirmDel, setConfirmDel] = useState<number | null>(null);

  const save = async (ev: CalendarEvent) => {
    try {
      const url = ev.id ? `/api/calendar_events/${ev.id}` : '/api/calendar_events';
      const res = await fetch(url, {
        method: ev.id ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(ev),
      });
      if (res.ok) {
        const data = await res.json();
        setEditing(null);
        setEvents((e: any) => ev.id ? e.map((x: CalendarEvent) => x.id === ev.id ? data.data : x) : [...e, data.data]);
        onToast('Event saved!', 'success');
      }
    } catch { onToast('Error', 'error'); }
  };

  const del = async (id: number) => {
    await fetch(`/api/calendar_events/${id}`, { method: 'DELETE' });
    setEvents((e: any) => e.filter((x: CalendarEvent) => x.id !== id));
    onToast('Event deleted', 'success');
    setConfirmDel(null);
  };

  return (
    <div>
      <SecHead title="📅 Calendar Events" count={events.length}
        action={<Btn onClick={() => setEditing({ id: 0, date: '', title: '', type: 'default', color: '#D4A853', description: null, active: true })} size="sm">+ New Event</Btn>} />
      {events.length === 0 ? <Empty icon="📅" title="No events" /> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: '16px' }}>
          {events.map((ev: CalendarEvent) => (
            <EntityCard key={ev.id} title={ev.title} desc={ev.description || ev.type} meta={`${ev.date} • ${ev.type}`}
              actions={
                <>
                  <Btn size="sm" variant="secondary" onClick={() => setEditing(ev)}>Edit</Btn>
                  <Btn size="sm" variant="danger" onClick={() => setConfirmDel(ev.id)}>Del</Btn>
                </>
              } />
          ))}
        </div>
      )}
      {editing && <CalendarEditor event={editing} setEvent={setEditing} onSave={save} onCancel={() => setEditing(null)} />}
      {confirmDel !== null && <Confirm message="Delete this event?" onCancel={() => setConfirmDel(null)} onConfirm={() => del(confirmDel)} />}
    </div>
  );
}

function CalendarEditor({ event, setEvent, onSave, onCancel }: any) {
  const e = { ...event };
  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 460, width: '90%' }}>
        <h3 style={{ margin: '0 0 20px', fontSize: '18px', fontWeight: 700, color: C.navy }}>{e.id ? 'Edit Event' : 'New Event'}</h3>
        <div style={{ display: 'grid', gap: '14px' }}>
          <I label="Title" value={e.title} onChange={(v: string) => setEvent({ ...e, title: v })} />
          <I label="Date" type="date" value={e.date} onChange={(v: string) => setEvent({ ...e, date: v })} />
          <S label="Type" value={e.type} onChange={(v: string) => setEvent({ ...e, type: v })}
            options={[{ value: 'default', label: 'Default' }, { value: 'special', label: 'Special' }, { value: 'holiday', label: 'Holiday' }]} />
          <I label="Color" value={e.color} onChange={(v: string) => setEvent({ ...e, color: v })} />
          <TA label="Description" value={e.description || ''} onChange={(v: string) => setEvent({ ...e, description: v || null })} />
          <Tgl label="Active" checked={e.active} onChange={(v: boolean) => setEvent({ ...e, active: v })} />
        </div>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '24px' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={() => onSave(e)}>Save</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Social Events Section ─── */
function SocialSection({ events, setEvents, images, onToast }: any) {
  const [editing, setEditing] = useState<SocialEvent | null>(null);
  const [confirmDel, setConfirmDel] = useState<number | null>(null);

  const save = async (ev: SocialEvent) => {
    try {
      const url = ev.id ? `/api/social_events/${ev.id}` : '/api/social_events';
      const res = await fetch(url, {
        method: ev.id ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(ev),
      });
      if (res.ok) {
        const data = await res.json();
        setEditing(null);
        setEvents((e: any) => ev.id ? e.map((x: SocialEvent) => x.id === ev.id ? data.data : x) : [...e, data.data]);
        onToast('Event saved!', 'success');
      }
    } catch { onToast('Error', 'error'); }
  };

  const del = async (id: number) => {
    await fetch(`/api/social_events/${id}`, { method: 'DELETE' });
    setEvents((e: any) => e.filter((x: SocialEvent) => x.id !== id));
    onToast('Event deleted', 'success');
    setConfirmDel(null);
  };

  return (
    <div>
      <SecHead title="🎪 Social Events" count={events.length}
        action={<Btn onClick={() => setEditing({ id: 0, name: '', description: '', price: null, date: null, photos: [], featured_photo: null, active: true, sort_order: events.length })} size="sm">+ New Event</Btn>} />
      {events.length === 0 ? <Empty icon="🎪" title="No social events" /> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '16px' }}>
          {events.map((ev: SocialEvent) => (
            <EntityCard key={ev.id} title={ev.name} desc={ev.description || ''} meta={`${ev.price || 'Free'}${ev.date ? ' • ' + ev.date : ''}`}
              thumb={ev.featured_photo || ev.photos?.[0]}
              photoUrls={ev.photos}
              actions={
                <>
                  <Btn size="sm" variant="secondary" onClick={() => setEditing(ev)}>Edit</Btn>
                  <Btn size="sm" variant="danger" onClick={() => setConfirmDel(ev.id)}>Del</Btn>
                </>
              } />
          ))}
        </div>
      )}
      {editing && <SocialEditor event={editing} setEvent={setEditing} images={images} onSave={save} onCancel={() => setEditing(null)} />}
      {confirmDel !== null && <Confirm message="Delete this event?" onCancel={() => setConfirmDel(null)} onConfirm={() => del(confirmDel)} />}
    </div>
  );
}

function SocialEditor({ event, setEvent, images, onSave, onCancel }: any) {
  const [showPicker, setShowPicker] = useState(false);
  const [localPhotos, setLocalPhotos] = useState<string[]>(event.photos || []);
  const ev = { ...event, photos: localPhotos };

  const addPhotos = async (files: FileList) => {
    const newPhotos: string[] = [];
    for (const f of Array.from(files)) {
      const b64 = await readFileBase64(f);
      try {
        const r = await fetch('/api/admin/images', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ filename: f.name, data: b64, category: 'social', room_id: null, location_target: 'social' }),
        });
        if (r.ok) { const d = await r.json(); newPhotos.push(d.data.data); }
      } catch { const b = await readFileBase64(f); newPhotos.push(b); }
    }
    setLocalPhotos(prev => [...prev, ...newPhotos]);
  };

  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 500, width: '90%', maxHeight: '90vh', overflowY: 'auto' }}>
        <h3 style={{ margin: '0 0 20px', fontSize: '18px', fontWeight: 700, color: C.navy }}>{ev.id ? 'Edit Event' : 'New Event'}</h3>
        <div style={{ display: 'grid', gap: '14px' }}>
          <I label="Name" value={ev.name} onChange={(v: string) => setEvent({ ...ev, name: v })} />
          <TA label="Description" value={ev.description || ''} onChange={(v: string) => setEvent({ ...ev, description: v })} />
          <I label="Price" value={ev.price || ''} onChange={(v: string) => setEvent({ ...ev, price: v || null })} />
          <I label="Date" type="date" value={ev.date || ''} onChange={(v: string) => setEvent({ ...ev, date: v || null })} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
            <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>Photos</label>
            <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
              <Btn onClick={() => document.getElementById('social-photos')?.click()} size="sm" variant="secondary">+ Add Photos</Btn>
              <input id="social-photos" type="file" accept="image/*" multiple style={{ display: 'none' }}
                onChange={e => { addPhotos(e.target.files!); e.target.value = ''; }} />
            </div>
            <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
              {localPhotos.map((p, i) => (
                <div key={i} style={{ position: 'relative' }}>
                  <img src={p} alt="" style={{ width: 64, height: 48, objectFit: 'cover', borderRadius: 6, border: '1px solid #eee' }} />
                  <button onClick={() => setLocalPhotos(prev => prev.filter((_, j) => j !== i))}
                    style={{ position: 'absolute', top: -4, right: -4, width: 18, height: 18, borderRadius: '50%', background: C.danger, color: '#fff', border: 'none', cursor: 'pointer', fontSize: '11px', lineHeight: 18, padding: 0 }}
                  >×</button>
                </div>
              ))}
            </div>
          </div>
          <Tgl label="Active" checked={ev.active} onChange={(v: boolean) => setEvent({ ...ev, active: v })} />
        </div>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '24px' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={() => onSave(ev)}>Save</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Rooms Section ─── */
function RoomsSection({ rooms, setRooms, images, onToast }: any) {
  const [editing, setEditing] = useState<Room | null>(null);
  const [confirmDel, setConfirmDel] = useState<number | null>(null);

  const save = async (room: Room) => {
    try {
      const url = room.id ? `/api/rooms/${room.id}` : '/api/rooms';
      const res = await fetch(url, {
        method: room.id ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(room),
      });
      if (res.ok) {
        const data = await res.json();
        setEditing(null);
        setRooms((r: any) => room.id ? r.map((x: Room) => x.id === room.id ? data.data : x) : [...r, data.data]);
        onToast('Room saved!', 'success');
      }
    } catch { onToast('Error', 'error'); }
  };

  const del = async (id: number) => {
    await fetch(`/api/rooms/${id}`, { method: 'DELETE' });
    setRooms((r: any) => r.filter((x: Room) => x.id !== id));
    onToast('Room deleted', 'success');
    setConfirmDel(null);
  };

  return (
    <div>
      <SecHead title="🏨 Rooms" count={rooms.length}
        action={<Btn onClick={() => setEditing({ id: 0, name: '', description: '', price: '', photos: [], featured_photo: null, active: true, sort_order: rooms.length })} size="sm">+ New Room</Btn>} />
      {rooms.length === 0 ? <Empty icon="🏨" title="No rooms" /> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '16px' }}>
          {rooms.map((r: Room) => (
            <EntityCard key={r.id} title={r.name} desc={r.description || ''} meta={r.price}
              thumb={r.featured_photo || r.photos?.[0]}
              photoUrls={r.photos}
              actions={
                <>
                  <Btn size="sm" variant="secondary" onClick={() => setEditing(r)}>Edit</Btn>
                  <Btn size="sm" variant="danger" onClick={() => setConfirmDel(r.id)}>Del</Btn>
                </>
              } />
          ))}
        </div>
      )}
      {editing && <RoomEditor room={editing} setRoom={setEditing} images={images} onSave={save} onCancel={() => setEditing(null)} />}
      {confirmDel !== null && <Confirm message="Delete this room?" onCancel={() => setConfirmDel(null)} onConfirm={() => del(confirmDel)} />}
    </div>
  );
}

function RoomEditor({ room, setRoom, images, onSave, onCancel }: any) {
  const [showPicker, setShowPicker] = useState(false);
  const [localPhotos, setLocalPhotos] = useState<string[]>(room.photos || []);
  const r = { ...room, photos: localPhotos };

  const addPhotos = async (files: FileList) => {
    const newPhotos: string[] = [];
    for (const f of Array.from(files)) {
      const b64 = await readFileBase64(f);
      try {
        const res = await fetch('/api/admin/images', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ filename: f.name, data: b64, category: 'rooms', room_id: r.id || null, location_target: `room-${r.id || 'new'}` }),
        });
        if (res.ok) { const d = await res.json(); newPhotos.push(d.data.data); }
      } catch { const b = await readFileBase64(f); newPhotos.push(b); }
    }
    setLocalPhotos(prev => [...prev, ...newPhotos]);
  };

  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 500, width: '90%', maxHeight: '90vh', overflowY: 'auto' }}>
        <h3 style={{ margin: '0 0 20px', fontSize: '18px', fontWeight: 700, color: C.navy }}>{r.id ? 'Edit Room' : 'New Room'}</h3>
        <div style={{ display: 'grid', gap: '14px' }}>
          <I label="Name" value={r.name} onChange={(v: string) => setRoom({ ...r, name: v })} />
          <TA label="Description" value={r.description || ''} onChange={(v: string) => setRoom({ ...r, description: v })} />
          <I label="Price" value={r.price} onChange={(v: string) => setRoom({ ...r, price: v })} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
            <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>Photos</label>
            <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
              <Btn onClick={() => document.getElementById(`room-photos-${r.id}`)?.click()} size="sm" variant="secondary">+ Add Photos</Btn>
              <input id={`room-photos-${r.id}`} type="file" accept="image/*" multiple style={{ display: 'none' }}
                onChange={e => { addPhotos(e.target.files!); e.target.value = ''; }} />
            </div>
            <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
              {localPhotos.map((p, i) => (
                <div key={i} style={{ position: 'relative' }}>
                  <img src={p} alt="" style={{ width: 64, height: 48, objectFit: 'cover', borderRadius: 6, border: '1px solid #eee' }} />
                  <button onClick={() => setLocalPhotos(prev => prev.filter((_, j) => j !== i))}
                    style={{ position: 'absolute', top: -4, right: -4, width: 18, height: 18, borderRadius: '50%', background: C.danger, color: '#fff', border: 'none', cursor: 'pointer', fontSize: '11px', lineHeight: 18, padding: 0 }}>×</button>
                </div>
              ))}
            </div>
          </div>
          <Tgl label="Active" checked={r.active} onChange={(v: boolean) => setRoom({ ...r, active: v })} />
        </div>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '24px' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={() => onSave(r)}>Save</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Trips Section ─── */
type Trip = { id: number; user_id: number; username: string; room_id: number | null; room_name: string | null; check_in: string; check_out: string; notes: string | null; status: string };

function TripsSection({ onToast }: { onToast: (msg: string, type: string) => void }) {
  const [trips, setTrips] = useState<Trip[]>([]);
  const [users, setUsers] = useState<{id: number; username: string}[]>([]);
  const [rooms, setRooms] = useState<{id: number; name: string}[]>([]);
  const [editing, setEditing] = useState<Trip | null>(null);
  const [creating, setCreating] = useState(false);

  useEffect(() => {
    const load = async () => {
      const [tripsRes, usersRes, roomsRes] = await Promise.all([
        fetch('/api/admin/trips'),
        fetch('/api/admin/users'),
        fetch('/api/rooms'),
      ]);
      if (tripsRes.ok) { const d = await tripsRes.json(); setTrips(d.trips || []); }
      if (usersRes.ok) { const d = await usersRes.json(); setUsers(d.users || []); }
      if (roomsRes.ok) { const d = await roomsRes.json(); setRooms(Array.isArray(d) ? d : (d.data || [])); }
    };
    load();
  }, []);

  const save = async (trip: Trip) => {
    try {
      const method = trip.id ? 'PUT' : 'POST';
      const res = await fetch('/api/admin/trips', {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(trip),
      });
      if (res.ok) {
        const d = await res.json();
        if (trip.id) {
          setTrips(prev => prev.map(t => t.id === trip.id ? d.trip : t));
        } else {
          setTrips(prev => [...prev, d.trip]);
        }
        setEditing(null);
        setCreating(false);
        onToast('Trip saved', 'success');
      } else {
        const err = await res.json();
        onToast(err.error || 'Failed to save trip', 'error');
      }
    } catch { onToast('Error saving trip', 'error'); }
  };

  const del = async (id: number) => {
    if (!confirm('Delete this trip?')) return;
    try {
      await fetch('/api/admin/trips', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id }) });
      setTrips(prev => prev.filter(t => t.id !== id));
      onToast('Trip deleted', 'success');
    } catch { onToast('Error deleting trip', 'error'); }
  };

  const emptyTrip: Trip = { id: 0, user_id: 0, username: '', room_id: null, room_name: null, check_in: '', check_out: '', notes: '', status: 'confirmed' };

  return (
    <div>
      <SecHead title="✈️ Trips" count={trips.length} onAdd={() => { setCreating(true); setEditing(emptyTrip); }} />
      {creating && editing && !editing.id && (
        <div style={{ background: '#fff', borderRadius: 12, padding: '20px', marginBottom: '20px', boxShadow: C.shadow }}>
          <h3 style={{ margin: '0 0 16px', fontSize: '16px' }}>New Trip</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '12px' }}>
            <S label="User" value={editing.user_id} onChange={(v: string) => setEditing({ ...editing, user_id: Number(v) })} options={[{ value: 0, label: 'Select user' }, ...users.map(u => ({ value: u.id, label: u.username }))]} />
            <S label="Room" value={editing.room_id || ''} onChange={(v: string) => setEditing({ ...editing, room_id: v ? Number(v) : null })} options={[{ value: '', label: 'No room' }, ...rooms.map(r => ({ value: r.id, label: r.name }))]} />
            <I label="Check-in" type="date" value={editing.check_in} onChange={(v: string) => setEditing({ ...editing, check_in: v })} />
            <I label="Check-out" type="date" value={editing.check_out} onChange={(v: string) => setEditing({ ...editing, check_out: v })} />
            <S label="Status" value={editing.status} onChange={(v: string) => setEditing({ ...editing, status: v })} options={['pending', 'confirmed', 'checked_in', 'checked_out', 'cancelled'].map(s => ({ value: s, label: s.replace('_', ' ') }))} />
          </div>
          <TA label="Notes" value={editing.notes || ''} onChange={(v: string) => setEditing({ ...editing, notes: v })} rows={2} />
          <div style={{ display: 'flex', gap: '8px', marginTop: '16px' }}>
            <Btn onClick={() => save(editing)}>Save Trip</Btn>
            <Btn variant="secondary" onClick={() => { setCreating(false); setEditing(null); }}>Cancel</Btn>
          </div>
        </div>
      )}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
        {trips.map(t => (
          <div key={t.id} style={{ background: '#fff', borderRadius: 12, padding: '16px', boxShadow: C.shadow, display: 'flex', alignItems: 'center', gap: '16px', flexWrap: 'wrap' }}>
            <div style={{ flex: '1 1 200px' }}>
              <div style={{ fontWeight: 600, color: C.navy }}>{t.username || `User ${t.user_id}`}</div>
              <div style={{ fontSize: '13px', color: C.textLight }}>{t.room_name || 'No room assigned'}</div>
            </div>
            <div style={{ fontSize: '13px', color: C.text }}>
              <strong>In:</strong> {new Date(t.check_in).toLocaleDateString()} · <strong>Out:</strong> {new Date(t.check_out).toLocaleDateString()}
            </div>
            <Badge color={t.status === 'confirmed' ? C.success : t.status === 'checked_in' ? '#1976d2' : t.status === 'cancelled' ? C.danger : '#666'}>{t.status.replace('_', ' ')}</Badge>
            <div style={{ display: 'flex', gap: '8px' }}>
              <Btn size="sm" onClick={() => { setCreating(false); setEditing(t); }}>Edit</Btn>
              <Btn size="sm" variant="danger" onClick={() => del(t.id)}>Delete</Btn>
            </div>
          </div>
        ))}
      </div>
      {!creating && editing && editing.id && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000 }} onClick={() => setEditing(null)}>
          <div style={{ background: '#fff', borderRadius: 12, padding: '24px', maxWidth: '500px', width: '90%' }} onClick={e => e.stopPropagation()}>
            <h3 style={{ margin: '0 0 16px' }}>Edit Trip</h3>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
              <S label="User" value={editing.user_id} onChange={(v: string) => setEditing({ ...editing, user_id: Number(v) })} options={[{ value: 0, label: 'Select user' }, ...users.map(u => ({ value: u.id, label: u.username }))]} />
              <S label="Room" value={editing.room_id || ''} onChange={(v: string) => setEditing({ ...editing, room_id: v ? Number(v) : null })} options={[{ value: '', label: 'No room' }, ...rooms.map(r => ({ value: r.id, label: r.name }))]} />
              <I label="Check-in" type="date" value={editing.check_in} onChange={(v: string) => setEditing({ ...editing, check_in: v })} />
              <I label="Check-out" type="date" value={editing.check_out} onChange={(v: string) => setEditing({ ...editing, check_out: v })} />
              <S label="Status" value={editing.status} onChange={(v: string) => setEditing({ ...editing, status: v })} options={['pending', 'confirmed', 'checked_in', 'checked_out', 'cancelled'].map(s => ({ value: s, label: s.replace('_', ' ') }))} />
            </div>
            <TA label="Notes" value={editing.notes || ''} onChange={(v: string) => setEditing({ ...editing, notes: v })} rows={2} />
            <div style={{ display: 'flex', gap: '8px', marginTop: '16px' }}>
              <Btn onClick={() => save(editing)}>Save</Btn>
              <Btn variant="secondary" onClick={() => setEditing(null)}>Cancel</Btn>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ─── Messages Section ─── */
type MsgThread = { user_id: number; username: string; message: string; created_at: string };
type Msg = { id: number; sender_role: string; message: string; created_at: string };

function MessagesSection({ onToast }: { onToast: (msg: string, type: string) => void }) {
  const [threads, setThreads] = useState<MsgThread[]>([]);
  const [selectedUser, setSelectedUser] = useState<number | null>(null);
  const [messages, setMessages] = useState<Msg[]>([]);
  const [reply, setReply] = useState('');
  const messagesEndRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const load = async () => {
      const res = await fetch('/api/admin/messages');
      if (res.ok) { const d = await res.json(); setThreads(d.threads || []); }
    };
    load();
  }, []);

  useEffect(() => {
    if (selectedUser) {
      const load = async () => {
        const res = await fetch(`/api/admin/messages?user_id=${selectedUser}`);
        if (res.ok) { const d = await res.json(); setMessages(d.messages || []); }
      };
      load();
    }
  }, [selectedUser]);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  const sendReply = async () => {
    if (!reply.trim() || !selectedUser) return;
    try {
      const res = await fetch('/api/admin/messages', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ user_id: selectedUser, message: reply.trim() }),
      });
      if (res.ok) {
        const d = await res.json();
        setMessages(prev => [...prev, d.message]);
        setReply('');
        onToast('Reply sent', 'success');
      }
    } catch { onToast('Error sending reply', 'error'); }
  };

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '300px 1fr', gap: '20px', minHeight: '400px' }}>
      <div style={{ background: '#fff', borderRadius: 12, overflow: 'hidden', boxShadow: C.shadow }}>
        <div style={{ padding: '16px', borderBottom: `1px solid ${C.border}`, fontWeight: 600, color: C.navy }}>Conversations</div>
        <div style={{ maxHeight: '400px', overflowY: 'auto' }}>
          {threads.length === 0 ? (
            <div style={{ padding: '20px', textAlign: 'center', color: C.textLight }}>No conversations yet</div>
          ) : (
            threads.map(t => (
              <div key={t.user_id} onClick={() => setSelectedUser(t.user_id)} style={{ padding: '12px 16px', cursor: 'pointer', background: selectedUser === t.user_id ? C.goldLight : 'transparent', borderBottom: `1px solid ${C.border}` }}
                onMouseEnter={e => { if (selectedUser !== t.user_id) (e.currentTarget.style as any).background = '#f5f5f5'; }}
                onMouseLeave={e => { if (selectedUser !== t.user_id) (e.currentTarget.style as any).background = 'transparent'; }}>
                <div style={{ fontWeight: 500, color: C.navy }}>{t.username}</div>
                <div style={{ fontSize: '12px', color: C.textLight, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{t.message}</div>
              </div>
            ))
          )}
        </div>
      </div>
      <div style={{ background: '#fff', borderRadius: 12, overflow: 'hidden', boxShadow: C.shadow, display: 'flex', flexDirection: 'column' }}>
        {selectedUser ? (
          <>
            <div style={{ padding: '16px', borderBottom: `1px solid ${C.border}`, fontWeight: 600, color: C.navy }}>
              {threads.find(t => t.user_id === selectedUser)?.username || `User ${selectedUser}`}
            </div>
            <div style={{ flex: 1, overflowY: 'auto', padding: '16px', maxHeight: '300px' }}>
              {messages.map(m => (
                <div key={m.id} style={{ display: 'flex', justifyContent: m.sender_role === 'admin' ? 'flex-start' : 'flex-end', marginBottom: '12px' }}>
                  <div style={{ maxWidth: '70%', padding: '10px 14px', borderRadius: 12, background: m.sender_role === 'admin' ? C.gold : '#f0f0f0', color: m.sender_role === 'admin' ? '#fff' : C.navy }}>
                    <div style={{ fontSize: '12px', fontWeight: 500, marginBottom: '4px' }}>{m.sender_role === 'admin' ? 'Staff' : 'Guest'}</div>
                    <div style={{ fontSize: '14px' }}>{m.message}</div>
                    <div style={{ fontSize: '11px', opacity: 0.7, marginTop: '4px' }}>{new Date(m.created_at).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}</div>
                  </div>
                </div>
              ))}
              <div ref={messagesEndRef} />
            </div>
            <div style={{ padding: '12px', borderTop: `1px solid ${C.border}`, display: 'flex', gap: '8px' }}>
              <input value={reply} onChange={e => setReply(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') sendReply(); }} placeholder="Type a reply..." style={{ flex: 1, padding: '10px 14px', borderRadius: 8, border: `1px solid ${C.border}`, fontSize: '14px', outline: 'none' }} />
              <Btn onClick={sendReply} disabled={!reply.trim()}>Send</Btn>
            </div>
          </>
        ) : (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: C.textLight }}>Select a conversation to view messages</div>
        )}
      </div>
    </div>
  );
}

/* ─── Menu Section ─── */
function MenuSection({ items, setItems, images, onToast }: any) {
  const [editing, setEditing] = useState<MenuItem | null>(null);
  const [confirmDel, setConfirmDel] = useState<number | null>(null);
  const [dragIdx, setDragIdx] = useState<number | null>(null);
  const [overIdx, setOverIdx] = useState<number | null>(null);

  const save = async (item: MenuItem) => {
    if (!item.category || !item.name || !item.price) {
      onToast('Category, name, and price are required', 'error');
      return;
    }
    try {
      const url = item.id ? `/api/menu/${item.id}` : '/api/menu/';
      const res = await fetch(url, {
        method: item.id ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(item),
      });
      if (res.ok) {
        const data = await res.json();
        setEditing(null);
        if (item.id) {
          setItems((i: any) => i.map((x: any) => x.id === item.id ? data.data : x));
        } else {
          setItems((i: any) => [...i, data.data]);
        }
        onToast('Menu item saved!', 'success');
      } else {
        const err = await res.json().catch(() => ({}));
        onToast(err.error || 'Failed to save menu item', 'error');
      }
    } catch { onToast('Error', 'error'); }
  };

  const del = async (id: number) => {
    await fetch(`/api/menu/${id}`, { method: 'DELETE' });
    setItems((i: any) => i.filter((x: any) => x.id !== id));
    onToast('Item deleted', 'success');
    setConfirmDel(null);
  };

  const toggleVisible = async (item: MenuItem) => {
    const updated = { ...item, active: !item.active };
    try {
      await fetch(`/api/menu/${item.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ...item, active: updated.active }),
      });
      setItems((i: any) => i.map((x: any) => x.id === item.id ? updated : x));
    } catch { onToast('Error', 'error'); }
  };

  // ─── Drag-and-drop reordering ───
  const handleDragStart = (idx: number) => { setDragIdx(idx); };

  const handleDragOver = (e: any, idx: number) => {
    e.preventDefault();
    if (dragIdx !== null && dragIdx !== idx) setOverIdx(idx);
  };

  const handleDragEnd = () => {
    if (dragIdx !== null && overIdx !== null && dragIdx !== overIdx) {
      const reordered = [...items];
      const [moved] = reordered.splice(dragIdx, 1);
      reordered.splice(overIdx, 0, moved);
      setItems(reordered);
      setItems(reordered);
    }
    setDragIdx(null);
    setOverIdx(null);
  };

  const saveOrder = async () => {
    try {
      await fetch('/api/menu/reorder', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ order: items.map((it: MenuItem, i: number) => ({ id: it.id, sort_order: i })) }),
      });
      onToast('Order saved!', 'success');
    } catch { onToast('Error reordering', 'error'); }
  };

  const sorted = [...items].sort((a, b) => (a.sort_order || 0) - (b.sort_order || 0));

  return (
    <div>
      <SecHead title="🍽️ Menu" count={items.length}
        action={<Btn onClick={() => setEditing({ id: 0, category: '', name: '', description: '', price: '', is_daily_special: false, active: true, sort_order: items.length })} size="sm">+ New Item</Btn>} />
      {sorted.length === 0 ? <Empty icon="🍽️" title="No menu items" /> : (
        <div style={{ background: C.card, borderRadius: 16, overflow: 'hidden', boxShadow: C.shadow }}>
          {/* Drag handle instruction */}
          <div style={{ padding: '8px 16px', background: C.goldLight, fontSize: '12px', color: C.textLight, display: 'flex', alignItems: 'center', gap: '8px' }}>
            <span>⠿</span> Drag items to reorder · Toggle visibility to hide from the public site
          </div>

          {sorted.map((item: MenuItem, idx: number) => {
            const isDragging = dragIdx === idx;
            const isOver = overIdx === idx && dragIdx !== idx;
            return (
              <div
                key={item.id}
                draggable
                onDragStart={(e: any) => { e.dataTransfer!.effectAllowed = 'move'; handleDragStart(idx); }}
                onDragOver={(e) => handleDragOver(e, idx)}
                onDragEnd={handleDragEnd}
                onDragEnter={() => setOverIdx(idx)}
                style={{
                  display: 'flex',
                  alignItems: 'center',
                  gap: '12px',
                  padding: '12px 16px',
                  border: isOver ? `2px dashed ${C.gold}` : idx === 0 ? 'none' : `1px solid ${C.border}`,
                  borderTop: isDragging ? `2px dashed ${C.gold}` : 'none',
                  background: isDragging ? 'rgba(212,168,83,0.06)' : isOver ? C.goldLight : idx % 2 === 0 ? '#fff' : '#FAFAFA',
                  opacity: isDragging ? 0.5 : 1,
                  cursor: 'grab',
                  transition: 'all 150ms ease',
                  borderRadius: idx === 0 ? '0' : '0',
                }}
                onMouseEnter={(e) => {
                  if (!isDragging) e.currentTarget.style.background = C.goldLight;
                }}
                onMouseLeave={(e) => {
                  if (!isDragging && !isOver) e.currentTarget.style.background = idx % 2 === 0 ? '#fff' : '#FAFAFA';
                }}
              >
                {/* Drag handle */}
                <span style={{ fontSize: '18px', color: C.textLight, userSelect: 'none', flexShrink: 0, cursor: 'grab' }}
                  onMouseDown={() => {}}>⠿</span>

                {/* Position number */}
                <span style={{ fontSize: '13px', fontWeight: 700, color: C.textLight, width: '22px', textAlign: 'center', flexShrink: 0 }}>
                  {idx + 1}
                </span>

                {/* Visible/invisible toggle */}
                <label style={{ display: 'flex', alignItems: 'center', gap: '6px', cursor: 'pointer', flexShrink: 0 }}
                  onClick={(e) => { e.stopPropagation(); toggleVisible(item); }}>
                  <div style={{
                    width: '42px', height: '24px', borderRadius: '12px', position: 'relative',
                    background: item.active ? C.success : '#ccc',
                    transition: 'background 200ms',
                    flexShrink: 0,
                  }}>
                    <div style={{
                      width: '20px', height: '20px', borderRadius: '50%', background: '#fff',
                      position: 'absolute', top: '2px',
                      left: item.active ? '20px' : '2px',
                      transition: 'left 200ms',
                      boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
                    }} />
                  </div>
                  <span style={{ fontSize: '12px', color: item.active ? C.success : C.textLight, fontWeight: 600, minWidth: '24px' }}>
                    {item.active ? 'On' : 'Off'}
                  </span>
                </label>

                {/* Category badge */}
                <span style={{
                  fontSize: '11px', fontWeight: 700, padding: '3px 8px', borderRadius: 6,
                  background: C.navy, color: '#fff', flexShrink: 0,
                }}>{item.category}</span>

                {/* Name & Description */}
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 600, color: C.navy, fontSize: '14px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                    {item.name}
                  </div>
                  {item.description && (
                    <div style={{ fontSize: '12px', color: C.textLight, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                      {item.description}
                    </div>
                  )}
                </div>

                {/* Price */}
                <span style={{ fontWeight: 700, color: C.warm, fontSize: '14px', flexShrink: 0 }}>
                  {item.price}
                </span>

                {/* Actions */}
                <div style={{ display: 'flex', gap: '6px', flexShrink: 0 }}>
                  <Btn size="sm" variant="secondary" onClick={() => setEditing(item)} style={{ fontSize: '11px', padding: '3px 8px' }}>✏️</Btn>
                  <Btn size="sm" variant="danger" onClick={() => setConfirmDel(item.id)} style={{ fontSize: '11px', padding: '3px 8px' }}>🗑️</Btn>
                </div>
              </div>
            );
          })}

          {/* Save order button */}
          <div style={{ padding: '12px 16px', borderTop: `1px solid ${C.border}`, display: 'flex', justifyContent: 'flex-end' }}>
            <Btn onClick={saveOrder} size="sm">💾 Save Order</Btn>
          </div>
        </div>
      )}
      {editing && <MenuEditor item={editing} setItem={setEditing} onSave={save} onCancel={() => setEditing(null)} />}
      {confirmDel !== null && <Confirm message="Delete this menu item?" onCancel={() => setConfirmDel(null)} onConfirm={() => del(confirmDel)} />}
    </div>
  );
}

function MenuEditor({ item, setItem, onSave, onCancel }: any) {
  const i = { ...item };
  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 460, width: '90%' }}>
        <h3 style={{ margin: '0 0 20px', fontSize: '18px', fontWeight: 700, color: C.navy }}>{i.id ? 'Edit Item' : 'New Item'}</h3>
        <div style={{ display: 'grid', gap: '14px' }}>
          <I label="Category" value={i.category} onChange={(v: string) => setItem({ ...i, category: v })} />
          <I label="Name" value={i.name} onChange={(v: string) => setItem({ ...i, name: v })} />
          <TA label="Description" value={i.description || ''} onChange={(v: string) => setItem({ ...i, description: v })} />
          <I label="Price" value={i.price} onChange={(v: string) => setItem({ ...i, price: v })} />
          <Tgl label="Daily Special" checked={i.is_daily_special} onChange={(v: boolean) => setItem({ ...i, is_daily_special: v })} />
          <Tgl label="Active" checked={i.active} onChange={(v: boolean) => setItem({ ...i, active: v })} />
        </div>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '24px' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={() => onSave(i)}>Save</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Places Section ─── */
function PlacesSection({ places, setPlaces, images, onToast }: any) {
  const [editing, setEditing] = useState<Place | null>(null);
  const [confirmDel, setConfirmDel] = useState<number | null>(null);

  const save = async (place: Place) => {
    try {
      const url = place.id ? `/api/places/${place.id}` : '/api/places';
      const res = await fetch(url, {
        method: place.id ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(place),
      });
      if (res.ok) {
        const data = await res.json();
        setEditing(null);
        setPlaces((p: any) => place.id ? p.map((x: Place) => x.id === place.id ? data.data : x) : [...p, data.data]);
        onToast('Place saved!', 'success');
      }
    } catch { onToast('Error', 'error'); }
  };

  const del = async (id: number) => {
    await fetch(`/api/places/${id}`, { method: 'DELETE' });
    setPlaces((p: any) => p.filter((x: Place) => x.id !== id));
    onToast('Place deleted', 'success');
    setConfirmDel(null);
  };

  return (
    <div>
      <SecHead title="🗺️ Landscape Places" count={places.length}
        action={<Btn onClick={() => setEditing({ id: 0, name: '', description: '', photos: [], featured_photo: null, distance_km: '', visit_time: '', suggestion: '', active: true, sort_order: places.length })} size="sm">+ New Place</Btn>} />
      {places.length === 0 ? <Empty icon="🗺️" title="No places" /> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '16px' }}>
          {places.map((p: Place) => (
            <EntityCard key={p.id} title={p.name} desc={p.description || ''} meta={`${p.distance_km || ''} ${p.visit_time ? '• ' + p.visit_time : ''}`}
              thumb={p.featured_photo || p.photos?.[0]}
              photoUrls={p.photos}
              actions={
                <>
                  <Btn size="sm" variant="secondary" onClick={() => setEditing(p)}>Edit</Btn>
                  <Btn size="sm" variant="danger" onClick={() => setConfirmDel(p.id)}>Del</Btn>
                </>
              } />
          ))}
        </div>
      )}
      {editing && <PlaceEditor place={editing} setPlace={setEditing} images={images} onSave={save} onCancel={() => setEditing(null)} />}
      {confirmDel !== null && <Confirm message="Delete this place?" onCancel={() => setConfirmDel(null)} onConfirm={() => del(confirmDel)} />}
    </div>
  );
}

function PlaceEditor({ place, setPlace, images, onSave, onCancel }: any) {
  const [localPhotos, setLocalPhotos] = useState<string[]>(place.photos || []);
  const p = { ...place, photos: localPhotos };

  const addPhotos = async (files: FileList) => {
    const newPhotos: string[] = [];
    for (const f of Array.from(files)) {
      const b64 = await readFileBase64(f);
      try {
        const res = await fetch('/api/admin/images', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ filename: f.name, data: b64, category: 'landscape', room_id: null, location_target: `place-${p.id || 'new'}` }),
        });
        if (res.ok) { const d = await res.json(); newPhotos.push(d.data.data); }
      } catch { const b = await readFileBase64(f); newPhotos.push(b); }
    }
    setLocalPhotos(prev => [...prev, ...newPhotos]);
  };

  return (
    <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
      <div style={{ background: '#FFFFFF', borderRadius: 16, padding: '24px 28px', maxWidth: 500, width: '90%', maxHeight: '90vh', overflowY: 'auto' }}>
        <h3 style={{ margin: '0 0 20px', fontSize: '18px', fontWeight: 700, color: C.navy }}>{p.id ? 'Edit Place' : 'New Place'}</h3>
        <div style={{ display: 'grid', gap: '14px' }}>
          <I label="Name" value={p.name} onChange={(v: string) => setPlace({ ...p, name: v })} />
          <TA label="Description" value={p.description || ''} onChange={(v: string) => setPlace({ ...p, description: v })} />
          <I label="Distance (km)" value={p.distance_km} onChange={(v: string) => setPlace({ ...p, distance_km: v })} />
          <I label="Visit Time" value={p.visit_time} onChange={(v: string) => setPlace({ ...p, visit_time: v })} />
          <TA label="Suggestion" value={p.suggestion || ''} onChange={(v: string) => setPlace({ ...p, suggestion: v })} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
            <label style={{ fontSize: '13px', fontWeight: 600, color: C.text }}>Photos</label>
            <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
              <Btn onClick={() => document.getElementById(`place-photos-${p.id}`)?.click()} size="sm" variant="secondary">+ Add Photos</Btn>
              <input id={`place-photos-${p.id}`} type="file" accept="image/*" multiple style={{ display: 'none' }}
                onChange={e => { addPhotos(e.target.files!); e.target.value = ''; }} />
            </div>
            <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
              {localPhotos.map((ph, i) => (
                <div key={i} style={{ position: 'relative' }}>
                  <img src={ph} alt="" style={{ width: 64, height: 48, objectFit: 'cover', borderRadius: 6, border: '1px solid #eee' }} />
                  <button onClick={() => setLocalPhotos(prev => prev.filter((_, j) => j !== i))}
                    style={{ position: 'absolute', top: -4, right: -4, width: 18, height: 18, borderRadius: '50%', background: C.danger, color: '#fff', border: 'none', cursor: 'pointer', fontSize: '11px', lineHeight: 18, padding: 0 }}>×</button>
                </div>
              ))}
            </div>
          </div>
          <Tgl label="Active" checked={p.active} onChange={(v: boolean) => setPlace({ ...p, active: v })} />
        </div>
        <div style={{ display: 'flex', gap: '10px', justifyContent: 'flex-end', marginTop: '24px' }}>
          <Btn onClick={onCancel} variant="secondary">Cancel</Btn>
          <Btn onClick={() => onSave(p)}>Save</Btn>
        </div>
      </div>
    </div>
  );
}

/* ─── Reviews Section ─── */
function ReviewsSection({ reviews, setReviews, onToast }: any) {
  const approve = async (id: number) => {
    try {
      await fetch(`/api/reviews/${id}`, {
        method: 'PUT', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ approved: true }),
      });
      setReviews((r: any) => r.map((x: Review) => x.id === id ? { ...x, approved: true } : x));
      onToast('Review approved!', 'success');
    } catch { onToast('Error', 'error'); }
  };

  const reject = async (id: number) => {
    try {
      await fetch(`/api/reviews/${id}`, {
        method: 'PUT', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ approved: false }),
      });
      setReviews((r: any) => r.map((x: Review) => x.id === id ? { ...x, approved: false } : x));
      onToast('Review hidden', 'success');
    } catch { onToast('Error', 'error'); }
  };

  return (
    <div>
      <SecHead title="⭐ Reviews" count={reviews.length} />
      {reviews.length === 0 ? <Empty icon="⭐" title="No reviews" /> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: '16px' }}>
          {reviews.map((r: Review) => (
            <div key={r.id} style={{ background: C.card, borderRadius: 16, padding: '16px 20px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' }}>
                <span style={{ fontWeight: 700, color: C.navy }}>{r.author_name}</span>
                <Badge color={r.approved ? C.success : '#FF9800'}>{r.approved ? 'Approved' : 'Pending'}</Badge>
              </div>
              <div style={{ fontSize: '14px', color: '#FFB400', marginBottom: '8px', letterSpacing: 2 }}>
                {'★'.repeat(r.rating)}{'☆'.repeat(5 - r.rating)}
              </div>
              <p style={{ margin: '0 0 12px', fontSize: '13px', color: C.text, lineHeight: 1.5 }}>{r.text}</p>
              <div style={{ display: 'flex', gap: '8px' }}>
                {!r.approved && <Btn size="sm" variant="secondary" onClick={() => approve(r.id)}>Approve</Btn>}
                {r.approved && <Btn size="sm" variant="secondary" onClick={() => reject(r.id)}>Hide</Btn>}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ─── Brand Section ─── */
function BrandSection({ images, onToast }: { images: Image[]; onToast: (m: string, t: string) => void }) {
  const [config, setConfig] = useState<FooterConfig>({
    logo: '', favicon: '', tagline: 'Tu refugio en la naturaleza',
    facebook_url: '', instagram_url: '', whatsapp_url: '',
    address: '', phone: '', email: '',
  });
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    loadConfig();
  }, []);

  const loadConfig = async () => {
    try {
      const res = await fetch('/api/site-assets');
      if (res.ok) {
        const data = await res.json();
        if (data.data) {
          setConfig(prev => ({ ...prev, ...data.data }));
        }
      }
    } catch (err) {
      console.error('Failed to load config:', err);
    } finally {
      setLoading(false);
    }
  };

  const handleUpload = async (key: keyof FooterConfig) => {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    input.onchange = async (e) => {
      const file = (e.target as HTMLInputElement).files?.[0];
      if (!file) return;
      const b64 = await readFileBase64(file);
      try {
        const res = await fetch('/api/admin/images', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ filename: file.name, data: b64, category: 'other', room_id: null, location_target: key }),
        });
        if (res.ok) {
          const d = await res.json();
          setConfig(prev => ({ ...prev, [key]: d.data.data }));
          onToast('Image uploaded!', 'success');
        }
      } catch { onToast('Upload failed', 'error'); }
    };
    input.click();
  };

  const saveConfig = async () => {
    setSaving(true);
    try {
      const res = await fetch('/api/site-assets', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ values: config }),
      });
      if (res.ok) {
        onToast('Configuration saved!', 'success');
      } else {
        onToast('Failed to save', 'error');
      }
    } catch {
      onToast('Failed to save', 'error');
    } finally {
      setSaving(false);
    }
  };

  if (loading) return <div style={{ padding: 20, color: C.textLight }}>Loading...</div>;

  return (
    <div>
      <SecHead title="🎨 Brand & Identity" />
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: '20px' }}>
        {(['logo', 'favicon'] as (keyof FooterConfig)[]).map(key => (
          <div key={key} style={{ background: C.card, borderRadius: 16, padding: '20px', boxShadow: C.shadow, textAlign: 'center', border: `1px solid ${C.border}` }}>
            <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '12px', textTransform: 'capitalize' }}>{key}</div>
            {config[key] ? (
              <img src={config[key] as string} alt={key} style={{ width: 120, height: 80, objectFit: 'contain', borderRadius: 8, marginBottom: '12px' }} />
            ) : (
              <div style={{ width: 120, height: 80, background: '#EEE', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#BBB', margin: '0 auto 12px' }}>
                No {key}
              </div>
            )}
            <Btn onClick={() => handleUpload(key)} size="sm" variant="secondary">Upload</Btn>
          </div>
        ))}
        <div style={{ background: C.card, borderRadius: 16, padding: '20px', boxShadow: C.shadow, border: `1px solid ${C.border}`, gridColumn: 'span 2' }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '12px' }}>Tagline</div>
          <I value={config.tagline} onChange={(v: string) => setConfig(prev => ({ ...prev, tagline: v }))} placeholder="Your hotel tagline" />
        </div>
      </div>

      <SecHead title="📞 Contact & Social" />
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '16px', marginBottom: 20 }}>
        <div style={{ background: C.card, borderRadius: 16, padding: '16px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '8px' }}>📍 Address</div>
          <I value={config.address} onChange={(v: string) => setConfig(prev => ({ ...prev, address: v }))} placeholder="Full address" />
        </div>
        <div style={{ background: C.card, borderRadius: 16, padding: '16px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '8px' }}>📞 Phone</div>
          <I value={config.phone} onChange={(v: string) => setConfig(prev => ({ ...prev, phone: v }))} placeholder="+593 99 999 9999" />
        </div>
        <div style={{ background: C.card, borderRadius: 16, padding: '16px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '8px' }}>✉️ Email</div>
          <I value={config.email} onChange={(v: string) => setConfig(prev => ({ ...prev, email: v }))} placeholder="contact@lahuasca.com" />
        </div>
        <div style={{ background: C.card, borderRadius: 16, padding: '16px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '8px' }}>📘 Facebook URL</div>
          <I value={config.facebook_url} onChange={(v: string) => setConfig(prev => ({ ...prev, facebook_url: v }))} placeholder="https://facebook.com/..." />
        </div>
        <div style={{ background: C.card, borderRadius: 16, padding: '16px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '8px' }}>📷 Instagram URL</div>
          <I value={config.instagram_url} onChange={(v: string) => setConfig(prev => ({ ...prev, instagram_url: v }))} placeholder="https://instagram.com/..." />
        </div>
        <div style={{ background: C.card, borderRadius: 16, padding: '16px', boxShadow: C.shadow, border: `1px solid ${C.border}` }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: C.text, marginBottom: '8px' }}>💬 WhatsApp URL</div>
          <I value={config.whatsapp_url} onChange={(v: string) => setConfig(prev => ({ ...prev, whatsapp_url: v }))} placeholder="https://wa.me/..." />
        </div>
      </div>

      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '16px' }}>
        <Btn onClick={saveConfig} disabled={saving}>{saving ? 'Saving...' : '💾 Save Configuration'}</Btn>
      </div>
    </div>
  );
}

/* ─── Dashboard (stats cards) ─── */
function Dashboard({ rooms, slides, events, reviews, places }: any) {
  return (
    <div>
      <h2 style={{ margin: '0 0 20px', fontSize: '22px', fontWeight: 700, color: C.navy }}>Dashboard</h2>
      <div style={{ display: 'flex', gap: '14px', flexWrap: 'wrap', marginBottom: '24px' }}>
        <StatCard icon="🏨" value={rooms?.length || 0} label="Rooms" />
        <StatCard icon="🎞️" value={slides?.length || 0} label="Slides" />
        <StatCard icon="📅" value={events?.length || 0} label="Events" />
        <StatCard icon="🗺️" value={places?.length || 0} label="Places" />
        <StatCard icon="⭐" value={reviews?.filter((r: Review) => r.approved)?.length || 0} label="Approved Reviews" />
      </div>
    </div>
  );
}

/* ─── Users Section ─── */
function UsersSection({ onToast }: { onToast: (msg: string, type: string) => void }) {
  const [users, setUsers] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState<any | null>(null);
  const [newUser, setNewUser] = useState({ username: '', password: '', role: 'user' });
  const [showAdd, setShowAdd] = useState(false);

  useEffect(() => {
    loadUsers();
  }, []);

  const loadUsers = async () => {
    try {
      const res = await fetch('/api/admin/users');
      if (res.ok) {
        const data = await res.json();
        setUsers(data.data || []);
      }
    } catch (err) {
      console.error('Failed to load users:', err);
    } finally {
      setLoading(false);
    }
  };

  const createUser = async () => {
    if (!newUser.username || !newUser.password) {
      onToast('Username and password required', 'error');
      return;
    }
    try {
      const res = await fetch('/api/admin/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(newUser),
      });
      if (res.ok) {
        onToast('User created!', 'success');
        setNewUser({ username: '', password: '', role: 'user' });
        setShowAdd(false);
        loadUsers();
      } else {
        const err = await res.json();
        onToast(err.error || 'Failed to create user', 'error');
      }
    } catch {
      onToast('Error creating user', 'error');
    }
  };

  const updateUser = async (user: any) => {
    try {
      const res = await fetch('/api/admin/users', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(user),
      });
      if (res.ok) {
        onToast('User updated!', 'success');
        setEditing(null);
        loadUsers();
      } else {
        const err = await res.json();
        onToast(err.error || 'Failed to update user', 'error');
      }
    } catch {
      onToast('Error updating user', 'error');
    }
  };

  const deleteUser = async (id: number) => {
    try {
      const res = await fetch(`/api/admin/users?id=${id}`, { method: 'DELETE' });
      if (res.ok) {
        onToast('User deleted', 'success');
        loadUsers();
      }
    } catch {
      onToast('Error deleting user', 'error');
    }
  };

  if (loading) {
    return <div style={{ textAlign: 'center', padding: '40px' }}>Loading...</div>;
  }

  return (
    <div>
      <SecHead title="👥 Users" count={users.length}
        action={<Btn onClick={() => setShowAdd(!showAdd)} size="sm">+ Add User</Btn>} />
      {showAdd && (
        <div style={{ background: C.card, borderRadius: 12, padding: 16, marginBottom: 16 }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 12 }}>
            <I label="Username" value={newUser.username} onChange={(v: string) => setNewUser({ ...newUser, username: v })} />
            <I label="Password" type="password" value={newUser.password} onChange={(v: string) => setNewUser({ ...newUser, password: v })} />
            <div>
              <label style={{ fontSize: 13, fontWeight: 600, color: C.text, display: 'block', marginBottom: 6 }}>Role</label>
              <select value={newUser.role} onChange={(e) => setNewUser({ ...newUser, role: e.target.value })}
                style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: `1px solid ${C.border}`, fontSize: 14 }}>
                <option value="user">User</option>
                <option value="admin">Admin</option>
              </select>
            </div>
          </div>
          <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>
            <Btn onClick={createUser} size="sm">Create User</Btn>
            <Btn variant="secondary" onClick={() => setShowAdd(false)} size="sm">Cancel</Btn>
          </div>
        </div>
      )}
      <div style={{ display: 'grid', gap: '12px' }}>
        {users.map((u: any) => (
          <div key={u.id} style={{ background: C.card, borderRadius: 12, padding: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div>
              <div style={{ fontWeight: 600, color: C.text }}>{u.username} <span style={{ fontSize: 12, background: u.role === 'admin' ? '#dc2626' : '#059669', color: '#fff', padding: '2px 8px', borderRadius: 4, marginLeft: 8 }}>{u.role}</span></div>
              <div style={{ fontSize: 12, color: C.textLight }}>{u.first_name || ''} {u.last_name || ''} {u.comments_disabled ? '• Comments disabled' : ''}</div>
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <Btn size="sm" variant="secondary" onClick={() => setEditing(u)}>Edit</Btn>
            </div>
          </div>
        ))}
      </div>
      {editing && (
        <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9998 }}>
          <div style={{ background: '#fff', borderRadius: 16, padding: 24, maxWidth: 400, width: '90%' }}>
            <h3 style={{ margin: '0 0 20px', fontSize: 18, fontWeight: 700 }}>Edit User</h3>
            <div style={{ display: 'grid', gap: 12 }}>
              <I label="First Name" value={editing.first_name || ''} onChange={(v: string) => setEditing({ ...editing, first_name: v })} />
              <I label="Last Name" value={editing.last_name || ''} onChange={(v: string) => setEditing({ ...editing, last_name: v })} />
              <I label="New Password (leave blank to keep current)" type="password" value={editing.password || ''} onChange={(v: string) => setEditing({ ...editing, password: v })} placeholder="Enter new password to change" />
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <input type="checkbox" checked={editing.comments_disabled || false} onChange={(e) => setEditing({ ...editing, comments_disabled: e.target.checked })} />
                <label style={{ fontSize: 13, color: C.text }}>Disable comments</label>
              </div>
            </div>
            <div style={{ marginTop: 16, display: 'flex', gap: 8 }}>
              <Btn onClick={() => updateUser(editing)} size="sm">Save</Btn>
              <Btn variant="secondary" onClick={() => setEditing(null)} size="sm">Cancel</Btn>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ─── Weather Section ─── */
function WeatherSection({ onToast }: { onToast: (msg: string, type: string) => void }) {
  const [enabled, setEnabled] = useState(true);
  const [cities, setCities] = useState<{ name: string; lat: string; lon: string }[]>([]);
  const [newCity, setNewCity] = useState({ name: '', lat: '', lon: '' });
  const [loading, setLoading] = useState(true);

  // Load weather config
  useEffect(() => {
    const loadConfig = async () => {
      try {
        const res = await fetch('/api/site-assets?key=weather_config');
        if (res.ok) {
          const data = await res.json();
          if (data.data) {
            const config = JSON.parse(data.data);
            setEnabled(config.enabled ?? true);
            setCities(config.cities ?? []);
          }
        }
      } catch (err) {
        console.error('Failed to load weather config:', err);
      } finally {
        setLoading(false);
      }
    };
    loadConfig();
  }, []);

  const saveConfig = async () => {
    try {
      const config = { enabled, cities };
      const res = await fetch('/api/site-assets', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ key: 'weather_config', value: JSON.stringify(config) }),
      });
      
      if (res.ok) {
        onToast('Weather settings saved', 'success');
      } else {
        throw new Error('Failed to save');
      }
    } catch (err) {
      onToast('Error saving weather settings', 'error');
    }
  };

  const addCity = () => {
    if (newCity.name && newCity.lat && newCity.lon) {
      setCities([...cities, newCity]);
      setNewCity({ name: '', lat: '', lon: '' });
    }
  };

  const removeCity = (index: number) => {
    setCities(cities.filter((_, i) => i !== index));
  };

  if (loading) {
    return (
      <div>
        <SecHead title="🌤️ Weather Widget" />
        <div style={{ textAlign: 'center', padding: '40px', color: C.textLight }}>
          Loading...
        </div>
      </div>
    );
  }

  return (
    <div>
      <SecHead title="🌤️ Weather Widget" />
      <div style={{ background: C.card, borderRadius: 12, padding: '24px', marginBottom: '24px', border: `1px solid ${C.border}` }}>
        <p style={{ color: C.text, marginBottom: '24px' }}>
          Configure the weather widget displayed on the homepage
        </p>
        
        <div style={{ marginBottom: '24px' }}>
          <label style={{ display: 'flex', alignItems: 'center', gap: '8px', cursor: 'pointer' }}>
            <input 
              type="checkbox" 
              checked={enabled} 
              onChange={(e) => setEnabled(e.target.checked)}
              style={{ width: '18px', height: '18px' }}
            />
            <span style={{ fontWeight: 500, color: C.text }}>Enable Weather Widget</span>
          </label>
        </div>
        
        <h3 style={{ margin: '0 0 16px', color: C.text, fontSize: '16px' }}>Cities</h3>
        <div style={{ marginBottom: '16px' }}>
          {cities.map((city, index) => (
            <div key={index} style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '8px', padding: '8px', background: C.bg, borderRadius: '8px' }}>
              <span style={{ flex: 1, color: C.text }}>{city.name} ({city.lat}, {city.lon})</span>
              <button 
                onClick={() => removeCity(index)}
                style={{ 
                  background: C.danger, 
                  color: 'white', 
                  border: 'none', 
                  borderRadius: '4px', 
                  padding: '4px 8px', 
                  cursor: 'pointer',
                  fontSize: '12px'
                }}
              >
                Remove
              </button>
            </div>
          ))}
        </div>
        
        <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', padding: '16px', background: C.bg, borderRadius: '8px' }}>
          <h4 style={{ margin: '0 0 8px', color: C.text, fontSize: '14px' }}>Add City</h4>
          <I label="City Name" value={newCity.name} onChange={(v: string) => setNewCity({...newCity, name: v})} />
          <div style={{ display: 'flex', gap: '12px' }}>
            <I label="Latitude" value={newCity.lat} onChange={(v: string) => setNewCity({...newCity, lat: v})} />
            <I label="Longitude" value={newCity.lon} onChange={(v: string) => setNewCity({...newCity, lon: v})} />
          </div>
          <button 
            onClick={addCity}
            style={{ 
              alignSelf: 'flex-start',
              background: C.gold, 
              color: 'white', 
              border: 'none', 
              borderRadius: '6px', 
              padding: '8px 16px', 
              cursor: 'pointer',
              fontWeight: 500
            }}
          >
            Add City
          </button>
        </div>
        
        <div style={{ marginTop: '24px' }}>
          <button 
            onClick={saveConfig}
            style={{ 
              background: C.gold, 
              color: 'white', 
              border: 'none', 
              borderRadius: '6px', 
              padding: '12px 24px', 
              cursor: 'pointer',
              fontWeight: 600,
              fontSize: '14px'
            }}
          >
            Save Settings
          </button>
        </div>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════
   MAIN PAGE
   ═══════════════════════════════════════════════════ */
export default function AdminPage() {
  const [activeSection, setActiveSection] = useState('dashboard');
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [toasts, setToasts] = useState<{ id: number; message: string; type: string }[]>([]);
  const [authChecked, setAuthChecked] = useState(false);
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  const [slides, setSlides] = useState<Slide[]>([]);
  const [rooms, setRooms] = useState<Room[]>([]);
  const [events, setEvents] = useState<CalendarEvent[]>([]);
  const [socialEvents, setSocialEvents] = useState<SocialEvent[]>([]);
  const [menuItems, setMenuItems] = useState<MenuItem[]>([]);
  const [places, setPlaces] = useState<Place[]>([]);
  const [reviews, setReviews] = useState<Review[]>([]);
  const [images, setImages] = useState<Image[]>([]);

  const [imageFilter, setImageFilter] = useState('all');
  const [galleryLoading, setGalleryLoading] = useState(false);

  const toastId = useRef(0);
  const showToast = useCallback((message: string, type: string) => {
    const id = ++toastId.current;
    setToasts(prev => [...prev, { id, message, type }]);
  }, []);

  const removeToast = useCallback((id: number) => {
    setToasts(prev => prev.filter(t => t.id !== id));
  }, []);

  /* ── Auth check ── */
  useEffect(() => {
    fetch('/api/auth/me', { credentials: 'include' })
      .then(r => r.json())
      .then(data => {
        if (data.authenticated) setIsAuthenticated(true);
        setAuthChecked(true);
      })
      .catch(() => setAuthChecked(true));
  }, []);

  /* ── Data fetching ── */
  const loadImages = async () => {
    try {
      const res = await fetch('/api/admin/images');
      if (res.ok) { const d = await res.json(); setImages(Array.isArray(d) ? d : (d.images || [])); }
    } catch (err) { console.error('Failed to load images:', err); }
  };

  useEffect(() => {
    if (!isAuthenticated) return;
    const fetchAll = async () => {
      try {
        const [slidesRes, roomsRes, calRes, socialRes, menuRes, placesRes, reviewsRes, imagesRes] = await Promise.all([
          fetch('/api/slides'),
          fetch('/api/rooms'),
          fetch('/api/calendar_events'),
          fetch('/api/social_events/public'),
          fetch('/api/admin/menu'),
          fetch('/api/places'),
          fetch('/api/reviews'),
          fetch('/api/admin/images').catch(() => null),
        ]);
        if (slidesRes.ok) { const d = await slidesRes.json(); setSlides(Array.isArray(d) ? d : (d.data || [])); }
        if (roomsRes.ok) { const d = await roomsRes.json(); setRooms(Array.isArray(d) ? d : (d.data || [])); }
        if (calRes.ok) { const d = await calRes.json(); setEvents(Array.isArray(d) ? d : (d.data || [])); }
        if (socialRes.ok) { const d = await socialRes.json(); setSocialEvents(Array.isArray(d) ? d : (d.data || [])); }
        if (menuRes.ok) { const d = await menuRes.json(); setMenuItems(Array.isArray(d) ? d : (d.data || [])); }
        if (placesRes.ok) { const d = await placesRes.json(); setPlaces(Array.isArray(d) ? d : (d.data || [])); }
        if (reviewsRes.ok) { const d = await reviewsRes.json(); setReviews(Array.isArray(d) ? d : (d.data || [])); }
        if (imagesRes?.ok) { const d = await imagesRes.json(); setImages(Array.isArray(d) ? d : (d.data || d.images || [])); }
      } catch (err) { console.error('Failed to load admin data:', err); }
    };
    fetchAll();
  }, [isAuthenticated]);

  const deleteImage = async (id: number) => {
    try {
      await fetch(`/api/admin/images/${id}`, { method: 'DELETE' });
      setImages(prev => prev.filter(img => img.id !== id));
      showToast('Image deleted', 'success');
    } catch { showToast('Error deleting image', 'error'); }
  };

  const renderSection = () => {
    switch (activeSection) {
      case 'dashboard': return <Dashboard rooms={rooms} slides={slides} events={events} reviews={reviews} places={places} />;
      case 'brand': return <BrandSection images={images} onToast={showToast} />;
      case 'gallery': return (
        <div>
          <SecHead title="🖼️ Image Gallery" count={images.length} />
          <ImageGallery images={images} onDelete={deleteImage} />
        </div>
      );
      case 'slides': return <SlidesSection slides={slides} setSlides={setSlides} images={images} onToast={showToast} onRefreshImages={loadImages} />;
      case 'calendar': return <CalendarSection events={events} setEvents={setEvents} images={images} onToast={showToast} />;
      case 'social': return <SocialSection events={socialEvents} setEvents={setSocialEvents} images={images} onToast={showToast} />;
      case 'rooms': return <RoomsSection rooms={rooms} setRooms={setRooms} images={images} onToast={showToast} />;
      case 'menu': return <MenuSection items={menuItems} setItems={setMenuItems} images={images} onToast={showToast} />;
      case 'places': return <PlacesSection places={places} setPlaces={setPlaces} images={images} onToast={showToast} />;
      case 'reviews': return <ReviewsSection reviews={reviews} setReviews={setReviews} onToast={showToast} />;
      case 'users': return <UsersSection onToast={showToast} />;
      case 'weather': return <WeatherSection onToast={showToast} />;
      case 'trips': return <TripsSection onToast={showToast} />;
      case 'messages': return <MessagesSection onToast={showToast} />;
      default: return <Dashboard rooms={rooms} slides={slides} events={events} reviews={reviews} places={places} />;
    }
  };

  return (
    <div style={{ minHeight: '100vh', background: C.bg, display: 'flex' }}>
      {/* Toasts */}
      {toasts.map(t => <Toast key={t.id} message={t.message} type={t.type} onClose={() => removeToast(t.id)} />)}

      {/* Auth loading */}
      {!authChecked && (
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontSize: '32px', marginBottom: '16px' }}>⏳</div>
            <div style={{ fontSize: '16px', color: C.text }}>Checking authentication...</div>
          </div>
        </div>
      )}

      {/* Not authenticated - show login prompt */}
      {authChecked && !isAuthenticated && (
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <div style={{ textAlign: 'center', maxWidth: 400, padding: '40px', background: '#fff', borderRadius: 16, boxShadow: C.shadow }}>
            <div style={{ fontSize: '48px', marginBottom: '16px' }}>🔒</div>
            <h2 style={{ margin: '0 0 12px', fontSize: '24px', color: C.navy }}>Admin Access Required</h2>
            <p style={{ margin: '0 0 24px', fontSize: '14px', color: C.textLight }}>
              Please log in to access the admin panel.
            </p>
            <a href="/login" style={{ display: 'inline-block', padding: '12px 32px', background: C.gold, color: '#fff', borderRadius: 8, textDecoration: 'none', fontWeight: 600, fontSize: '15px' }}>
              Go to Login
            </a>
          </div>
        </div>
      )}

      {/* Authenticated - show admin panel */}
      {authChecked && isAuthenticated && (
        <>
          {/* Mobile sidebar toggle */}
          <div style={{ display: 'none' }} /> {/* placeholder */}

          {/* Sidebar */}
          <aside style={{
            width: 260, background: C.navy, height: '100vh', position: 'sticky', top: 0, overflowY: 'auto',
            display: 'flex', flexDirection: 'column', transition: 'transform 300ms',
            borderRight: '1px solid rgba(255,255,255,0.06)',
          }}>
            <div style={{ padding: '24px 20px', borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
              <h1 style={{ margin: 0, fontSize: '18px', fontWeight: 700, color: C.gold }}>
                🏨 Hosteria La Huasca
              </h1>
              <p style={{ margin: '4px 0 0', fontSize: '11px', color: 'rgba(255,255,255,0.4)' }}>Admin Portal</p>
            </div>
            <nav style={{ padding: '16px 12px', flex: 1 }}>
              {NAV.map(n => (
                <button key={n.id} onClick={() => { setActiveSection(n.id); setSidebarOpen(false); }}
                  style={{ width: '100%', display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 14px', marginBottom: '4px',
                    borderRadius: 10, border: 'none', cursor: 'pointer', fontSize: '14px', fontWeight: 500,
                    background: activeSection === n.id ? C.goldLight : 'transparent',
                    color: activeSection === n.id ? C.gold : 'rgba(255,255,255,0.6)',
                    transition: 'all 200ms', textAlign: 'left' }}
                  onMouseEnter={e => { if (activeSection !== n.id) { e.currentTarget.style.background = 'rgba(255,255,255,0.06)'; e.currentTarget.style.color = '#fff'; } }}
                  onMouseLeave={e => { if (activeSection !== n.id) { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'rgba(255,255,255,0.6)'; } }}>
                  <span style={{ fontSize: '18px' }}>{n.icon}</span>
                  {n.label}
                </button>
              ))}
            </nav>
            <div style={{ padding: '16px 20px', borderTop: '1px solid rgba(255,255,255,0.06)', fontSize: '11px', color: 'rgba(255,255,255,0.3)' }}>
              v1.0.0
            </div>
          </aside>

          {/* Main content */}
          <main style={{ flex: 1, padding: '32px 40px', overflowY: 'auto', maxHeight: '100vh' }}>
            <div style={{ maxWidth: 1200, margin: '0 auto' }}>
              {renderSection()}
            </div>
          </main>
        </>
      )}
    </div>
  );
}
