// Modals: New booking, Booking detail, Confirmation toast/preview

const Backdrop = ({ onClose, children, width = 560 }) => (
  <div onClick={onClose} style={{
    position: 'fixed', inset: 0, background: 'rgba(20,18,14,0.4)',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    zIndex: 1000, padding: 20,
    animation: 'fadeIn 160ms ease-out',
  }}>
    <div onClick={e => e.stopPropagation()} style={{
      background: '#fff', borderRadius: 14, width: '100%', maxWidth: width,
      maxHeight: '90vh', overflow: 'auto',
      boxShadow: '0 20px 60px rgba(0,0,0,0.25)',
      animation: 'slideUp 200ms ease-out',
    }}>
      {children}
    </div>
  </div>
);

const Field = ({ label, children, required }) => (
  <label style={{ display: 'block', marginBottom: 14 }}>
    <div style={{ fontSize: 12, fontWeight: 600, color: '#4a4a44', marginBottom: 6, letterSpacing: '0.01em' }}>
      {label}{required && <span style={{ color: '#C25555' }}> *</span>}
    </div>
    {children}
  </label>
);

const inputStyle = {
  width: '100%', padding: '10px 12px',
  border: '1px solid #DDD9CE', borderRadius: 8,
  fontSize: 14, fontFamily: 'inherit',
  background: '#FBFAF6', outline: 'none',
  transition: 'border-color 120ms, background 120ms',
  boxSizing: 'border-box',
};

const TextInput = (props) => (
  <input {...props} style={{
    ...inputStyle,
    ...(props.style || {}),
  }} onFocus={e => e.target.style.borderColor = '#7B8A6B'}
     onBlur={e => e.target.style.borderColor = '#DDD9CE'} />
);

const PrimaryBtn = ({ children, onClick, disabled, ...rest }) => (
  <button onClick={onClick} disabled={disabled} {...rest} style={{
    background: disabled ? '#C5C0B0' : '#3F4A3A',
    color: '#fff', border: 'none', borderRadius: 8,
    padding: '10px 18px', fontSize: 14, fontWeight: 600,
    cursor: disabled ? 'not-allowed' : 'pointer',
    fontFamily: 'inherit',
    transition: 'background 120ms',
  }}>{children}</button>
);

const SecondaryBtn = ({ children, onClick, danger, ...rest }) => (
  <button onClick={onClick} {...rest} style={{
    background: 'transparent',
    color: danger ? '#A03838' : '#3F4A3A',
    border: `1px solid ${danger ? '#E0BFBF' : '#DDD9CE'}`,
    borderRadius: 8, padding: '10px 18px', fontSize: 14, fontWeight: 500,
    cursor: 'pointer', fontFamily: 'inherit',
  }}>{children}</button>
);

// Smart time picker showing only slots where the booking fits without conflict
const SmartTimePicker = ({ value, slots, onChange }) => {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    if (open) document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  const current = slots.find(s => s.time === value);
  const isCurrentBlocked = current && !current.available;

  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button onClick={() => setOpen(o => !o)} style={{
        ...inputStyle,
        textAlign: 'left',
        cursor: 'pointer',
        background: isCurrentBlocked ? '#FBEEEE' : '#FBFAF6',
        borderColor: isCurrentBlocked ? '#E0BFBF' : '#DDD9CE',
        color: isCurrentBlocked ? '#A03838' : '#1a1a1a',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
      }}>
        <span>{fmtTime(value)}{isCurrentBlocked ? ' · optaget' : ''}</span>
        <span style={{ color: '#888', fontSize: 11 }}>▾</span>
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: '100%', left: 0, right: 0, marginTop: 4,
          background: '#fff', border: '1px solid #DDD9CE', borderRadius: 8,
          boxShadow: '0 8px 24px rgba(0,0,0,0.12)', zIndex: 10,
          maxHeight: 280, overflow: 'auto', padding: 6,
          display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 4,
        }}>
          {slots.map(slot => {
            const active = slot.time === value;
            return (
              <button key={slot.time}
                disabled={!slot.available}
                onClick={() => { if (slot.available) { onChange(slot.time); setOpen(false); } }}
                style={{
                  background: active ? '#3F4A3A' : (slot.available ? '#fff' : '#F4F2EA'),
                  color: active ? '#fff' : (slot.available ? '#1a1a1a' : '#bbb'),
                  border: `1px solid ${active ? '#3F4A3A' : '#EFEDE5'}`,
                  borderRadius: 5,
                  padding: '6px 4px',
                  fontSize: 12, fontWeight: active ? 600 : 500,
                  cursor: slot.available ? 'pointer' : 'not-allowed',
                  fontFamily: 'inherit',
                  textDecoration: slot.available ? 'none' : 'line-through',
                  textDecorationColor: '#ccc',
                }}>
                {fmtTime(slot.time)}
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
};

// ---------- New booking modal ----------
const NewBookingModal = ({ open, initial, onClose, onCreate, staff, bookings = [] }) => {
  const [customerSearch, setCustomerSearch] = React.useState('');
  const [selectedCustomer, setSelectedCustomer] = React.useState(null);
  const [isNewCustomer, setIsNewCustomer] = React.useState(false);
  const [name, setName] = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [email, setEmail] = React.useState('');
  const firstSvcId = (window.SERVICES || [])[0]?.id || '';
  const [serviceIds, setServiceIds] = React.useState(firstSvcId ? [firstSvcId] : []);
  const [staffId, setStaffId] = React.useState(initial?.staffId || staff[0]?.id);
  const [start, setStart] = React.useState(initial?.start || 9*60);
  const [bookingDate, setBookingDate] = React.useState(initial?.date || toISODate(new Date()));
  const [note, setNote] = React.useState('');
  const [showResults, setShowResults] = React.useState(false);

  React.useEffect(() => {
    if (open) {
      setCustomerSearch(''); setSelectedCustomer(null); setIsNewCustomer(false);
      setName(''); setPhone(''); setEmail(''); setNote('');
      const fid = (window.SERVICES || [])[0]?.id || '';
      setServiceIds(fid ? [fid] : []);
      setStaffId(initial?.staffId || staff[0]?.id);
      setStart(initial?.start ?? 9*60);
      setBookingDate(initial?.date || toISODate(new Date()));
    }
  }, [open, initial]);

  // Compute available start times for selected staff + selected services.
  // MUST run on every render (before any early return) — rules of hooks.
  // Range matches the calendar grid (full 24h) so salons with unusual hours
  // can still pick early-morning or late-night slots.
  const availableSlots = React.useMemo(() => {
    const slots = [];
    if (!serviceIds.length) return slots;
    const startMin = (typeof START_HOUR === 'number' ? START_HOUR : 0) * 60;
    const endMin = (typeof END_HOUR === 'number' ? END_HOUR : 23) * 60 + 45;
    for (let t = startMin; t <= endMin; t += 15) {
      const ok = !hasConflict(staffId, t, serviceIds, bookings);
      slots.push({ time: t, available: ok });
    }
    return slots;
  }, [staffId, serviceIds, bookings, open]);

  if (!open) return null;

  const isCurrentSlotConflict = serviceIds.length > 0 &&
    hasConflict(staffId, start, serviceIds, bookings);

  const matches = customerSearch.length >= 1 && !selectedCustomer
    ? CUSTOMERS.filter(c => c.name.toLowerCase().includes(customerSearch.toLowerCase())
                         || c.phone.includes(customerSearch)).slice(0, 5)
    : [];

  const pickCustomer = (c) => {
    setSelectedCustomer(c);
    setCustomerSearch(c.name);
    setName(c.name); setPhone(c.phone); setEmail(c.email);
    setShowResults(false);
    setIsNewCustomer(false);
    // Auto-select customer's favorite stylist if they have one
    if (c.favoriteStaffId && staff.some(s => s.id === c.favoriteStaffId)) {
      setStaffId(c.favoriteStaffId);
    }
  };

  const canSubmit = serviceIds.length > 0 && !isCurrentSlotConflict && (selectedCustomer || (isNewCustomer && name));

  const submit = () => {
    if (!canSubmit) return;
    const isNewCust = !selectedCustomer;
    const customer = selectedCustomer || {
      id: 'cn' + Date.now(), name, phone, email, visits: 0, lastService: serviceIds[0],
    };
    // App's onCreate is responsible for putting `customer` through
    // setCustomers() when isNew is true — that's how it ends up in
    // Firestore. Mutating the global CUSTOMERS array directly here
    // bypassed React state and the change was lost on reload.
    onCreate({
      id: 'b' + Date.now(),
      staffId, start, serviceIds: [...serviceIds],
      customerId: customer.id,
      date: bookingDate,
      note,
    }, customer, isNewCust);
  };

  const previewBooking = { start, serviceIds };
  const segs = getBookingSegments(previewBooking);
  const totalEnd = start + getBookingDuration(previewBooking);
  const totalPrice = serviceIds.reduce((s, id) => s + (SERVICE_BY_ID[id]?.price || 0), 0);
  const activeMinutes = segs.filter(s => s.kind === 'work').reduce((sum, s) => sum + (s.end - s.start), 0);

  const toggleService = (id) => {
    setServiceIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
  };
  const removeServiceAt = (i) => setServiceIds(prev => prev.filter((_, idx) => idx !== i));
  const moveService = (i, dir) => {
    setServiceIds(prev => {
      const next = [...prev];
      const j = i + dir;
      if (j < 0 || j >= next.length) return prev;
      [next[i], next[j]] = [next[j], next[i]];
      return next;
    });
  };

  return (
    <Backdrop onClose={onClose} width={620}>
      <div style={{ padding: '24px 28px', borderBottom: '1px solid #EFEDE5', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div style={{ fontSize: 11, color: '#888', fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' }}>Ny booking</div>
          <div style={{ fontSize: 22, fontWeight: 600, color: '#1a1a1a', marginTop: 4 }}>Opret aftale</div>
        </div>
        <button onClick={onClose} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: '#888', padding: 6 }}>
          <IconX size={22} />
        </button>
      </div>

      <div style={{ padding: '20px 28px' }}>
        {/* Customer search */}
        <Field label="Kunde" required>
          <div style={{ position: 'relative' }}>
            <div style={{ position: 'absolute', left: 12, top: 12, color: '#999', pointerEvents: 'none' }}>
              <IconSearch size={16} />
            </div>
            <TextInput
              placeholder="Søg på navn eller telefon…"
              value={customerSearch}
              onChange={e => {
                setCustomerSearch(e.target.value);
                setSelectedCustomer(null);
                setShowResults(true);
              }}
              onFocus={() => setShowResults(true)}
              style={{ paddingLeft: 36 }}
            />
            {showResults && matches.length > 0 && (
              <div style={{
                position: 'absolute', top: '100%', left: 0, right: 0, marginTop: 4,
                background: '#fff', border: '1px solid #DDD9CE', borderRadius: 8,
                boxShadow: '0 8px 24px rgba(0,0,0,0.12)', zIndex: 10,
                maxHeight: 240, overflow: 'auto',
              }}>
                {matches.map(c => (
                  <div key={c.id} onClick={() => pickCustomer(c)} style={{
                    padding: '10px 14px', cursor: 'pointer',
                    borderBottom: '1px solid #F4F2EA',
                    display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                  }} onMouseEnter={e => e.currentTarget.style.background = '#FBFAF6'}
                     onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                    <div>
                      <div style={{ fontSize: 14, fontWeight: 500, color: '#1a1a1a' }}>{c.name}</div>
                      <div style={{ fontSize: 12, color: '#777' }}>{c.phone}</div>
                    </div>
                    <div style={{ fontSize: 11, color: '#888' }}>{c.visits} besøg</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </Field>

        <label style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14, fontSize: 13, color: '#4a4a44', cursor: 'pointer' }}>
          <input type="checkbox" checked={isNewCustomer} onChange={e => {
            setIsNewCustomer(e.target.checked);
            if (e.target.checked) { setSelectedCustomer(null); setCustomerSearch(''); }
          }} />
          Opret som ny kunde
        </label>

        {isNewCustomer && (
          <div style={{ background: '#FBFAF6', borderRadius: 10, padding: 16, marginBottom: 14, border: '1px solid #EEEBE0' }}>
            <div style={{ fontSize: 11, color: '#888', marginBottom: 10, fontStyle: 'italic' }}>Telefon og email er valgfri — men kræves for at sende SMS/email-bekræftelse.</div>
            <Field label="Navn" required>
              <TextInput value={name} onChange={e => setName(e.target.value)} placeholder="Fornavn Efternavn" />
            </Field>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
              <Field label="Telefon">
                <TextInput value={phone} onChange={e => setPhone(e.target.value)} placeholder="+45 ..." />
              </Field>
              <Field label="Email">
                <TextInput value={email} onChange={e => setEmail(e.target.value)} placeholder="navn@email.dk" />
              </Field>
            </div>
          </div>
        )}

        <Field label={`Services ${serviceIds.length > 1 ? `(${serviceIds.length} valgt — udføres i rækkefølge)` : ''}`}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
            {SERVICES.map(s => {
              const colors = getServicePalette(s.color);
              const active = serviceIds.includes(s.id);
              return (
                <button key={s.id} onClick={() => toggleService(s.id)} style={{
                  background: active ? colors.bg : '#fff',
                  border: `1.5px solid ${active ? colors.border : '#E5E2D5'}`,
                  borderRadius: 8, padding: '10px 12px', cursor: 'pointer',
                  textAlign: 'left', fontFamily: 'inherit', position: 'relative',
                  transition: 'all 120ms',
                }}>
                  {active && (
                    <div style={{ position: 'absolute', top: 6, right: 6, width: 16, height: 16, borderRadius: '50%', background: colors.border, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                      <IconCheck size={10} stroke="#fff" />
                    </div>
                  )}
                  <div style={{ fontSize: 13, fontWeight: 600, color: active ? colors.text : '#1a1a1a' }}>{s.name}</div>
                  <div style={{ fontSize: 11, color: active ? colors.text : '#888', marginTop: 2, opacity: 0.85 }}>
                    {s.duration} min{s.pauseAfter ? ` + ${s.pauseAfter}m mellemrum` : ''} · {s.price} kr
                  </div>
                </button>
              );
            })}
          </div>

          {serviceIds.length > 0 && (
            <div style={{ marginTop: 12, padding: 12, background: '#FBFAF6', border: '1px solid #EFEDE5', borderRadius: 8 }}>
              <div style={{ fontSize: 11, fontWeight: 600, color: '#666', marginBottom: 8, letterSpacing: '0.06em', textTransform: 'uppercase' }}>Forløb</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                {segs.map((seg, i) => {
                  if (seg.kind === 'gap') {
                    return (
                      <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 12, color: '#888', fontStyle: 'italic', paddingLeft: 26 }}>
                        <span style={{ width: 80 }}>{fmtTime(seg.start)}–{fmtTime(seg.end)}</span>
                        <span>↓ Mellemrum · {seg.end - seg.start} min (frisøren er fri — kan booke andre kunder ind)</span>
                      </div>
                    );
                  }
                  const c = getServicePalette(seg.color);
                  const idx = serviceIds.indexOf(seg.serviceId);
                  return (
                    <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
                      <div style={{ width: 18, height: 18, borderRadius: 4, background: c.bg, border: `1.5px solid ${c.border}`, flexShrink: 0 }} />
                      <span style={{ width: 80, color: '#666', fontSize: 12, fontWeight: 500 }}>{fmtTime(seg.start)}–{fmtTime(seg.end)}</span>
                      <span style={{ flex: 1, fontWeight: 500 }}>{seg.name}</span>
                      <button onClick={() => moveService(idx, -1)} disabled={idx === 0} style={{ background: 'transparent', border: 'none', cursor: idx === 0 ? 'default' : 'pointer', color: idx === 0 ? '#ccc' : '#888', padding: 2, fontSize: 12 }}>↑</button>
                      <button onClick={() => moveService(idx, 1)} disabled={idx === serviceIds.length - 1} style={{ background: 'transparent', border: 'none', cursor: idx === serviceIds.length - 1 ? 'default' : 'pointer', color: idx === serviceIds.length - 1 ? '#ccc' : '#888', padding: 2, fontSize: 12 }}>↓</button>
                      <button onClick={() => removeServiceAt(idx)} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: '#A03838', padding: 2 }}><IconX size={12} /></button>
                    </div>
                  );
                })}
              </div>
              <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px dashed #E5E2D5', display: 'flex', justifyContent: 'space-between', fontSize: 12, color: '#666' }}>
                <span>Aktiv tid: <strong style={{ color: '#1a1a1a' }}>{activeMinutes} min</strong> · Total: <strong style={{ color: '#1a1a1a' }}>{totalEnd - start} min</strong></span>
                <span>I alt: <strong style={{ color: '#1a1a1a' }}>{totalPrice} kr</strong></span>
              </div>
            </div>
          )}
        </Field>

        {/* Date picker — quick chips for today / tomorrow / day after, plus a
            calendar-input for any other day. Default is whatever date the user
            had open in the calendar when they opened the modal. */}
        <Field label="Dato" required>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
            {(() => {
              const today = new Date();
              const tomorrow = new Date(today.getTime() + 86400000);
              const dayAfter = new Date(today.getTime() + 2 * 86400000);
              const chips = [
                { label: 'I dag', date: toISODate(today) },
                { label: 'I morgen', date: toISODate(tomorrow) },
                { label: 'I overmorgen', date: toISODate(dayAfter) },
              ];
              return chips.map(c => (
                <button key={c.date} type="button" onClick={() => setBookingDate(c.date)} style={{
                  padding: '8px 14px', borderRadius: 20,
                  border: bookingDate === c.date ? '1.5px solid #3F4A3A' : '1px solid #DDD9CE',
                  background: bookingDate === c.date ? '#3F4A3A' : '#fff',
                  color: bookingDate === c.date ? '#fff' : '#3F4A3A',
                  fontFamily: 'inherit', fontSize: 13, fontWeight: 500, cursor: 'pointer',
                }}>{c.label}</button>
              ));
            })()}
            <input type="date" value={bookingDate}
              onChange={e => setBookingDate(e.target.value)}
              style={{ ...inputStyle, width: 170 }}
            />
            <span style={{ fontSize: 12, color: '#888', marginLeft: 4 }}>
              {(() => {
                try {
                  const [y, m, d] = bookingDate.split('-').map(Number);
                  return formatDanishDate(new Date(y, m - 1, d));
                } catch { return ''; }
              })()}
            </span>
          </div>
        </Field>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
          <Field label="Medarbejder">
            <select value={staffId} onChange={e => setStaffId(e.target.value)} style={inputStyle}>
              {staff.map(s => <option key={s.id} value={s.id}>{s.name}{selectedCustomer?.favoriteStaffId === s.id ? ' — ♥ favorit' : ''}</option>)}
            </select>
            {selectedCustomer?.favoriteStaffId && staffId === selectedCustomer.favoriteStaffId && (
              <div style={{ fontSize: 11, color: '#7B8A6B', marginTop: 4, fontWeight: 500 }}>♥ Kundens foretrukne frisør er valgt</div>
            )}
          </Field>
          <Field label="Tidspunkt">
            <SmartTimePicker
              value={start}
              slots={availableSlots}
              onChange={setStart}
            />
          </Field>
          <Field label="Slut">
            <div style={{ ...inputStyle, background: '#F4F2EA', color: '#777' }}>{fmtTime(totalEnd)}</div>
          </Field>
        </div>

        <Field label="Noter">
          <textarea value={note} onChange={e => setNote(e.target.value)} rows={2}
            placeholder="Fx ønsker farvebehandling næste gang…"
            style={{ ...inputStyle, fontFamily: 'inherit', resize: 'vertical' }} />
        </Field>

        <div style={{ background: '#F4F7F0', border: '1px solid #DCE6CC', borderRadius: 8, padding: 12, marginTop: 8, fontSize: 12, color: '#3F5A30', display: 'flex', gap: 10, alignItems: 'flex-start' }}>
          <IconCheck size={16} stroke="#3F5A30" />
          <div>
            <strong>Bekræftelse sendes automatisk:</strong> SMS + email straks · påmindelse 24t og 2t før aftalen.
          </div>
        </div>
      </div>

      <div style={{ padding: '16px 28px', borderTop: '1px solid #EFEDE5', display: 'flex', justifyContent: 'flex-end', gap: 10, background: '#FBFAF6' }}>
        <SecondaryBtn onClick={onClose}>Annullér</SecondaryBtn>
        <PrimaryBtn onClick={submit} disabled={!canSubmit}>Opret booking</PrimaryBtn>
      </div>
    </Backdrop>
  );
};

// ---------- Booking detail modal ----------
const BookingDetailModal = ({ booking, onClose, onDelete, onShowMessages, onSendToPOS, onMarkNoShow }) => {
  if (!booking) return null;
  const segs = getBookingSegments(booking);
  const primary = getBookingPrimary(booking);
  const customer = CUSTOMERS.find(c => c.id === booking.customerId);
  const staff = STAFF.find(s => s.id === booking.staffId);
  const colors = getServicePalette(primary?.color);
  const totalDur = getBookingDuration(booking);
  const totalPrice = getBookingPrice(booking);
  const title = getBookingTitle(booking);
  const status = booking.status || 'pending';

  const statusBadge = {
    no_show:     { label: 'UDEBLEVET',     bg: '#FEF2F2', color: '#A03838', border: '#FECACA' },
    in_checkout: { label: 'I KASSEN',      bg: '#FEF6DC', color: '#8A6B1F', border: '#F0DC9C' },
    paid:        { label: 'BETALT',        bg: '#F4F7F0', color: '#3F5A30', border: '#DCE6CC' },
  }[status];

  return (
    <Backdrop onClose={onClose} width={480}>
      <div style={{ background: colors.bg, padding: '24px 28px', borderRadius: '14px 14px 0 0', borderBottom: `3px solid ${colors.border}` }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{ fontSize: 11, color: colors.text, opacity: 0.7, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' }}>{title}</div>
              {statusBadge && (
                <span style={{
                  fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
                  padding: '2px 8px', borderRadius: 10,
                  background: statusBadge.bg, color: statusBadge.color,
                  border: `1px solid ${statusBadge.border}`,
                }}>{statusBadge.label}</span>
              )}
            </div>
            <div style={{ fontSize: 24, fontWeight: 600, color: colors.text, marginTop: 4 }}>{customer?.name || 'Ukendt kunde'}</div>
            <div style={{ fontSize: 13, color: colors.text, opacity: 0.8, marginTop: 6 }}>
              {fmtTime(booking.start)} – {fmtTime(booking.start + totalDur)} · {totalDur} min · {totalPrice} kr
            </div>
          </div>
          <button onClick={onClose} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: colors.text, opacity: 0.7, padding: 6 }}>
            <IconX size={22} />
          </button>
        </div>
      </div>

      <div style={{ padding: '20px 28px' }}>
        {segs.length > 1 && (
          <div style={{ marginBottom: 16, padding: 12, background: '#FBFAF6', border: '1px solid #EFEDE5', borderRadius: 8 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: '#666', marginBottom: 8, letterSpacing: '0.06em', textTransform: 'uppercase' }}>Forløb</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              {segs.map((seg, i) => {
                if (seg.kind === 'gap') {
                  return (
                    <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: '#888', fontStyle: 'italic', paddingLeft: 26 }}>
                      <span style={{ width: 80 }}>{fmtTime(seg.start)}–{fmtTime(seg.end)}</span>
                      <span>Mellemrum · {seg.end - seg.start} min</span>
                    </div>
                  );
                }
                const c = getServicePalette(seg.color);
                return (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
                    <div style={{ width: 18, height: 18, borderRadius: 4, background: c.bg, border: `1.5px solid ${c.border}`, flexShrink: 0 }} />
                    <span style={{ width: 80, color: '#666', fontSize: 12, fontWeight: 500 }}>{fmtTime(seg.start)}–{fmtTime(seg.end)}</span>
                    <span style={{ flex: 1, fontWeight: 500 }}>{seg.name}</span>
                  </div>
                );
              })}
            </div>
          </div>
        )}

        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <DetailRow icon={<IconUser size={16} />} label="Medarbejder" value={staff?.name || 'Ukendt'} />
          <DetailRow icon={<IconPhone size={16} />} label="Telefon" value={customer?.phone || '—'} />
          <DetailRow icon={<IconMail size={16} />} label="Email" value={customer?.email || '—'} />
          <DetailRow icon={<IconClock size={16} />} label="Tidligere besøg" value={`${customer?.visits ?? 0} aftaler`} />
          {customer?.noShows && customer.noShows.length > 0 && (
            <DetailRow icon={<IconBell size={16} />} label="Tidligere udeblivelser"
              value={`${customer.noShows.length} gang${customer.noShows.length === 1 ? '' : 'e'}`} />
          )}
        </div>

        <div style={{ marginTop: 18, padding: 12, background: '#F4F7F0', borderRadius: 8, border: '1px solid #DCE6CC', display: 'flex', alignItems: 'center', gap: 10 }}>
          <IconCheck size={16} stroke="#3F5A30" />
          <div style={{ fontSize: 12, color: '#3F5A30', flex: 1 }}>
            Bekræftelse sendt · Påmindelse planlagt 24t + 2t før
          </div>
          <button onClick={() => onShowMessages(booking)} style={{
            background: 'transparent', border: 'none', color: '#3F5A30',
            fontSize: 12, fontWeight: 600, cursor: 'pointer', textDecoration: 'underline',
          }}>Vis</button>
        </div>

        {/* Action row — Før til kassen + Markér udeblevet, only when relevant */}
        {status === 'pending' && (
          <div style={{ marginTop: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            <button onClick={() => onSendToPOS && onSendToPOS(booking)} style={{
              background: '#3F4A3A', color: '#fff', border: 'none', borderRadius: 10,
              padding: '12px 14px', fontSize: 14, fontWeight: 600, cursor: 'pointer',
              fontFamily: 'inherit', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              boxShadow: '0 2px 8px rgba(63,74,58,0.20)',
            }}>
              <IconGrid size={15} /> Før til kassen →
            </button>
            <button onClick={() => {
              if (confirm(`Markér ${customer?.name || 'kunden'} som udeblevet fra denne booking?`)) {
                onMarkNoShow && onMarkNoShow(booking);
              }
            }} style={{
              background: '#FEF2F2', color: '#A03838', border: '1.5px solid #FECACA', borderRadius: 10,
              padding: '12px 14px', fontSize: 14, fontWeight: 600, cursor: 'pointer',
              fontFamily: 'inherit', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            }}>
              <IconAlert size={15} strokeWidth={2} /> Udeblevet
            </button>
          </div>
        )}
      </div>

      <div style={{ padding: '16px 28px', borderTop: '1px solid #EFEDE5', display: 'flex', justifyContent: 'space-between', background: '#FBFAF6' }}>
        <SecondaryBtn onClick={() => onDelete(booking)} danger>
          <IconTrash size={14} style={{ marginRight: 6, verticalAlign: 'middle' }} />
          Slet booking
        </SecondaryBtn>
        <div style={{ display: 'flex', gap: 10 }}>
          <SecondaryBtn onClick={onClose}>Luk</SecondaryBtn>
        </div>
      </div>
    </Backdrop>
  );
};

const DetailRow = ({ icon, label, value }) => (
  <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
    <div style={{ color: '#888', flexShrink: 0 }}>{icon}</div>
    <div style={{ fontSize: 12, color: '#888', width: 130, flexShrink: 0 }}>{label}</div>
    <div style={{ fontSize: 14, color: '#1a1a1a', fontWeight: 500 }}>{value}</div>
  </div>
);

// ---------- Confirmation messages preview ----------
const MessagesPreviewModal = ({ booking, onClose }) => {
  if (!booking) return null;
  const customer = CUSTOMERS.find(c => c.id === booking.customerId);
  const staff = STAFF.find(s => s.id === booking.staffId);
  const totalDur = getBookingDuration(booking);
  const totalPrice = getBookingPrice(booking);
  const title = getBookingTitle(booking);
  // Use the booking's actual date if present; fall back to the demo date
  const bookingDate = booking.date
    ? (() => { const [y, m, d] = booking.date.split('-').map(Number); return new Date(y, m - 1, d); })()
    : new Date();
  const dateStr = formatDanishDate(bookingDate).toLowerCase();
  const timeStr = `${fmtTime(booking.start)}–${fmtTime(booking.start + totalDur)}`;

  if (!customer || !staff) return null; // safety: deleted customer/staff would crash the SMS template
  // Build a salon-specific cancel URL when we have a salon context
  const salonHost = (window.__SALONIQ_SALON__?.subdomain
    ? window.__SALONIQ_SALON__.subdomain + '.saloniq.dk'
    : 'saloniq.dk');
  const cancelLink = salonHost + '/aflys/' + booking.id.slice(-4);
  const smsBefore = `Hej ${customer.name.split(' ')[0]}! Din tid er bekræftet: ${title} hos ${staff.name.split(' ')[0]} ${dateStr} kl. ${fmtTime(booking.start)}. Aflys/ombook: `;
  const openLink = () => {
    window.dispatchEvent(new CustomEvent('open-customer-link', { detail: booking }));
    onClose();
  };

  return (
    <Backdrop onClose={onClose} width={560}>
      <div style={{ padding: '20px 24px', borderBottom: '1px solid #EFEDE5', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ fontSize: 16, fontWeight: 600 }}>Bekræftelser sendt til {customer.name}</div>
        <button onClick={onClose} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: '#888' }}>
          <IconX size={20} />
        </button>
      </div>
      <div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 16 }}>
        {/* SMS preview */}
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, fontSize: 12, color: '#666', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.08em' }}>
            <IconMessage size={14} /> SMS · sendt nu
          </div>
          <div style={{ background: '#E8F4FE', borderRadius: 14, padding: '12px 16px', fontSize: 14, color: '#1a3a5c', lineHeight: 1.5, maxWidth: 360 }}>
            {smsBefore}
            <a onClick={openLink} style={{ color: '#1a5cb8', textDecoration: 'underline', cursor: 'pointer', fontWeight: 500 }}>{cancelLink}</a>
          </div>
          <div style={{ fontSize: 11, color: '#888', marginTop: 6, display: 'flex', justifyContent: 'space-between', maxWidth: 360 }}>
            <span>Til {customer.phone}</span>
            <span style={{ color: '#1a5cb8', cursor: 'pointer', textDecoration: 'underline' }} onClick={openLink}>Forhåndsvis kunde-link →</span>
          </div>
        </div>

        {/* Email preview */}
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, fontSize: 12, color: '#666', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.08em' }}>
            <IconMail size={14} /> Email · sendt nu
          </div>
          <div style={{ border: '1px solid #EFEDE5', borderRadius: 10, overflow: 'hidden' }}>
            <div style={{ padding: '10px 14px', background: '#FBFAF6', fontSize: 12, color: '#777', borderBottom: '1px solid #EFEDE5' }}>
              <div><strong>Til:</strong> {customer.email}</div>
              <div><strong>Emne:</strong> Bekræftelse: {title} {dateStr}</div>
            </div>
            <div style={{ padding: 18, fontSize: 13, color: '#1a1a1a', lineHeight: 1.6, background: '#fff' }}>
              <div style={{ fontWeight: 600, fontSize: 16, marginBottom: 12 }}>Tak for din booking!</div>
              <div>Hej {customer.name.split(' ')[0]},</div>
              <div style={{ marginTop: 8 }}>Vi glæder os til at se dig:</div>
              <div style={{ marginTop: 12, padding: 12, background: '#FBFAF6', borderRadius: 8, fontSize: 13 }}>
                <div><strong>Service:</strong> {title}</div>
                <div><strong>Frisør:</strong> {staff.name}</div>
                <div><strong>Tidspunkt:</strong> {dateStr}, kl. {timeStr}</div>
                <div><strong>Pris:</strong> {totalPrice} kr</div>
              </div>
              <div style={{ marginTop: 12, fontSize: 12, color: '#666' }}>Du modtager påmindelse 24t og 2t før din aftale.</div>
            </div>
          </div>
        </div>

        {/* Reminders scheduled */}
        <div style={{ background: '#FBFAF6', border: '1px solid #EFEDE5', borderRadius: 10, padding: 14 }}>
          <div style={{ fontSize: 12, color: '#666', fontWeight: 600, marginBottom: 8 }}>PÅMINDELSER PLANLAGT</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: 13 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <IconClock size={14} stroke="#888" />
              <span style={{ color: '#888', width: 96 }}>24 timer før</span>
              <span>SMS + email</span>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <IconClock size={14} stroke="#888" />
              <span style={{ color: '#888', width: 96 }}>2 timer før</span>
              <span>SMS</span>
            </div>
          </div>
        </div>
      </div>
      <div style={{ padding: '14px 24px', borderTop: '1px solid #EFEDE5', display: 'flex', justifyContent: 'flex-end', background: '#FBFAF6' }}>
        <PrimaryBtn onClick={onClose}>Luk</PrimaryBtn>
      </div>
    </Backdrop>
  );
};

// ---------- Service editor modal ----------
// Map old named-color values to hex equivalents so existing services migrate.
const SERVICE_NAMED_TO_HEX = {
  red: '#E14F4F', green: '#4FA84F', blue: '#3D7DB8',
  yellow: '#C9A828', purple: '#7E5BB3', pink: '#C25D89',
};

// Light-themed HEX + RGB color picker for the service editor.
function ServiceColorPicker({ value, onChange }) {
  const hex = (value && String(value).startsWith('#')) ? value : '#4FA84F';
  const m = hex.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
  const rgb = m
    ? { r: parseInt(m[1], 16), g: parseInt(m[2], 16), b: parseInt(m[3], 16) }
    : { r: 79, g: 168, b: 79 };
  const [hexDraft, setHexDraft] = React.useState(hex);

  React.useEffect(() => { setHexDraft(hex); }, [hex]);

  const toHex = (n) => Math.round(Math.max(0, Math.min(255, n))).toString(16).padStart(2, '0');
  const updateRgb = (channel, raw) => {
    const n = Math.max(0, Math.min(255, parseInt(raw) || 0));
    const next = { ...rgb, [channel]: n };
    onChange('#' + toHex(next.r) + toHex(next.g) + toHex(next.b));
  };
  const commitHex = () => {
    const cleaned = hexDraft.startsWith('#') ? hexDraft : '#' + hexDraft;
    if (/^#[a-f\d]{6}$/i.test(cleaned)) onChange(cleaned.toLowerCase());
    else setHexDraft(hex);
  };

  const presets = [
    '#E14F4F', '#4FA84F', '#3D7DB8', '#C9A828', '#7E5BB3', '#C25D89',
    '#3F4A3A', '#0F766E', '#9333EA', '#BE123C', '#F97316', '#0EA5E9',
  ];
  const sliderTrack = (channel) => {
    const left  = '#' + toHex(channel === 'r' ? 0 : rgb.r) + toHex(channel === 'g' ? 0 : rgb.g) + toHex(channel === 'b' ? 0 : rgb.b);
    const right = '#' + toHex(channel === 'r' ? 255 : rgb.r) + toHex(channel === 'g' ? 255 : rgb.g) + toHex(channel === 'b' ? 255 : rgb.b);
    return `linear-gradient(to right, ${left}, ${right})`;
  };

  return (
    <div>
      <div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
        <div style={{
          width: 64, height: 64, borderRadius: 10, background: hex,
          border: '2px solid #E5E2D5', flexShrink: 0,
          boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
        }} />

        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
            <span style={{ fontSize: 11, fontWeight: 700, color: '#666', width: 22 }}>HEX</span>
            <input
              type="text" value={hexDraft}
              onChange={e => setHexDraft(e.target.value)}
              onBlur={commitHex}
              onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); commitHex(); } }}
              spellCheck={false}
              style={{
                flex: 1, padding: '6px 10px', boxSizing: 'border-box',
                border: '1px solid #DDD9CE', borderRadius: 6,
                fontFamily: 'ui-monospace, SF Mono, monospace', fontSize: 12,
                outline: 'none', background: '#FBFAF6', textTransform: 'lowercase',
              }}
            />
          </div>

          {['r', 'g', 'b'].map((c) => (
            <div key={c} style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
              <span style={{ fontSize: 11, fontWeight: 700, color: '#666', width: 22, textTransform: 'uppercase' }}>{c}</span>
              <input
                type="range" min={0} max={255} value={rgb[c]}
                onChange={e => updateRgb(c, e.target.value)}
                style={{
                  flex: 1, height: 5, borderRadius: 3, appearance: 'none',
                  background: sliderTrack(c), outline: 'none', cursor: 'pointer',
                }}
              />
              <input
                type="number" min={0} max={255} value={rgb[c]}
                onChange={e => updateRgb(c, e.target.value)}
                style={{
                  width: 44, padding: '3px 4px', boxSizing: 'border-box',
                  border: '1px solid #DDD9CE', borderRadius: 5,
                  fontSize: 11, outline: 'none', textAlign: 'center', background: '#FBFAF6',
                }}
              />
            </div>
          ))}
        </div>
      </div>

      <div style={{ marginTop: 10 }}>
        <div style={{ fontSize: 10, color: '#888', fontWeight: 700, marginBottom: 5, letterSpacing: '0.06em', textTransform: 'uppercase' }}>Forslag</div>
        <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
          {presets.map(p => {
            const active = p.toLowerCase() === hex.toLowerCase();
            return (
              <button key={p} type="button" onClick={() => onChange(p.toLowerCase())} style={{
                width: 22, height: 22, borderRadius: 6, background: p, border: 'none',
                cursor: 'pointer',
                outline: active ? '2px solid #3F4A3A' : '1px solid #E5E2D5',
                outlineOffset: active ? 2 : 0,
              }} title={p} />
            );
          })}
        </div>
      </div>

      <style>{`
        input[type="range"]::-webkit-slider-thumb {
          appearance: none;
          width: 14px; height: 14px;
          border-radius: 50%;
          background: #fff;
          border: 1.5px solid #888;
          cursor: pointer;
          box-shadow: 0 1px 3px rgba(0,0,0,0.25);
        }
        input[type="range"]::-moz-range-thumb {
          width: 14px; height: 14px;
          border-radius: 50%;
          background: #fff;
          border: 1.5px solid #888;
          cursor: pointer;
        }
      `}</style>
    </div>
  );
}

const ServiceEditorModal = (props) => {
  if (!props.service) return null;
  return <ServiceEditorModalForm key={props.service.id || '_new'} {...props} />;
};

const ServiceEditorModalForm = ({ service, onClose, onSave, onDelete }) => {
  const isNew = !service.id || service._isNew;
  const [name, setName] = React.useState(service.name || '');
  const [duration, setDuration] = React.useState(service.duration ?? 30);
  const [pauseAfter, setPauseAfter] = React.useState(service.pauseAfter ?? 0);
  const [price, setPrice] = React.useState(service.price ?? 350);
  // Always store as hex internally — convert legacy named colors on load
  const initialHex = service.color
    ? (service.color.startsWith('#') ? service.color : (SERVICE_NAMED_TO_HEX[service.color] || '#4FA84F'))
    : '#4FA84F';
  const [color, setColor] = React.useState(initialHex);

  const canSave = name.trim().length > 0 && duration > 0;

  const submit = () => {
    if (!canSave) return;
    onSave({
      id: service.id || ('svc_' + Date.now()),
      name: name.trim(),
      duration: parseInt(duration) || 0,
      pauseAfter: parseInt(pauseAfter) || 0,
      price: parseInt(price) || 0,
      color,
    });
  };

  const previewSegs = (() => {
    const segs = [];
    let t = 0;
    segs.push({ kind: 'work', start: 0, end: duration, name });
    t = duration;
    if (pauseAfter > 0) {
      segs.push({ kind: 'gap', start: t, end: t + pauseAfter });
    }
    return segs;
  })();
  const totalLen = duration + pauseAfter;
  const swatch = getServicePalette(color);

  return (
    <Backdrop onClose={onClose} width={520}>
      <div style={{ padding: '24px 28px', borderBottom: '1px solid #EFEDE5', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div style={{ fontSize: 11, color: '#888', fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' }}>{isNew ? 'Ny service' : 'Redigér service'}</div>
          <div style={{ fontSize: 22, fontWeight: 600, color: '#1a1a1a', marginTop: 4 }}>{name || 'Ny service'}</div>
        </div>
        <button onClick={onClose} style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: '#888', padding: 6 }}>
          <IconX size={22} />
        </button>
      </div>

      <div style={{ padding: '20px 28px' }}>
        <Field label="Navn" required>
          <TextInput value={name} onChange={e => setName(e.target.value)} placeholder="Fx Helfarve, Dameklip…" />
        </Field>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
          <Field label="Aktiv tid (min)" required>
            <TextInput type="number" min="5" step="5" value={duration} onChange={e => setDuration(e.target.value)} />
          </Field>
          <Field label="Mellemrum efter (min)">
            <TextInput type="number" min="0" step="5" value={pauseAfter} onChange={e => setPauseAfter(e.target.value)} />
          </Field>
          <Field label="Pris (kr)">
            <TextInput type="number" min="0" step="5" value={price} onChange={e => setPrice(e.target.value)} />
          </Field>
        </div>

        <div style={{ fontSize: 12, color: '#777', marginTop: -4, marginBottom: 14, lineHeight: 1.5 }}>
          <strong style={{ color: '#4a4a44' }}>Mellemrum efter</strong> bruges fx ved farver, hvor produktet skal trække. Frisøren er fri i mellemrummet og kan tage en anden kunde.
        </div>

        <Field label="Farve i kalenderen">
          <ServiceColorPicker value={color} onChange={setColor} />
        </Field>

        {/* Live preview */}
        <div style={{ marginTop: 8, padding: 14, background: '#FBFAF6', border: '1px solid #EFEDE5', borderRadius: 10 }}>
          <div style={{ fontSize: 11, fontWeight: 600, color: '#666', marginBottom: 10, letterSpacing: '0.06em', textTransform: 'uppercase' }}>Forhåndsvisning</div>
          <div style={{ display: 'flex', gap: 14, alignItems: 'stretch' }}>
            <div style={{ width: 140, position: 'relative', borderRadius: 6, overflow: 'hidden', border: `1.5px solid ${swatch.border}` }}>
              {previewSegs.map((seg, i) => {
                const len = seg.end - seg.start;
                const flex = Math.max(20, (len / Math.max(totalLen, 1)) * 100);
                if (seg.kind === 'gap') {
                  return (
                    <div key={i} style={{
                      flex: `${flex} 0 0`, height: flex * 1.2,
                      background: 'repeating-linear-gradient(45deg, rgba(180,170,140,0.1), rgba(180,170,140,0.1) 5px, rgba(180,170,140,0.22) 5px, rgba(180,170,140,0.22) 10px)',
                      borderTop: '1px dashed rgba(0,0,0,0.15)',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      fontSize: 10, color: '#888', fontStyle: 'italic',
                    }}>
                      Mellemrum {pauseAfter}m
                    </div>
                  );
                }
                return (
                  <div key={i} style={{
                    flex: `${flex} 0 0`, height: flex * 1.2,
                    background: swatch.bg, color: swatch.text,
                    padding: '6px 10px', fontSize: 12, fontWeight: 600,
                  }}>
                    {name || 'Service'}<br/>
                    <span style={{ fontWeight: 400, fontSize: 10, opacity: 0.85 }}>{duration} min</span>
                  </div>
                );
              })}
            </div>
            <div style={{ flex: 1, fontSize: 13, color: '#4a4a44', lineHeight: 1.6 }}>
              <div><strong>Aktiv:</strong> {duration} min</div>
              {pauseAfter > 0 && <div><strong>Mellemrum:</strong> {pauseAfter} min</div>}
              <div><strong>I alt:</strong> {totalLen} min</div>
              <div style={{ marginTop: 6, color: '#777', fontSize: 12 }}>
                {pauseAfter > 0
                  ? `Bookingen optager ${duration} min af frisørens tid — mellemrummet er ledigt for andre kunder.`
                  : `Bookingen optager ${totalLen} min af kalenderen.`}
              </div>
            </div>
          </div>
        </div>
      </div>

      <div style={{ padding: '16px 28px', borderTop: '1px solid #EFEDE5', display: 'flex', justifyContent: 'space-between', background: '#FBFAF6' }}>
        <div>
          {!isNew && onDelete && (
            <SecondaryBtn onClick={() => onDelete(service)} danger>
              <IconTrash size={14} style={{ marginRight: 6, verticalAlign: 'middle' }} />
              Slet
            </SecondaryBtn>
          )}
        </div>
        <div style={{ display: 'flex', gap: 10 }}>
          <SecondaryBtn onClick={onClose}>Annullér</SecondaryBtn>
          <PrimaryBtn onClick={submit} disabled={!canSave}>{isNew ? 'Opret' : 'Gem'}</PrimaryBtn>
        </div>
      </div>
    </Backdrop>
  );
};

// ---------- Receipt modal (print + email + view) ----------
// Renders a salon-branded receipt that prints as a thermal-style 80mm slip.
// Uses CSS @media print to hide the rest of the app while printing.
const ReceiptModal = (props) => {
  if (!props.sale) return null;
  return <ReceiptModalInner key={props.sale.id} {...props} />;
};

const ReceiptModalInner = ({ sale, salon, customer, staff, onClose }) => {
  const dateObj = new Date(sale.paidAt || Date.now());
  const dateStr = dateObj.toLocaleDateString('da-DK', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
  const timeStr = dateObj.toLocaleTimeString('da-DK', { hour: '2-digit', minute: '2-digit' });
  const receiptNo = '#' + (sale.id || '').slice(-6).toUpperCase();
  const methodLabel = ({ 'card':'Kort', 'cash':'Kontant', 'mobile':'MobilePay' })[sale.method] || sale.method || '—';

  const handlePrint = () => { window.print(); };

  const handleEmail = () => {
    const lineWidth = 32;
    const itemLines = sale.items.map(i => {
      const left = `${i.qty}× ${i.name}`;
      const right = `${i.price * i.qty} kr`;
      const pad = Math.max(1, lineWidth - left.length - right.length);
      return left + ' '.repeat(pad) + right;
    });
    const body = [
      `Hej ${customer?.name?.split(' ')[0] || 'kunde'},`,
      ``,
      `Tak for dit besøg hos ${salon?.name || 'os'} — her er din kvittering.`,
      ``,
      `KVITTERING ${receiptNo}`,
      `${dateStr} kl. ${timeStr}`,
      staff?.name ? `Behandler: ${staff.name}` : '',
      ``,
      '─'.repeat(lineWidth),
      ...itemLines,
      '─'.repeat(lineWidth),
      `Subtotal:`.padEnd(lineWidth - String(sale.subtotal).length - 3) + `${sale.subtotal} kr`,
      sale.tip > 0 ? `Drikkepenge:`.padEnd(lineWidth - String(sale.tip).length - 3) + `${sale.tip} kr` : '',
      `I ALT:`.padEnd(lineWidth - String(sale.total).length - 3) + `${sale.total} kr`,
      `Betalt med: ${methodLabel}`,
      ``,
      `Vi glæder os til at se dig igen.`,
      `${salon?.name || 'Saloniq'}`,
      salon?.address || '',
      salon?.phone || '',
    ].filter(l => l !== '').join('\n');
    const subject = `Kvittering fra ${salon?.name || 'salonen'} ${receiptNo}`;
    window.location.href = `mailto:${encodeURIComponent(customer?.email || '')}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
  };

  return (
    <>
      <div className="saloniq-receipt-backdrop" style={{
        position: 'fixed', inset: 0, background: 'rgba(20,20,20,0.55)',
        display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9000,
        padding: 20, fontFamily: "'Manrope', sans-serif",
        animation: 'fadeIn 0.2s ease',
      }}
      onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
        <div style={{
          background: '#fff', borderRadius: 14,
          width: '100%', maxWidth: 380, maxHeight: '90vh',
          overflow: 'auto', boxShadow: '0 12px 48px rgba(0,0,0,0.30)',
          animation: 'slideUp 0.25s ease',
        }}>
          {/* The actual receipt — gets printed */}
          <div className="saloniq-receipt-printable" style={{
            padding: '28px 24px 24px',
            fontFamily: "'Manrope', -apple-system, sans-serif",
            color: '#1a1a1a',
          }}>
            {/* Logo / salon header */}
            <div style={{ textAlign: 'center', marginBottom: 18 }}>
              {salon?.logo ? (
                <img src={salon.logo} alt={salon.name}
                  style={{ maxWidth: 120, maxHeight: 60, objectFit: 'contain', marginBottom: 10 }} />
              ) : null}
              <div style={{
                fontFamily: "'Fraunces', serif", fontSize: 22, fontWeight: 500,
                margin: 0,
              }}>{salon?.name || 'Saloniq'}</div>
              {salon?.address && <div style={{ fontSize: 11, color: '#666', marginTop: 2 }}>{salon.address}</div>}
              {salon?.phone && <div style={{ fontSize: 11, color: '#666' }}>{salon.phone}</div>}
            </div>

            {/* Meta */}
            <div style={{
              borderTop: '1px dashed #999', borderBottom: '1px dashed #999',
              padding: '10px 0', margin: '14px 0',
              fontSize: 11, color: '#444', display: 'flex', justifyContent: 'space-between',
            }}>
              <div>
                <div style={{ fontWeight: 600 }}>KVITTERING {receiptNo}</div>
                <div>{dateStr}</div>
                <div>kl. {timeStr}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                {customer?.name && <div>Kunde: <strong>{customer.name}</strong></div>}
                {staff?.name && <div>Behandler: {staff.name}</div>}
              </div>
            </div>

            {/* Items */}
            <div style={{ marginBottom: 14 }}>
              {sale.items.map((it, idx) => (
                <div key={idx} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', fontSize: 13 }}>
                  <div style={{ flex: 1, paddingRight: 8 }}>
                    <span style={{ display: 'inline-block', width: 26, color: '#888' }}>{it.qty}×</span>
                    {it.name}
                    {it.type === 'product' && <span style={{ color: '#888', fontSize: 11, marginLeft: 4 }}>(produkt)</span>}
                  </div>
                  <div style={{ fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap' }}>{it.price * it.qty} kr</div>
                </div>
              ))}
            </div>

            {/* Totals */}
            <div style={{
              borderTop: '1px dashed #999', paddingTop: 10, fontSize: 13,
              fontVariantNumeric: 'tabular-nums',
            }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', padding: '3px 0' }}>
                <span style={{ color: '#666' }}>Subtotal</span>
                <span>{sale.subtotal} kr</span>
              </div>
              {sale.tip > 0 && (
                <div style={{ display: 'flex', justifyContent: 'space-between', padding: '3px 0' }}>
                  <span style={{ color: '#666' }}>Drikkepenge</span>
                  <span>{sale.tip} kr</span>
                </div>
              )}
              <div style={{
                display: 'flex', justifyContent: 'space-between',
                padding: '8px 0', marginTop: 4,
                borderTop: '2px solid #1a1a1a',
                fontSize: 17, fontWeight: 700,
              }}>
                <span>I ALT</span>
                <span>{sale.total} kr</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0', fontSize: 12, color: '#666' }}>
                <span>Betalt med</span>
                <span>{methodLabel}</span>
              </div>
            </div>

            {/* Footer */}
            <div style={{
              marginTop: 16, paddingTop: 12,
              borderTop: '1px dashed #999',
              textAlign: 'center', fontSize: 11, color: '#666', lineHeight: 1.5,
            }}>
              Tak for dit besøg.<br/>
              Vi glæder os til at se dig igen.
            </div>
            <div style={{
              marginTop: 16, textAlign: 'center', fontSize: 9, color: '#aaa', letterSpacing: '0.06em',
            }}>SALONIQ · AF OONIQ</div>
          </div>

          {/* Action buttons (hidden during print) */}
          <div className="saloniq-receipt-actions" style={{
            padding: '14px 20px', borderTop: '1px solid #EFEDE5',
            display: 'flex', gap: 8, background: '#FBFAF6',
          }}>
            <button onClick={handleEmail} disabled={!customer?.email} style={{
              flex: 1, padding: '10px', background: '#fff', color: customer?.email ? '#3F4A3A' : '#bbb',
              border: '1.5px solid #DDD9CE', borderRadius: 8,
              fontSize: 13, fontWeight: 600, cursor: customer?.email ? 'pointer' : 'not-allowed',
              fontFamily: 'inherit',
            }} title={customer?.email ? `Send til ${customer.email}` : 'Kunden har ingen email'}>
              {customer?.email ? 'Send på email' : 'Ingen email'}
            </button>
            <button onClick={handlePrint} style={{
              flex: 1, padding: '10px', background: '#3F4A3A', color: '#fff',
              border: 'none', borderRadius: 8,
              fontSize: 13, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
            }}>Print / PDF</button>
            <button onClick={onClose} style={{
              padding: '10px 14px', background: 'transparent', color: '#666',
              border: '1.5px solid #DDD9CE', borderRadius: 8,
              fontSize: 13, cursor: 'pointer', fontFamily: 'inherit',
            }}>Luk</button>
          </div>
        </div>
      </div>

      {/* Print stylesheet — hides everything except the receipt during print */}
      <style>{`
        @media print {
          body * { visibility: hidden !important; }
          .saloniq-receipt-printable, .saloniq-receipt-printable * { visibility: visible !important; }
          .saloniq-receipt-backdrop { background: transparent !important; box-shadow: none !important; padding: 0 !important; }
          .saloniq-receipt-backdrop > div { box-shadow: none !important; max-height: none !important; max-width: none !important; }
          .saloniq-receipt-actions { display: none !important; }
          .saloniq-receipt-printable {
            position: absolute !important; top: 0; left: 0;
            width: 80mm !important; padding: 6mm !important;
          }
          @page { size: 80mm auto; margin: 0; }
        }
      `}</style>
    </>
  );
};

// ---------- Toast ----------
const Toast = ({ message, onShowDetails, onClose }) => {
  React.useEffect(() => {
    const t = setTimeout(onClose, 5000);
    return () => clearTimeout(t);
  }, [message]);
  if (!message) return null;
  return (
    <div style={{
      position: 'fixed', bottom: 28, left: '50%',
      transform: 'translateX(-50%)',
      background: '#1F2A1F', color: '#fff',
      padding: '12px 16px 12px 18px', borderRadius: 10,
      display: 'flex', alignItems: 'center', gap: 14,
      boxShadow: '0 12px 32px rgba(0,0,0,0.25)',
      zIndex: 2000, fontSize: 13,
      animation: 'toastIn 240ms ease-out',
    }}>
      <div style={{ background: '#3F5A30', borderRadius: '50%', width: 24, height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
        <IconCheck size={14} stroke="#fff" />
      </div>
      <span>{message}</span>
      {onShowDetails && (
        <button onClick={onShowDetails} style={{
          background: 'transparent', border: '1px solid rgba(255,255,255,0.3)',
          color: '#fff', borderRadius: 6, padding: '4px 10px', fontSize: 12,
          cursor: 'pointer', fontFamily: 'inherit',
        }}>Vis</button>
      )}
      <button onClick={onClose} style={{ background: 'transparent', border: 'none', color: '#fff', opacity: 0.6, cursor: 'pointer', padding: 4 }}>
        <IconX size={16} />
      </button>
    </div>
  );
};

Object.assign(window, {
  NewBookingModal, BookingDetailModal, MessagesPreviewModal, Toast, ReceiptModal,
  ServiceEditorModal,
  PrimaryBtn, SecondaryBtn, TextInput, Field, inputStyle,
});
