const { useState, useEffect } = React;

const FUNCTIONS_BASE = "https://us-central1-medusa-music-booking-portal.cloudfunctions.net";

// Change this to a strong password you'll remember
const ADMIN_PASSWORD = "medusa2026";

async function callFn(path, body) {
  const res = await fetch(`${FUNCTIONS_BASE}/${path}`, {
    method:  "POST",
    headers: { "Content-Type": "application/json" },
    body:    JSON.stringify(body),
  });
  return res.json();
}

const PALETTE = {
  amber:    { bg: "#FAEEDA", border: "#BA7517", text: "#633806" },
  teal:     { bg: "#E1F5EE", border: "#0F6E56", text: "#085041" },
  coral:    { bg: "#FAECE7", border: "#993C1D", text: "#4A1B0C" },
  purple:   { bg: "#EEEDFE", border: "#534AB7", text: "#26215C" },
  gray:     { bg: "#F1EFE8", border: "#5F5E5A", text: "#2C2C2A" },
  blue:     { bg: "#EFF6FF", border: "#2563EB", text: "#1E40AF" },
};

const VENUES = [
  { id: "taproom",    label: "Taproom",     description: "Indoor ~120-seat space, climate controlled" },
  { id: "beergarden", label: "Beer garden", description: "Outdoor space, weather permitting" },
];

const PRESET_TIMES = [
  "12:00 PM", "12:30 PM", "1:00 PM", "1:30 PM", "2:00 PM", "2:30 PM",
  "3:00 PM", "3:30 PM", "4:00 PM", "4:30 PM", "5:00 PM", "5:30 PM",
  "6:00 PM", "6:30 PM", "7:00 PM", "7:30 PM", "8:00 PM",
];

const SET_LENGTH_OPTIONS = [
  "1 hour", "1.5 hours", "2 hours", "2.5 hours", "3 hours", "3.5 hours", "4 hours",
];

const steps = ["Date & time", "Profile", "Assets", "Review"];

function Badge({ color, children }) {
  return (
    <span style={{ background: PALETTE[color]?.bg || "#F1EFE8", color: PALETTE[color]?.text || "#2C2C2A", border: `0.5px solid ${PALETTE[color]?.border || "#5F5E5A"}`, fontSize: 12, padding: "2px 10px", borderRadius: 20, fontWeight: 500, whiteSpace: "nowrap" }}>
      {children}
    </span>
  );
}

function statusBadge(status) {
  const map = { approved: "teal", pending: "amber", declined: "coral", countered: "blue", available: "purple", booked: "gray", cancelled: "gray" };
  return map[status] ? <Badge color={map[status]}>{status.charAt(0).toUpperCase() + status.slice(1)}</Badge> : null;
}

function SlotPill({ time, selected, onClick, disabled }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{ padding: "6px 14px", borderRadius: 20, border: `0.5px solid ${selected ? PALETTE.amber.border : disabled ? "var(--color-border-tertiary)" : "var(--color-border-secondary)"}`, background: selected ? PALETTE.amber.bg : disabled ? "var(--color-background-tertiary)" : "var(--color-background-primary)", color: selected ? PALETTE.amber.text : disabled ? "var(--color-text-secondary)" : "var(--color-text-primary)", fontSize: 13, fontWeight: selected ? 500 : 400, cursor: disabled ? "default" : "pointer", opacity: disabled ? 0.5 : 1 }}>
      {time}
    </button>
  );
}

function Nav({ view, setView }) {
  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 24px", borderBottom: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-primary)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ fontSize: 18, fontWeight: 500, color: "var(--color-text-primary)", letterSpacing: "-0.3px" }}>Medusa Brewing</span>
        <span style={{ fontSize: 13, color: "var(--color-text-secondary)", marginTop: 1 }}>Artist Booking</span>
      </div>
      {view !== "admin" && (
        <button onClick={() => setView("artist")} style={{ fontSize: 13, padding: "5px 14px", borderRadius: 8, border: `0.5px solid ${view === "artist" ? "var(--color-border-primary)" : "var(--color-border-tertiary)"}`, background: view === "artist" ? "var(--color-background-secondary)" : "transparent", cursor: "pointer", color: "var(--color-text-primary)" }}>Artist Portal</button>
      )}
    </div>
  );
}

function AdminAuthModal({ onSuccess, onClose }) {
  const [input, setInput] = useState("");
  const [error, setError] = useState(false);

  const attempt = () => {
    if (input === ADMIN_PASSWORD) {
      localStorage.setItem("adminAuthed", "true");
      onSuccess();
    } else {
      setError(true);
      setInput("");
    }
  };

  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.4)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 100 }}>
      <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 14, padding: "28px 32px", maxWidth: 360, width: "90%" }}>
        <div style={{ fontSize: 18, fontWeight: 500, marginBottom: 6 }}>Admin access</div>
        <p style={{ fontSize: 14, color: "var(--color-text-secondary)", marginBottom: 20 }}>Enter the admin password to continue.</p>
        <input
          type="password" value={input} autoFocus
          onChange={e => { setInput(e.target.value); setError(false); }}
          onKeyDown={e => e.key === "Enter" && attempt()}
          placeholder="Password"
          style={{ width: "100%", boxSizing: "border-box", marginBottom: error ? 8 : 16 }}
        />
        {error && <p style={{ fontSize: 13, color: PALETTE.coral.text, marginBottom: 12 }}>Incorrect password.</p>}
        <div style={{ display: "flex", justifyContent: "space-between" }}>
          <button onClick={onClose} style={{ padding: "8px 18px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-secondary)" }}>Cancel</button>
          <button onClick={attempt} style={{ padding: "8px 22px", borderRadius: 8, border: `0.5px solid ${PALETTE.amber.border}`, background: PALETTE.amber.bg, cursor: "pointer", fontSize: 14, color: PALETTE.amber.text, fontWeight: 500 }}>Enter</button>
        </div>
      </div>
    </div>
  );
}

function CounterOfferModal({ sub, onSubmit, onClose }) {
  const [counterPay, setCounterPay] = useState(sub.pay || "");
  const [message, setMessage] = useState("");
  const [sending, setSending] = useState(false);

  const canSend = counterPay.trim() && !sending;

  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.4)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 100 }}>
      <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 14, padding: "28px 32px", maxWidth: 440, width: "90%" }}>
        <div style={{ fontSize: 17, fontWeight: 500, marginBottom: 4 }}>Counter offer</div>
        <div style={{ fontSize: 13, color: "var(--color-text-secondary)", marginBottom: 20 }}>
          {sub.name} requested <strong style={{ color: "var(--color-text-primary)" }}>{sub.pay}</strong> for {sub.date}{sub.slot ? ` at ${sub.slot}` : ""}
        </div>
        <div style={{ marginBottom: 14 }}>
          <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>Your offer</label>
          <input value={counterPay} onChange={e => setCounterPay(e.target.value)} placeholder="e.g. $350" style={{ width: "100%", boxSizing: "border-box" }} />
        </div>
        <div style={{ marginBottom: 20 }}>
          <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>Message to artist (optional)</label>
          <textarea value={message} onChange={e => setMessage(e.target.value)} rows={3} placeholder="Add any context or conditions…" style={{ width: "100%", boxSizing: "border-box", padding: "8px 12px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-primary)", color: "var(--color-text-primary)", fontSize: 14, resize: "vertical" }} />
        </div>
        <div style={{ display: "flex", justifyContent: "space-between" }}>
          <button onClick={onClose} style={{ padding: "8px 18px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-secondary)" }}>Cancel</button>
          <button disabled={!canSend} onClick={async () => {
            setSending(true);
            await onSubmit(sub.id, counterPay.trim(), message.trim());
            setSending(false);
            onClose();
          }} style={{ padding: "8px 22px", borderRadius: 8, border: `0.5px solid ${canSend ? PALETTE.blue.border : "var(--color-border-tertiary)"}`, background: canSend ? PALETTE.blue.bg : "transparent", cursor: canSend ? "pointer" : "not-allowed", fontSize: 14, color: canSend ? PALETTE.blue.text : "var(--color-text-secondary)", fontWeight: 500 }}>
            {sending ? "Sending…" : "Send counter offer"}
          </button>
        </div>
      </div>
    </div>
  );
}

function ArtistPortal({ dates }) {
  const [step, setStep]           = useState(0);
  const [selections, setSelections] = useState([]); // [{date: dateObj, slot: "5:00 PM"}]
  const [form, setForm]             = useState({ name: "", contactName: "", genre: "", bio: "", email: "", phone: "", draw: "", performers: "", pay: "", payableTo: "", links: "", sound: "" });
  const [assets, setAssets]         = useState({ logo: null, photo: null, instagram: "", spotify: "", website: "" });
  const [submitted, setSubmitted]   = useState(false);
  const [agreed, setAgreed]         = useState(false);
  const [submitting, setSubmitting] = useState(false);

  const upd  = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const updA = (k, v) => setAssets(a => ({ ...a, [k]: v }));

  const isDateSelected = id  => selections.some(s => s.date.id === id);
  const getSlotForDate = id  => selections.find(s => s.date.id === id)?.slot || null;
  const toggleDate     = d   => {
    if (isDateSelected(d.id)) setSelections(prev => prev.filter(s => s.date.id !== d.id));
    else                       setSelections(prev => [...prev, { date: d, slot: null }]);
  };
  const setSlotForDate = (dateId, slot) =>
    setSelections(prev => prev.map(s => s.date.id === dateId ? { ...s, slot } : s));

  const canProceed0 = selections.length > 0 && selections.every(s => s.slot);

  const reset = () => {
    setSubmitted(false); setStep(0); setSelections([]);
    setForm({ name: "", contactName: "", genre: "", bio: "", email: "", phone: "", draw: "", performers: "", pay: "", payableTo: "", links: "", sound: "" });
    setAssets({ logo: null, photo: null, instagram: "", spotify: "", website: "" });
    setAgreed(false); setSubmitting(false);
  };

  if (submitted) return (
    <div style={{ maxWidth: 560, margin: "60px auto", textAlign: "center", padding: "0 24px" }}>
      <div style={{ width: 56, height: 56, borderRadius: "50%", background: PALETTE.teal.bg, display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px", border: `0.5px solid ${PALETTE.teal.border}` }}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M5 12l5 5L19 7" stroke={PALETTE.teal.text} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
      </div>
      <h2 style={{ fontSize: 22, fontWeight: 500, margin: "0 0 8px" }}>Request submitted</h2>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15, lineHeight: 1.6 }}>
        We'll review your application for <strong>{selections.length} date{selections.length !== 1 ? "s" : ""}</strong> and be in touch at <strong>{form.email}</strong>. If approved, you'll receive a contract to sign electronically.
      </p>
      <div style={{ marginTop: 12, display: "flex", flexDirection: "column", gap: 6 }}>
        {selections.map(s => (
          <div key={s.date.id} style={{ display: "flex", gap: 8, justifyContent: "center" }}>
            <Badge color="purple">{s.date.label}</Badge>
            <Badge color="amber">{s.slot}</Badge>
          </div>
        ))}
      </div>
      <button onClick={reset} style={{ marginTop: 24, padding: "8px 20px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-primary)" }}>Submit another</button>
    </div>
  );

  return (
    <div style={{ maxWidth: 680, margin: "0 auto", padding: "32px 24px" }}>
      <div style={{ marginBottom: 28 }}>
        <h2 style={{ fontSize: 22, fontWeight: 500, margin: "0 0 6px" }}>Book a performance at Medusa Brewing</h2>
        <p style={{ color: "var(--color-text-secondary)", fontSize: 15, margin: "0 0 12px" }}>Browse open dates, pick a time slot, and submit your artist profile. We'll be in touch to confirm.</p>
        <p style={{ fontSize: 13, color: PALETTE.amber.text, background: PALETTE.amber.bg, border: `0.5px solid ${PALETTE.amber.border}`, borderRadius: 8, padding: "10px 14px", margin: 0, lineHeight: 1.6 }}>
          <strong>Please complete all fields as thoroughly as possible.</strong> Submissions with missing or incomplete information are likely to be declined.
        </p>
      </div>

      <div style={{ display: "flex", gap: 8, marginBottom: 28, alignItems: "center", flexWrap: "wrap" }}>
        {steps.map((s, i) => (
          <div key={s} style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <div style={{ width: 24, height: 24, borderRadius: "50%", background: i <= step ? PALETTE.amber.bg : "var(--color-background-secondary)", border: `0.5px solid ${i <= step ? PALETTE.amber.border : "var(--color-border-tertiary)"}`, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 12, fontWeight: 500, color: i <= step ? PALETTE.amber.text : "var(--color-text-secondary)" }}>{i + 1}</div>
              <span style={{ fontSize: 13, color: i === step ? "var(--color-text-primary)" : "var(--color-text-secondary)", fontWeight: i === step ? 500 : 400 }}>{s}</span>
            </div>
            {i < steps.length - 1 && <div style={{ width: 20, height: 0.5, background: "var(--color-border-tertiary)" }} />}
          </div>
        ))}
      </div>

      {step === 0 && (
        <div>
          <p style={{ fontSize: 14, color: "var(--color-text-secondary)", marginBottom: 16 }}>Select one or more dates and a time slot for each. You can apply for multiple dates in a single submission.</p>
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {dates.map(d => {
              const isAvail    = d.status === "available";
              const isSelected = isDateSelected(d.id);
              const chosenSlot = getSlotForDate(d.id);
              return (
                <div key={d.id} onClick={() => { if (isAvail) toggleDate(d); }}
                  style={{ padding: "14px 16px", borderRadius: 12, border: `0.5px solid ${isSelected ? PALETTE.amber.border : "var(--color-border-tertiary)"}`, background: isSelected ? PALETTE.amber.bg : !isAvail ? "var(--color-background-tertiary)" : "var(--color-background-primary)", cursor: isAvail ? "pointer" : "default", opacity: !isAvail ? 0.55 : 1 }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: isAvail ? 10 : 0 }}>
                    <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
                      <span style={{ fontSize: 15, fontWeight: 500, color: "var(--color-text-primary)" }}>{d.label}</span>
                      {statusBadge(d.status)}
                      {d.artist && <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>{d.artist}</span>}
                    </div>
                    <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
                      {isSelected && chosenSlot && <Badge color="teal">{chosenSlot} ✓</Badge>}
                      {isSelected && !chosenSlot && <span style={{ fontSize: 12, color: PALETTE.amber.text }}>Pick a time →</span>}
                      {isAvail && !isSelected && d.setLength && <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>{d.setLength} set</span>}
                    </div>
                  </div>
                  {isAvail && (
                    <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
                      {(d.slots || []).map(slot => (
                        <SlotPill key={slot} time={slot} selected={chosenSlot === slot}
                          onClick={e => {
                            e.stopPropagation();
                            if (!isDateSelected(d.id)) setSelections(prev => [...prev, { date: d, slot }]);
                            else setSlotForDate(d.id, slot);
                          }} />
                      ))}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
          {selections.length > 0 && (
            <div style={{ marginTop: 14, padding: "10px 14px", borderRadius: 8, background: PALETTE.teal.bg, border: `0.5px solid ${PALETTE.teal.border}`, fontSize: 13, color: PALETTE.teal.text, display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
              <span style={{ fontWeight: 500 }}>{selections.length} date{selections.length !== 1 ? "s" : ""} selected:</span>
              {selections.map(s => (
                <span key={s.date.id}>{s.date.label}{s.slot ? ` at ${s.slot}` : " (no time yet)"}</span>
              ))}
            </div>
          )}
          <div style={{ marginTop: 16, display: "flex", justifyContent: "flex-end" }}>
            <button disabled={!canProceed0} onClick={() => setStep(1)} style={{ padding: "8px 22px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: canProceed0 ? PALETTE.amber.bg : "transparent", cursor: canProceed0 ? "pointer" : "not-allowed", fontSize: 14, color: canProceed0 ? PALETTE.amber.text : "var(--color-text-secondary)", fontWeight: 500 }}>Continue</button>
          </div>
        </div>
      )}

      {step === 1 && (
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div style={{ padding: "10px 14px", borderRadius: 8, background: PALETTE.amber.bg, border: `0.5px solid ${PALETTE.amber.border}`, fontSize: 13, color: PALETTE.amber.text, display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>
            <span style={{ fontWeight: 500 }}>Requesting {selections.length} date{selections.length !== 1 ? "s" : ""}:</span>
            {selections.map((s, i) => (
              <span key={s.date.id}>{s.date.label} at {s.slot}{i < selections.length - 1 ? " ·" : ""}</span>
            ))}
          </div>
          {[["Artist / Band name", "name", "text"], ["Contact person (authorized representative)", "contactName", "text"], ["Genre", "genre", "text"], ["Contact email", "email", "email"], ["Phone number", "phone", "tel"], ["Estimated draw (attendees)", "draw", "text"], ["Number of performers", "performers", "number"], ["Requested pay", "pay", "text"], ["Make payment payable to", "payableTo", "text"]].map(([label, key, type]) => (
            <div key={key}>
              <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>{label}</label>
              <input type={type} value={form[key]} onChange={e => upd(key, e.target.value)} style={{ width: "100%", boxSizing: "border-box" }} />
            </div>
          ))}
          <div>
            <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>Bio / description</label>
            <textarea value={form.bio} onChange={e => upd("bio", e.target.value)} rows={4} style={{ width: "100%", boxSizing: "border-box", padding: "8px 12px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-primary)", color: "var(--color-text-primary)", fontSize: 14, resize: "vertical" }} />
          </div>
          <div>
            <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>Link to live performance video</label>
            <input value={form.links} onChange={e => upd("links", e.target.value)} style={{ width: "100%", boxSizing: "border-box" }} />
          </div>
          <div style={{ padding: "14px 16px", borderRadius: 10, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-secondary)" }}>
            <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4 }}>House sound system</div>
            <div style={{ fontSize: 13, color: "var(--color-text-secondary)", marginBottom: 12, lineHeight: 1.5 }}>We provide a <strong style={{ color: "var(--color-text-primary)" }}>Bose L1 Pro</strong> PA system and a <strong style={{ color: "var(--color-text-primary)" }}>4-channel mixer</strong> at no charge. Will you be using our system or bringing your own?</div>
            <div style={{ display: "flex", gap: 8 }}>
              {[["house", "Use house system"], ["own", "Bringing my own sound"]].map(([val, label]) => (
                <button key={val} onClick={() => upd("sound", val)}
                  style={{ flex: 1, padding: "8px 12px", borderRadius: 8, border: `0.5px solid ${form.sound === val ? PALETTE.teal.border : "var(--color-border-secondary)"}`, background: form.sound === val ? PALETTE.teal.bg : "var(--color-background-primary)", color: form.sound === val ? PALETTE.teal.text : "var(--color-text-primary)", fontSize: 13, fontWeight: form.sound === val ? 500 : 400, cursor: "pointer" }}>
                  {label}
                </button>
              ))}
            </div>
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8 }}>
            <button onClick={() => setStep(0)} style={{ padding: "8px 18px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-secondary)" }}>Back</button>
            <button disabled={!form.name || !form.contactName || !form.email || !form.sound} onClick={() => setStep(2)} style={{ padding: "8px 22px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: form.name && form.contactName && form.email && form.sound ? PALETTE.amber.bg : "transparent", cursor: form.name && form.contactName && form.email && form.sound ? "pointer" : "not-allowed", fontSize: 14, color: form.name && form.contactName && form.email && form.sound ? PALETTE.amber.text : "var(--color-text-secondary)", fontWeight: 500 }}>Continue</button>
          </div>
        </div>
      )}

      {step === 2 && (
        <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
          <p style={{ fontSize: 14, color: "var(--color-text-secondary)", margin: "0 0 4px" }}>Upload your press kit assets. These are used for promotion once confirmed.</p>
          {[["Logo (PNG or SVG)", "logo", 2], ["Press photo", "photo", 5]].map(([label, key, maxMB]) => (
            <div key={key} style={{ padding: "20px", borderRadius: 10, border: "0.5px dashed var(--color-border-secondary)", textAlign: "center", background: "var(--color-background-secondary)" }}>
              <div style={{ fontSize: 13, color: "var(--color-text-secondary)", marginBottom: 8 }}>{label} <span style={{ opacity: 0.6 }}>(max {maxMB}MB)</span></div>
              <input type="file" accept="image/*" onChange={e => {
                const file = e.target.files[0];
                if (file && file.size > maxMB * 1024 * 1024) {
                  alert(`${label} must be under ${maxMB}MB. Your file is ${(file.size / 1024 / 1024).toFixed(1)}MB.`);
                  e.target.value = "";
                  return;
                }
                updA(key, file || null);
              }} style={{ fontSize: 13 }} />
              {assets[key] && <div style={{ fontSize: 12, color: PALETTE.teal.text, marginTop: 6 }}>Selected: {assets[key].name}</div>}
            </div>
          ))}
          {[["Instagram handle", "instagram"], ["Spotify / streaming link", "spotify"], ["Website", "website"]].map(([label, key]) => (
            <div key={key}>
              <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>{label}</label>
              <input value={assets[key]} onChange={e => updA(key, e.target.value)} style={{ width: "100%", boxSizing: "border-box" }} />
            </div>
          ))}
          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8 }}>
            <button onClick={() => setStep(1)} style={{ padding: "8px 18px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-secondary)" }}>Back</button>
            <button onClick={() => setStep(3)} style={{ padding: "8px 22px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: PALETTE.amber.bg, cursor: "pointer", fontSize: 14, color: PALETTE.amber.text, fontWeight: 500 }}>Review</button>
          </div>
        </div>
      )}

      {step === 3 && (
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 12, padding: "18px 20px" }}>
            <div style={{ fontSize: 13, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 12, textTransform: "uppercase", letterSpacing: 0.5 }}>Review your submission</div>
            <div style={{ padding: "6px 0", borderBottom: "0.5px solid var(--color-border-tertiary)", marginBottom: 4 }}>
              <span style={{ fontSize: 13, color: "var(--color-text-secondary)" }}>Dates requested</span>
              <div style={{ display: "flex", flexDirection: "column", gap: 4, marginTop: 6 }}>
                {selections.map(s => (
                  <div key={s.date.id} style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
                    <Badge color="purple">{s.date.label}</Badge>
                    <Badge color="amber">{s.slot}</Badge>
                    {s.date.setLength && <span style={{ fontSize: 12, color: "var(--color-text-secondary)", alignSelf: "center" }}>{s.date.setLength} set</span>}
                  </div>
                ))}
              </div>
            </div>
            {[["Artist / Band", form.name], ["Contact person", form.contactName], ["Genre", form.genre], ["Email", form.email], ["Phone", form.phone], ["Estimated draw", form.draw], ["Number of performers", form.performers], ["Requested pay", form.pay], ["Payment payable to", form.payableTo], ["Sound", form.sound === "house" ? "Using house system (Bose L1 Pro + 4-ch mixer)" : "Bringing own sound"]].map(([k, v]) => v && (
              <div key={k} style={{ display: "flex", justifyContent: "space-between", padding: "6px 0", borderBottom: "0.5px solid var(--color-border-tertiary)", fontSize: 14 }}>
                <span style={{ color: "var(--color-text-secondary)" }}>{k}</span>
                <span style={{ fontWeight: 500 }}>{v}</span>
              </div>
            ))}
          </div>
          <div style={{ padding: "14px 16px", borderRadius: 10, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-secondary)", fontSize: 13, color: "var(--color-text-secondary)", lineHeight: 1.6 }}>
            <strong style={{ color: "var(--color-text-primary)" }}>What happens next:</strong> We'll review within a few days. If approved, you'll receive an auto-filled contract for electronic signature confirming your date, time, and agreed pay.
          </div>
          <label style={{ display: "flex", gap: 10, alignItems: "flex-start", fontSize: 14, cursor: "pointer" }}>
            <input type="checkbox" checked={agreed} onChange={e => setAgreed(e.target.checked)} style={{ marginTop: 2 }} />
            <span style={{ color: "var(--color-text-secondary)", lineHeight: 1.5 }}>I confirm all information is accurate and agree to be contacted by Medusa Brewing regarding this booking request.</span>
          </label>
          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 4 }}>
            <button onClick={() => setStep(2)} style={{ padding: "8px 18px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-secondary)" }}>Back</button>
            <button disabled={!agreed || submitting} onClick={async () => {
              setSubmitting(true);
              try {
                const { storage, ref, uploadBytes, getDownloadURL } = window.__firebase;
                let logoUrl = null, photoUrl = null;
                if (assets.logo) {
                  const r = ref(storage, `press-kits/${Date.now()}-logo-${assets.logo.name}`);
                  await uploadBytes(r, assets.logo);
                  logoUrl = await getDownloadURL(r);
                }
                if (assets.photo) {
                  const r = ref(storage, `press-kits/${Date.now()}-photo-${assets.photo.name}`);
                  await uploadBytes(r, assets.photo);
                  photoUrl = await getDownloadURL(r);
                }
                let allOk = true;
                for (const sel of selections) {
                  const result = await callFn("submitBooking", {
                    ...form,
                    date:      sel.date.label,
                    dateRaw:   sel.date.date,
                    dateId:    sel.date.id,
                    slot:      sel.slot,
                    setLength: sel.date.setLength,
                    instagram: assets.instagram,
                    spotify:   assets.spotify,
                    website:   assets.website,
                    logoUrl,
                    photoUrl,
                  });
                  if (!result.success) { allOk = false; break; }
                }
                if (allOk) setSubmitted(true);
              } catch (err) {
                console.error("Submission failed:", err);
              } finally {
                setSubmitting(false);
              }
            }} style={{ padding: "8px 22px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: agreed && !submitting ? PALETTE.teal.bg : "transparent", cursor: agreed && !submitting ? "pointer" : "not-allowed", fontSize: 14, color: agreed && !submitting ? PALETTE.teal.text : "var(--color-text-secondary)", fontWeight: 500 }}>
              {submitting ? "Submitting…" : "Submit request"}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

function ContractModal({ sub, onClose }) {
  const BASE_URL    = "https://booking.medusabrewing.com";
  const contractUrl = `${BASE_URL}?sign=true&id=${sub.id}`;
  const today       = new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
  const signedDate  = sub.contractSignedAt?.toDate?.()?.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });

  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.4)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 100 }}>
      <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 14, padding: "28px 32px", maxWidth: 520, width: "90%", maxHeight: "85vh", overflowY: "auto" }}>
        <div style={{ fontSize: 18, fontWeight: 500, marginBottom: 6 }}>Performance agreement</div>
        <div style={{ fontSize: 13, marginBottom: 20 }}>
          {sub.contractSigned
            ? <span style={{ color: PALETTE.teal.text, fontWeight: 500 }}>Signed ✓ by {sub.contractSignedBy}{signedDate ? ` on ${signedDate}` : ""}</span>
            : <span style={{ color: PALETTE.amber.text }}>Awaiting artist signature</span>
          }
        </div>
        <div style={{ fontSize: 14, lineHeight: 1.8, color: "var(--color-text-primary)", background: "var(--color-background-secondary)", padding: "16px 18px", borderRadius: 10, border: "0.5px solid var(--color-border-tertiary)", marginBottom: 20 }}>
          <p style={{ margin: "0 0 10px" }}>This Performance Agreement is entered into as of <strong>{today}</strong> between <strong>Medusa Brewing Company</strong> ("Venue") and <strong>{sub.name}</strong> ("Artist"), represented by <strong>{sub.contactName || "authorized representative"}</strong>.</p>
          {sub.venue && <p style={{ margin: "0 0 8px" }}><strong>Venue:</strong> {VENUES.find(v => v.id === sub.venue)?.label || sub.venue}</p>}
          <p style={{ margin: "0 0 8px" }}><strong>Set time:</strong> {sub.slot}</p>
          {sub.setLength && <p style={{ margin: "0 0 8px" }}><strong>Set length:</strong> {sub.setLength}</p>}
          <p style={{ margin: "0 0 8px" }}><strong>Performance fee:</strong> {sub.counterPay || sub.pay}</p>
          {sub.payableTo && <p style={{ margin: "0 0 8px" }}><strong>Payment payable to:</strong> {sub.payableTo}</p>}
          <p style={{ margin: "0 0 8px" }}><strong>Sound:</strong> {sub.sound === "house" ? "Artist will use house system (Bose L1 Pro + 4-channel mixer)" : "Artist will provide own sound system"}</p>
          <p style={{ margin: "12px 0 0", fontSize: 13, color: "var(--color-text-secondary)" }}>Artist agrees to perform for the full agreed set length. For every 3-hour booking, the Artist is entitled to one 30-minute break or two 15-minute breaks. Venue provides sound and front-of-house support. Payment made in full night of performance. 14-day cancellation notice required.</p>
        </div>
        {!sub.contractSigned && (
          <div style={{ marginBottom: 20, padding: "12px 14px", borderRadius: 8, background: PALETTE.amber.bg, border: `0.5px solid ${PALETTE.amber.border}` }}>
            <div style={{ fontSize: 12, color: PALETTE.amber.text, fontWeight: 500, marginBottom: 4 }}>Signing link (send to artist)</div>
            <div style={{ fontSize: 12, color: PALETTE.amber.text, wordBreak: "break-all", fontFamily: "monospace" }}>{contractUrl}</div>
          </div>
        )}
        <div style={{ display: "flex", justifyContent: "flex-end" }}>
          <button onClick={onClose} style={{ padding: "8px 22px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: "transparent", cursor: "pointer", fontSize: 14, color: "var(--color-text-primary)" }}>Close</button>
        </div>
      </div>
    </div>
  );
}

function ContractSign({ submissionId }) {
  const [sub, setSub] = useState(null);
  const [loading, setLoading] = useState(true);
  const [sig, setSig] = useState("");
  const [signing, setSigning] = useState(false);
  const [done, setDone] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const { db, doc, onSnapshot } = window.__firebase;
    return onSnapshot(
      doc(db, "submissions", submissionId),
      snap => { if (snap.exists()) setSub({ id: snap.id, ...snap.data() }); setLoading(false); },
      err  => { console.error(err); setLoading(false); }
    );
  }, [submissionId]);

  const today = new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });

  if (loading) return (
    <div style={{ textAlign: "center", padding: "80px 24px", color: "var(--color-text-secondary)", fontSize: 14 }}>Loading your agreement…</div>
  );

  if (!sub || sub.status !== "approved") return (
    <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15 }}>This contract link is no longer valid.</p>
    </div>
  );

  if (sub.contractSigned || done) return (
    <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
      <div style={{ width: 56, height: 56, borderRadius: "50%", background: PALETTE.teal.bg, display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px", border: `0.5px solid ${PALETTE.teal.border}` }}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M5 12l5 5L19 7" stroke={PALETTE.teal.text} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
      </div>
      <h2 style={{ fontSize: 20, fontWeight: 500, margin: "0 0 10px" }}>Agreement signed</h2>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15, lineHeight: 1.6 }}>
        Your performance agreement for <strong>{sub.date}</strong> at <strong>{sub.slot}</strong> has been signed. See you there!
      </p>
    </div>
  );

  const signAs = sub.contactName || sub.name || "";
  const canSign = sig.trim().toLowerCase() === signAs.toLowerCase() && !signing;

  return (
    <div style={{ maxWidth: 560, margin: "40px auto", padding: "0 24px" }}>
      <h2 style={{ fontSize: 22, fontWeight: 500, margin: "0 0 8px" }}>Performance agreement</h2>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 14, margin: "0 0 24px" }}>Review and sign your agreement with Medusa Brewing.</p>
      <div style={{ fontSize: 14, lineHeight: 1.8, color: "var(--color-text-primary)", background: "var(--color-background-secondary)", padding: "16px 18px", borderRadius: 10, border: "0.5px solid var(--color-border-tertiary)", marginBottom: 24 }}>
        <p style={{ margin: "0 0 12px" }}>This Performance Agreement is entered into as of <strong>{today}</strong> between <strong>Medusa Brewing Company</strong> ("Venue") and <strong>{sub.name}</strong> ("Artist"), represented by <strong>{sub.contactName || "authorized representative"}</strong>.</p>
        <p style={{ margin: "0 0 8px" }}><strong>Date:</strong> {sub.date}</p>
        <p style={{ margin: "0 0 8px" }}><strong>Set time:</strong> {sub.slot}</p>
        {sub.setLength && <p style={{ margin: "0 0 8px" }}><strong>Set length:</strong> {sub.setLength}</p>}
        <p style={{ margin: "0 0 8px" }}><strong>Performance fee:</strong> {sub.counterPay || sub.pay}</p>
        {sub.payableTo && <p style={{ margin: "0 0 8px" }}><strong>Payment payable to:</strong> {sub.payableTo}</p>}
        <p style={{ margin: "0 0 8px" }}><strong>Sound:</strong> {sub.sound === "house" ? "Artist will use house system (Bose L1 Pro + 4-channel mixer)" : "Artist will provide own sound system"}</p>
        <p style={{ margin: "12px 0 0", fontSize: 13, color: "var(--color-text-secondary)" }}>Artist agrees to perform for the full agreed set length. For every 3-hour booking, the Artist is entitled to one 30-minute break or two 15-minute breaks. Venue provides sound and front-of-house support. Payment made in full night of performance. 14-day cancellation notice required.</p>
      </div>
      <div style={{ marginBottom: 20 }}>
        <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 6 }}>
          Sign by typing your full name (<strong style={{ color: "var(--color-text-primary)" }}>{signAs}</strong>) to confirm you are authorized to sign on behalf of {sub.name}:
        </label>
        <input
          value={sig}
          onChange={e => { setSig(e.target.value); setError(null); }}
          placeholder={`Type "${signAs}" to sign`}
          style={{ width: "100%", boxSizing: "border-box", fontStyle: "italic" }}
        />
        {error && <p style={{ fontSize: 13, color: PALETTE.coral.text, marginTop: 6 }}>{error}</p>}
      </div>
      <button disabled={!canSign} onClick={async () => {
        setSigning(true);
        setError(null);
        try {
          const result = await callFn("signContract", { id: submissionId, signedBy: sig.trim() });
          if (result.success) setDone(true);
          else setError("Something went wrong. Please try again.");
        } catch { setError("Something went wrong. Please try again."); }
        setSigning(false);
      }} style={{ width: "100%", padding: "11px 22px", borderRadius: 8, border: `0.5px solid ${canSign ? PALETTE.teal.border : "var(--color-border-tertiary)"}`, background: canSign ? PALETTE.teal.bg : "transparent", cursor: canSign ? "pointer" : "not-allowed", fontSize: 14, color: canSign ? PALETTE.teal.text : "var(--color-text-secondary)", fontWeight: 500 }}>
        {signing ? "Signing…" : "Sign agreement"}
      </button>
    </div>
  );
}

function AdminDashboard({ dates, setDates, onSignOut }) {
  const [subs, setSubs] = useState([]);
  const [tab, setTab] = useState("submissions");
  const [activeFilter, setActiveFilter] = useState(null);
  const [searchQuery, setSearchQuery]   = useState("");
  const [sortBy, setSortBy]             = useState("newest");
  const [contract, setContract] = useState(null);
  const [counterOfferSub, setCounterOfferSub] = useState(null);
  const [newDateY, setNewDateY] = useState("");
  const [newDateM, setNewDateM] = useState("");
  const [newDateD, setNewDateD] = useState("");
  const [bulkMonth, setBulkMonth]   = useState(() => { const d = new Date(); d.setMonth(d.getMonth() + 1); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; });
  const [bulkDays, setBulkDays]     = useState([5, 6]); // Fri, Sat default
  const [bulkAdding, setBulkAdding] = useState(false);
  const [bulkConfirm, setBulkConfirm] = useState(false);
  const [expandedDate, setExpandedDate] = useState(null);
  const [defaultSlots, setDefaultSlots] = useState(["5:00 PM", "8:00 PM"]);
  const [defaultVenues, setDefaultVenues] = useState(["taproom"]);
  const [defaultSetLength, setDefaultSetLength] = useState("3 hours");
  const [applyConfirm, setApplyConfirm]         = useState(false);
  const [selectedDateIds, setSelectedDateIds]   = useState(new Set());
  const [calendarFilter, setCalendarFilter]     = useState("all");

  useEffect(() => {
    const { db, collection, onSnapshot, query, orderBy } = window.__firebase;
    const q = query(collection(db, "submissions"), orderBy("createdAt", "desc"));
    return onSnapshot(
      q,
      snap => { setSubs(snap.docs.map(d => ({ id: d.id, ...d.data() }))); },
      err  => { console.error("Submissions listener error:", err); }
    );
  }, []);

  const approve = async id => {
    const sub = subs.find(s => s.id === id);
    setSubs(s => s.map(x => x.id === id ? { ...x, status: "approved" } : x));
    await callFn("updateSubmission", { id, status: "approved" });
    // Update Google Calendar
    if (sub?.dateId) {
      setDates(prev => prev.map(d => d.id === sub.dateId ? { ...d, status: "booked", artist: sub.name } : d));
      callFn("blockDate", {
        eventId:     sub.dateId,
        artistName:  sub.name,
        pay:         sub.counterPay || sub.pay,
        slot:        sub.slot,
        setLength:   sub.setLength,
        dateRaw:     sub.dateRaw,
        contactName: sub.contactName,
        phone:       sub.phone,
        email:       sub.email,
        payableTo:   sub.payableTo,
        genre:       sub.genre,
        draw:        sub.draw,
        sound:       sub.sound,
        bio:         sub.bio,
      }).catch(console.error);
    }
    // Email artist (fire-and-forget)
    if (sub?.email) {
      callFn("sendArtistEmail", {
        type: "approved", to: sub.email, name: sub.name,
        date: sub.date, slot: sub.slot, pay: sub.counterPay || sub.pay,
        sound: sub.sound, setLength: sub.setLength,
        submissionId: id,
      }).catch(console.error);
    }
  };

  const decline = async id => {
    const sub = subs.find(s => s.id === id);
    setSubs(s => s.map(x => x.id === id ? { ...x, status: "declined" } : x));
    await callFn("updateSubmission", { id, status: "declined" });
    if (sub?.email) {
      callFn("sendArtistEmail", {
        type: "declined", to: sub.email, name: sub.name, date: sub.date,
      }).catch(console.error);
    }
  };

  const submitCounterOffer = async (id, counterPay, counterMessage) => {
    const sub = subs.find(s => s.id === id);
    setSubs(s => s.map(x => x.id === id ? { ...x, status: "countered", counterPay, counterMessage } : x));
    await callFn("updateSubmission", { id, status: "countered", counterPay, counterMessage });
    if (sub?.email) {
      callFn("sendArtistEmail", {
        type: "countered", to: sub.email, name: sub.name,
        date: sub.date, slot: sub.slot, counterPay, counterMessage,
        submissionId: id,
      }).catch(console.error);
    }
  };

  const deleteSubmission = async id => {
    if (!window.confirm("Permanently delete this submission? Associated images will also be removed. This cannot be undone.")) return;
    setSubs(prev => prev.filter(s => s.id !== id));
    callFn("deleteSubmission", { id }).catch(console.error);
  };

  const cancel = async id => {
    if (!window.confirm("Cancel this booking? The artist will be notified and the calendar date will reopen.")) return;
    const sub = subs.find(s => s.id === id);
    setSubs(s => s.map(x => x.id === id ? { ...x, status: "cancelled" } : x));
    await callFn("updateSubmission", { id, status: "cancelled" });
    if (sub?.dateId) {
      setDates(prev => prev.map(d => d.id === sub.dateId ? { ...d, status: "available", artist: undefined } : d));
      callFn("unblockDate", { eventId: sub.dateId }).catch(console.error);
    }
    if (sub?.email) {
      callFn("sendArtistEmail", {
        type: "cancelled", to: sub.email, name: sub.name, date: sub.date, slot: sub.slot,
      }).catch(console.error);
    }
  };

  const handleDeleteDate = async dateId => {
    const date = dates.find(d => d.id === dateId);
    const msg  = date?.status === "booked"
      ? `⚠ This date is currently booked${date.artist && date.artist !== "Blocked" ? ` (${date.artist})` : ""}. Deleting it will permanently remove it from the calendar. Continue?`
      : "Permanently remove this date from the calendar? This cannot be undone.";
    if (!window.confirm(msg)) return;
    setDates(prev => prev.filter(d => d.id !== dateId));
    callFn("deleteCalendarDate", { eventId: dateId }).catch(console.error);
  };

  const toggleSelectDate = id => setSelectedDateIds(prev => {
    const next = new Set(prev);
    next.has(id) ? next.delete(id) : next.add(id);
    return next;
  });

  const handleBulkDelete = async () => {
    const selected     = dates.filter(d => selectedDateIds.has(d.id));
    const bookedCount  = selected.filter(d => d.status === "booked").length;
    const msg = bookedCount > 0
      ? `⚠ ${bookedCount} of the selected date${bookedCount > 1 ? "s are" : " is"} currently booked. Deleting will permanently remove ${bookedCount > 1 ? "them" : "it"} from the calendar. Continue?`
      : `Permanently remove ${selectedDateIds.size} date${selectedDateIds.size > 1 ? "s" : ""} from the calendar? This cannot be undone.`;
    if (!window.confirm(msg)) return;
    const ids = [...selectedDateIds];
    setDates(prev => prev.filter(d => !ids.includes(d.id)));
    setSelectedDateIds(new Set());
    ids.forEach(id => callFn("deleteCalendarDate", { eventId: id }).catch(console.error));
  };

  const handleBulkOpen = async () => {
    const ids = [...selectedDateIds].filter(id => dates.find(d => d.id === id)?.status === "booked");
    if (!ids.length) return;
    if (!window.confirm(`Re-open ${ids.length} booked date${ids.length > 1 ? "s" : ""}?`)) return;
    setDates(prev => prev.map(d => ids.includes(d.id) ? { ...d, status: "available", artist: undefined } : d));
    setSelectedDateIds(new Set());
    ids.forEach(id => callFn("unblockDate", { eventId: id }).catch(console.error));
  };

  const handleBulkBlock = async () => {
    const ids = [...selectedDateIds].filter(id => dates.find(d => d.id === id)?.status === "available");
    if (!ids.length) return;
    if (!window.confirm(`Block ${ids.length} available date${ids.length > 1 ? "s" : ""}?`)) return;
    setDates(prev => prev.map(d => ids.includes(d.id) ? { ...d, status: "booked" } : d));
    setSelectedDateIds(new Set());
    ids.forEach(id => callFn("blockDate", { eventId: id, artistName: "Blocked" }).catch(console.error));
  };

  const toggleDefaultSlot  = slot => setDefaultSlots(prev => prev.includes(slot) ? prev.filter(s => s !== slot) : [...prev, slot].sort());
  const toggleDefaultVenue = vid  => setDefaultVenues(prev => prev.includes(vid)  ? prev.filter(v => v !== vid)  : [...prev, vid]);

  const applyToAll = async () => {
    setDates(prev => prev.map(d => d.status !== "booked" ? { ...d, slots: [...defaultSlots], venues: [...defaultVenues], setLength: defaultSetLength } : d));
    await callFn("applyDefaultsToAllDates", { slots: defaultSlots, venues: defaultVenues, setLength: defaultSetLength });
    setApplyConfirm(true);
    setTimeout(() => setApplyConfirm(false), 2500);
  };

  const toggleSlot = async (dateId, slot) => {
    const date = dates.find(d => d.id === dateId);
    if (!date) return;
    const newSlots = (date.slots || []).includes(slot)
      ? date.slots.filter(s => s !== slot)
      : [...(date.slots || []), slot].sort();
    setDates(prev => prev.map(d => d.id === dateId ? { ...d, slots: newSlots } : d));
    await callFn("updateCalendarDate", { eventId: dateId, slots: newSlots, venues: date.venues || [], setLength: date.setLength || "3 hours" });
  };

  const toggleVenue = async (dateId, venueId) => {
    const date = dates.find(d => d.id === dateId);
    if (!date) return;
    const cur = date.venues || [];
    const newVenues = cur.includes(venueId) ? cur.filter(v => v !== venueId) : [...cur, venueId];
    setDates(prev => prev.map(d => d.id === dateId ? { ...d, venues: newVenues } : d));
    await callFn("updateCalendarDate", { eventId: dateId, slots: date.slots || [], venues: newVenues, setLength: date.setLength || "3 hours" });
  };

  const updateSetLength = async (dateId, setLength) => {
    const date = dates.find(d => d.id === dateId);
    if (!date) return;
    setDates(prev => prev.map(d => d.id === dateId ? { ...d, setLength } : d));
    await callFn("updateCalendarDate", { eventId: dateId, slots: date.slots || [], venues: date.venues || [], setLength });
  };

  const handleBlockDate = async dateId => {
    setDates(prev => prev.map(d => d.id === dateId ? { ...d, status: "booked" } : d));
    await callFn("blockDate", { eventId: dateId, artistName: "Blocked" });
  };

  const handleUnblockDate = async dateId => {
    setDates(prev => prev.map(d => d.id === dateId ? { ...d, status: "available", artist: undefined } : d));
    await callFn("unblockDate", { eventId: dateId });
  };

  const newDate = newDateY && newDateM && newDateD ? `${newDateY}-${newDateM}-${newDateD}` : "";

  const handleAddDate = async () => {
    if (!newDate) return;
    const label  = new Date(newDate + "T12:00:00").toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
    const result = await callFn("addCalendarDate", { date: newDate, slots: defaultSlots, venues: defaultVenues, setLength: defaultSetLength });
    if (result.eventId) {
      setDates(prev => [...prev, { id: result.eventId, date: newDate, label, status: "available", slots: [...defaultSlots], venues: [...defaultVenues], setLength: defaultSetLength }].sort((a, b) => a.date.localeCompare(b.date)));
    }
    setNewDateY(""); setNewDateM(""); setNewDateD("");
  };

  const getBulkPreviewDates = () => {
    if (!bulkMonth || bulkDays.length === 0) return [];
    const [year, month] = bulkMonth.split("-").map(Number);
    const daysInMonth   = new Date(year, month, 0).getDate();
    const result = [];
    for (let day = 1; day <= daysInMonth; day++) {
      const d = new Date(year, month - 1, day);
      if (bulkDays.includes(d.getDay())) {
        const dateStr = `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
        if (!dates.some(existing => existing.date === dateStr)) result.push(dateStr);
      }
    }
    return result;
  };

  const handleBulkAddDates = async () => {
    const newDates = getBulkPreviewDates();
    if (!newDates.length) return;
    setBulkAdding(true);
    try {
      const result = await callFn("addCalendarDatesBatch", { dates: newDates, slots: defaultSlots, venues: defaultVenues, setLength: defaultSetLength });
      if (result.eventIds) {
        const objs = newDates.map((dateStr, i) => ({
          id:       result.eventIds[i],
          date:     dateStr,
          label:    new Date(dateStr + "T12:00:00").toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" }),
          status:   "available",
          slots:    [...defaultSlots],
          venues:   [...defaultVenues],
          setLength: defaultSetLength,
        }));
        setDates(prev => [...prev, ...objs].sort((a, b) => a.date.localeCompare(b.date)));
        setBulkConfirm(true);
        setTimeout(() => setBulkConfirm(false), 3000);
      }
    } catch (err) { console.error(err); }
    setBulkAdding(false);
  };

  const pending   = subs.filter(s => s.status === "pending");
  const approved  = subs.filter(s => s.status === "approved");
  const declined  = subs.filter(s => s.status === "declined");
  const cancelled = subs.filter(s => s.status === "cancelled");

  const matchesSearch = s => {
    if (!searchQuery.trim()) return true;
    const q = searchQuery.toLowerCase();
    return [s.name, s.contactName, s.email, s.genre, s.date, s.phone, s.payableTo]
      .some(v => (v || "").toLowerCase().includes(q));
  };

  const visibleSubs = subs
    .filter(s => (!activeFilter || s.status === activeFilter) && matchesSearch(s))
    .sort((a, b) => {
      if (sortBy === "oldest")           return (a.submitted || "").localeCompare(b.submitted || "");
      if (sortBy === "performance-date") return (a.dateRaw  || "").localeCompare(b.dateRaw  || "");
      if (sortBy === "name-az")  return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase());
      if (sortBy === "name-za")  return (b.name || "").toLowerCase().localeCompare((a.name || "").toLowerCase());
      return (b.submitted || "").localeCompare(a.submitted || ""); // newest first (default)
    });

  const visibleCalendarDates = dates.filter(d =>
    calendarFilter === "available" ? d.status === "available" :
    calendarFilter === "booked"    ? d.status === "booked"    : true
  );
  const allVisibleSelected = visibleCalendarDates.length > 0 && visibleCalendarDates.every(d => selectedDateIds.has(d.id));
  const someSelected       = selectedDateIds.size > 0;
  const selectedHasBooked  = [...selectedDateIds].some(id => dates.find(d => d.id === id)?.status === "booked");
  const selectedHasAvail   = [...selectedDateIds].some(id => dates.find(d => d.id === id)?.status === "available");

  return (
    <div style={{ maxWidth: 720, margin: "0 auto", padding: "32px 24px" }}>
      {contract       && <ContractModal sub={contract} onClose={() => setContract(null)} />}
      {counterOfferSub && <CounterOfferModal sub={counterOfferSub} onSubmit={submitCounterOffer} onClose={() => setCounterOfferSub(null)} />}

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 24, flexWrap: "wrap", gap: 16 }}>
        <h2 style={{ fontSize: 22, fontWeight: 500, margin: 0 }}>Booking dashboard</h2>
        <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 10 }}>
            {[["Pending", pending.length, "amber", "pending"], ["Approved", approved.length, "teal", "approved"], ["Declined", declined.length, "coral", "declined"], ["Cancelled", cancelled.length, "gray", "cancelled"]].map(([label, count, c, status]) => {
              const active = activeFilter === status;
              return (
                <button key={label} onClick={() => setActiveFilter(active ? null : status)}
                  style={{ textAlign: "center", padding: "10px 16px", borderRadius: 10, background: PALETTE[c].bg, border: `${active ? "2px" : "0.5px"} solid ${PALETTE[c].border}`, cursor: "pointer", boxShadow: active ? `0 0 0 2px ${PALETTE[c].border}22` : "none" }}>
                  <div style={{ fontSize: 22, fontWeight: 500, color: PALETTE[c].text }}>{count}</div>
                  <div style={{ fontSize: 12, color: PALETTE[c].text, opacity: 0.8 }}>{label}</div>
                </button>
              );
            })}
          </div>
          <button onClick={onSignOut} style={{ padding: "6px 14px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 12, color: "var(--color-text-secondary)" }}>Sign out</button>
        </div>
      </div>

      <div style={{ display: "flex", gap: 4, marginBottom: 20, borderBottom: "0.5px solid var(--color-border-tertiary)" }}>
        {["submissions", "calendar"].map(t => (
          <button key={t} onClick={() => setTab(t)} style={{ padding: "8px 16px", borderRadius: "8px 8px 0 0", border: "none", borderBottom: tab === t ? "2px solid var(--color-text-primary)" : "2px solid transparent", background: "transparent", cursor: "pointer", fontSize: 14, fontWeight: tab === t ? 500 : 400, color: tab === t ? "var(--color-text-primary)" : "var(--color-text-secondary)" }}>
            {t.charAt(0).toUpperCase() + t.slice(1)}
          </button>
        ))}
      </div>

      {tab === "submissions" && (
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {/* Search + sort toolbar */}
          <div style={{ display: "flex", gap: 10, marginBottom: 4 }}>
            <div style={{ flex: 1, position: "relative" }}>
              <input
                value={searchQuery}
                onChange={e => setSearchQuery(e.target.value)}
                placeholder="Search by name, email, date, genre…"
                style={{ width: "100%", boxSizing: "border-box", paddingRight: searchQuery ? 32 : 12 }}
              />
              {searchQuery && (
                <button onClick={() => setSearchQuery("")} style={{ position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", background: "none", border: "none", cursor: "pointer", fontSize: 16, color: "var(--color-text-secondary)", lineHeight: 1 }}>×</button>
              )}
            </div>
            <select value={sortBy} onChange={e => setSortBy(e.target.value)}
              style={{ padding: "8px 12px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-primary)", color: "var(--color-text-primary)", fontSize: 13, cursor: "pointer" }}>
              <option value="newest">Newest first</option>
              <option value="oldest">Oldest first</option>
              <option value="performance-date">Performance date</option>
              <option value="name-az">Name A–Z</option>
              <option value="name-za">Name Z–A</option>
            </select>
          </div>

          {/* Active filter + result count */}
          {(activeFilter || searchQuery) && (
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", fontSize: 13, color: "var(--color-text-secondary)" }}>
              <span>{visibleSubs.length} result{visibleSubs.length !== 1 ? "s" : ""}{activeFilter ? ` · ${activeFilter}` : ""}{searchQuery ? ` · "${searchQuery}"` : ""}</span>
              <button onClick={() => { setActiveFilter(null); setSearchQuery(""); }} style={{ fontSize: 12, padding: "2px 8px", borderRadius: 6, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", color: "var(--color-text-secondary)" }}>Clear</button>
            </div>
          )}

          {subs.length === 0 && (
            <div style={{ textAlign: "center", padding: "40px 24px", color: "var(--color-text-secondary)", fontSize: 14 }}>No submissions yet.</div>
          )}
          {subs.length > 0 && visibleSubs.length === 0 && (
            <div style={{ textAlign: "center", padding: "40px 24px", color: "var(--color-text-secondary)", fontSize: 14 }}>No submissions match your search or filter.</div>
          )}
          {visibleSubs.map(s => (
            <div key={s.id} style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 12, padding: "16px 18px" }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 10 }}>
                <div>
                  <div style={{ fontSize: 16, fontWeight: 500, marginBottom: 6 }}>{s.name}</div>
                  <div style={{ display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
                    {s.genre  && <Badge color="gray">{s.genre}</Badge>}
                    {s.date   && <Badge color="purple">{s.date}</Badge>}
                    {s.slot   && <Badge color="amber">{s.slot}</Badge>}
                    {s.venue  && <Badge color="teal">{VENUES.find(v => v.id === s.venue)?.label || s.venue}</Badge>}
                    {statusBadge(s.status)}
                  </div>
                </div>
                <div style={{ fontSize: 12, color: "var(--color-text-secondary)", whiteSpace: "nowrap" }}>Submitted {s.submitted}</div>
              </div>
              {s.bio && <p style={{ fontSize: 13, color: "var(--color-text-secondary)", margin: "0 0 10px", lineHeight: 1.5 }}>{s.bio}</p>}
              <div style={{ display: "flex", gap: 16, fontSize: 13, marginBottom: 10, flexWrap: "wrap" }}>
                {s.contactName && <span><span style={{ color: "var(--color-text-secondary)" }}>Rep: </span>{s.contactName}</span>}
                {s.email       && <span><span style={{ color: "var(--color-text-secondary)" }}>Email: </span>{s.email}</span>}
                {s.phone       && <span><span style={{ color: "var(--color-text-secondary)" }}>Phone: </span>{s.phone}</span>}
                {s.payableTo   && <span><span style={{ color: "var(--color-text-secondary)" }}>Payable to: </span>{s.payableTo}</span>}
              </div>
              <div style={{ display: "flex", gap: 16, fontSize: 13, marginBottom: 10, flexWrap: "wrap" }}>
                {s.draw       && <span><span style={{ color: "var(--color-text-secondary)" }}>Draw: </span>{s.draw}</span>}
                {s.performers && <span><span style={{ color: "var(--color-text-secondary)" }}>Performers: </span>{s.performers}</span>}
                {s.pay        && <span><span style={{ color: "var(--color-text-secondary)" }}>Pay: </span>{s.pay}</span>}
                {s.setLength  && <span><span style={{ color: "var(--color-text-secondary)" }}>Set: </span>{s.setLength}</span>}
                {s.sound      && <span><span style={{ color: "var(--color-text-secondary)" }}>Sound: </span>{s.sound === "house" ? "House system" : "Own sound"}</span>}
              </div>
              {(s.instagram || s.spotify || s.website || s.links) && (
                <div style={{ display: "flex", gap: 12, fontSize: 13, marginBottom: 10, flexWrap: "wrap" }}>
                  {s.instagram && <span><span style={{ color: "var(--color-text-secondary)" }}>IG: </span>{s.instagram}</span>}
                  {s.spotify   && <span><span style={{ color: "var(--color-text-secondary)" }}>Spotify: </span><a href={s.spotify} target="_blank" rel="noopener noreferrer" style={{ color: PALETTE.teal.text }}>{s.spotify}</a></span>}
                  {s.website   && <span><span style={{ color: "var(--color-text-secondary)" }}>Web: </span><a href={s.website} target="_blank" rel="noopener noreferrer" style={{ color: PALETTE.teal.text }}>{s.website}</a></span>}
                  {s.links && !s.website && <span><span style={{ color: "var(--color-text-secondary)" }}>Performance video: </span><a href={s.links} target="_blank" rel="noopener noreferrer" style={{ color: PALETTE.teal.text }}>{s.links}</a></span>}
                </div>
              )}
              {(s.logoUrl || s.photoUrl) && (
                <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>
                  {s.logoUrl  && <a href={s.logoUrl}  target="_blank" rel="noopener noreferrer" style={{ fontSize: 12, color: PALETTE.purple.text, border: `0.5px solid ${PALETTE.purple.border}`, background: PALETTE.purple.bg, padding: "3px 10px", borderRadius: 6, textDecoration: "none" }}>View logo</a>}
                  {s.photoUrl && <a href={s.photoUrl} target="_blank" rel="noopener noreferrer" style={{ fontSize: 12, color: PALETTE.purple.text, border: `0.5px solid ${PALETTE.purple.border}`, background: PALETTE.purple.bg, padding: "3px 10px", borderRadius: 6, textDecoration: "none" }}>View press photo</a>}
                </div>
              )}
              {s.status === "countered" && (
                <div style={{ padding: "10px 12px", borderRadius: 8, background: PALETTE.blue.bg, border: `0.5px solid ${PALETTE.blue.border}`, fontSize: 13, color: PALETTE.blue.text, marginBottom: 10 }}>
                  Counter offer sent: <strong>{s.counterPay}</strong>
                  {s.counterMessage && <span> — {s.counterMessage}</span>}
                </div>
              )}
              {(s.status === "pending" || s.status === "countered") && (
                <div style={{ display: "flex", gap: 8 }}>
                  <button onClick={() => approve(s.id)} style={{ padding: "6px 16px", borderRadius: 8, border: `0.5px solid ${PALETTE.teal.border}`,  background: PALETTE.teal.bg,  cursor: "pointer", fontSize: 13, color: PALETTE.teal.text,  fontWeight: 500 }}>Approve</button>
                  {s.status === "pending" && (
                    <button onClick={() => setCounterOfferSub(s)} style={{ padding: "6px 16px", borderRadius: 8, border: `0.5px solid ${PALETTE.blue.border}`, background: PALETTE.blue.bg, cursor: "pointer", fontSize: 13, color: PALETTE.blue.text, fontWeight: 500 }}>Counter</button>
                  )}
                  <button onClick={() => decline(s.id)} style={{ padding: "6px 16px", borderRadius: 8, border: `0.5px solid ${PALETTE.coral.border}`, background: PALETTE.coral.bg, cursor: "pointer", fontSize: 13, color: PALETTE.coral.text }}>Decline</button>
                </div>
              )}
              <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 6 }}>
                <button onClick={() => deleteSubmission(s.id)} style={{ fontSize: 11, padding: "2px 10px", borderRadius: 6, border: `0.5px solid ${PALETTE.coral.border}`, background: "transparent", cursor: "pointer", color: PALETTE.coral.text, opacity: 0.6 }}>Delete</button>
              </div>
              {s.status === "approved" && s.cancelRequested && (
                <div style={{ padding: "10px 12px", borderRadius: 8, background: PALETTE.amber.bg, border: `0.5px solid ${PALETTE.amber.border}`, fontSize: 13, color: PALETTE.amber.text, marginBottom: 10, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                  <span>⚠ Artist has requested cancellation</span>
                  <button onClick={() => callFn("updateSubmission", { id: s.id, cancelRequested: false })} style={{ fontSize: 12, padding: "3px 10px", borderRadius: 6, border: `0.5px solid ${PALETTE.amber.border}`, background: "transparent", cursor: "pointer", color: PALETTE.amber.text }}>Dismiss</button>
                </div>
              )}
              {s.status === "approved" && (
                <div style={{ display: "flex", gap: 8 }}>
                  <button onClick={() => setContract(s)} style={{ padding: "6px 16px", borderRadius: 8, border: `0.5px solid ${s.contractSigned ? PALETTE.teal.border : PALETTE.purple.border}`, background: s.contractSigned ? PALETTE.teal.bg : PALETTE.purple.bg, cursor: "pointer", fontSize: 13, color: s.contractSigned ? PALETTE.teal.text : PALETTE.purple.text, fontWeight: 500 }}>
                    {s.contractSigned ? "Contract signed ✓" : "Contract — awaiting signature"}
                  </button>
                  <button onClick={() => cancel(s.id)} style={{ padding: "6px 16px", borderRadius: 8, border: `0.5px solid ${PALETTE.coral.border}`, background: PALETTE.coral.bg, cursor: "pointer", fontSize: 13, color: PALETTE.coral.text }}>Cancel booking</button>
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {tab === "calendar" && (
        <div style={{ paddingBottom: 400 }}>
          <div style={{ padding: "16px 18px", borderRadius: 12, border: `0.5px solid ${PALETTE.purple.border}`, background: PALETTE.purple.bg, marginBottom: 20 }}>
            <div style={{ fontSize: 13, fontWeight: 500, color: PALETTE.purple.text, marginBottom: 10 }}>Default settings</div>
            <div style={{ fontSize: 13, color: PALETTE.purple.text, opacity: 0.8, marginBottom: 12 }}>Applied automatically to new dates. Use "Apply to all" to push to existing open dates.</div>
            <div style={{ fontSize: 12, color: PALETTE.purple.text, opacity: 0.7, marginBottom: 6 }}>Time slots:</div>
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 12 }}>
              {PRESET_TIMES.map(t => (
                <SlotPill key={t} time={t} selected={defaultSlots.includes(t)} onClick={() => toggleDefaultSlot(t)} />
              ))}
            </div>
            <div style={{ fontSize: 12, color: PALETTE.purple.text, opacity: 0.7, marginBottom: 6 }}>Venues:</div>
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 12 }}>
              {VENUES.map(v => {
                const active = defaultVenues.includes(v.id);
                return (
                  <button key={v.id} onClick={() => toggleDefaultVenue(v.id)}
                    style={{ padding: "6px 14px", borderRadius: 20, border: `0.5px solid ${active ? PALETTE.amber.border : "var(--color-border-secondary)"}`, background: active ? PALETTE.amber.bg : "var(--color-background-primary)", color: active ? PALETTE.amber.text : "var(--color-text-primary)", fontSize: 13, fontWeight: active ? 500 : 400, cursor: "pointer" }}>
                    {v.label}
                  </button>
                );
              })}
            </div>
            <div style={{ fontSize: 12, color: PALETTE.purple.text, opacity: 0.7, marginBottom: 6 }}>Default set length:</div>
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 14 }}>
              {SET_LENGTH_OPTIONS.map(opt => (
                <button key={opt} onClick={() => setDefaultSetLength(opt)}
                  style={{ padding: "6px 14px", borderRadius: 20, border: `0.5px solid ${defaultSetLength === opt ? PALETTE.teal.border : "var(--color-border-secondary)"}`, background: defaultSetLength === opt ? PALETTE.teal.bg : "var(--color-background-primary)", color: defaultSetLength === opt ? PALETTE.teal.text : "var(--color-text-primary)", fontSize: 13, fontWeight: defaultSetLength === opt ? 500 : 400, cursor: "pointer" }}>
                  {opt}
                </button>
              ))}
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <button onClick={applyToAll} style={{ padding: "7px 16px", borderRadius: 8, border: `0.5px solid ${PALETTE.purple.border}`, background: "var(--color-background-primary)", cursor: "pointer", fontSize: 13, color: PALETTE.purple.text, fontWeight: 500 }}>Apply to all open dates</button>
              {applyConfirm && <span style={{ fontSize: 13, color: PALETTE.teal.text, fontWeight: 500 }}>Done — all open dates updated</span>}
            </div>
          </div>

          {/* Status filter + select/action bar */}
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12, flexWrap: "wrap", gap: 10 }}>
            <div style={{ display: "flex", gap: 4 }}>
              {[["All", "all"], ["Open", "available"], ["Booked", "booked"]].map(([label, val]) => (
                <button key={val} onClick={() => { setCalendarFilter(val); setSelectedDateIds(new Set()); }}
                  style={{ padding: "5px 14px", borderRadius: 20, border: `0.5px solid ${calendarFilter === val ? "var(--color-border-primary)" : "var(--color-border-tertiary)"}`, background: calendarFilter === val ? "var(--color-background-secondary)" : "transparent", fontSize: 13, cursor: "pointer", fontWeight: calendarFilter === val ? 500 : 400, color: "var(--color-text-primary)" }}>
                  {label}
                  <span style={{ marginLeft: 5, opacity: 0.6, fontSize: 12 }}>
                    {val === "all" ? dates.length : dates.filter(d => d.status === val).length}
                  </span>
                </button>
              ))}
            </div>
            {someSelected && (
              <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
                <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>{selectedDateIds.size} selected</span>
                {selectedHasBooked  && <button onClick={handleBulkOpen}  style={{ padding: "5px 12px", borderRadius: 8, border: `0.5px solid ${PALETTE.teal.border}`,  background: PALETTE.teal.bg,  cursor: "pointer", fontSize: 12, color: PALETTE.teal.text,  fontWeight: 500 }}>Open</button>}
                {selectedHasAvail   && <button onClick={handleBulkBlock} style={{ padding: "5px 12px", borderRadius: 8, border: `0.5px solid ${PALETTE.gray.border}`,  background: PALETTE.gray.bg,  cursor: "pointer", fontSize: 12, color: PALETTE.gray.text              }}>Block</button>}
                <button onClick={handleBulkDelete} style={{ padding: "5px 12px", borderRadius: 8, border: `0.5px solid ${PALETTE.coral.border}`, background: PALETTE.coral.bg, cursor: "pointer", fontSize: 12, color: PALETTE.coral.text, fontWeight: 500 }}>Delete</button>
                <button onClick={() => setSelectedDateIds(new Set())} style={{ padding: "5px 8px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "transparent", cursor: "pointer", fontSize: 12, color: "var(--color-text-secondary)" }}>✕</button>
              </div>
            )}
          </div>

          <div style={{ display: "flex", flexDirection: "column", gap: 10, marginBottom: 20 }}>
            {/* Select-all row */}
            {visibleCalendarDates.length > 0 && (
              <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "4px 16px" }}>
                <input type="checkbox" checked={allVisibleSelected} onChange={() => {
                  if (allVisibleSelected) setSelectedDateIds(new Set());
                  else setSelectedDateIds(new Set(visibleCalendarDates.map(d => d.id)));
                }} style={{ cursor: "pointer", width: 15, height: 15 }} />
                <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>{allVisibleSelected ? "Deselect all" : `Select all ${visibleCalendarDates.length}`}</span>
              </div>
            )}
            {visibleCalendarDates.map(d => (
              <div key={d.id} style={{ borderRadius: 12, border: `0.5px solid ${selectedDateIds.has(d.id) ? "var(--color-border-primary)" : expandedDate === d.id ? "var(--color-border-primary)" : "var(--color-border-tertiary)"}`, background: selectedDateIds.has(d.id) ? "var(--color-background-secondary)" : "var(--color-background-primary)", overflow: "hidden" }}>
                <div style={{ display: "flex", alignItems: "center" }}>
                  <div onClick={e => e.stopPropagation()} style={{ padding: "0 0 0 16px", display: "flex", alignItems: "center" }}>
                    <input type="checkbox" checked={selectedDateIds.has(d.id)} onChange={() => toggleSelectDate(d.id)} style={{ cursor: "pointer", width: 15, height: 15 }} />
                  </div>
                  <div onClick={() => setExpandedDate(expandedDate === d.id ? null : d.id)}
                    style={{ flex: 1, display: "flex", justifyContent: "space-between", alignItems: "center", padding: "12px 16px 12px 10px", cursor: "pointer" }}>
                  <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
                    <span style={{ fontSize: 15, fontWeight: 500 }}>{d.label}</span>
                    {statusBadge(d.status)}
                    {d.artist && <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>{d.artist}</span>}
                  </div>
                  <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
                    {d.setLength && <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>{d.setLength}</span>}
                    <div style={{ display: "flex", gap: 4, flexWrap: "wrap", justifyContent: "flex-end" }}>
                      {(d.slots || []).map(s => <SlotPill key={s} time={s} selected={false} disabled={true} />)}
                      {(!d.slots || d.slots.length === 0) && <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>No slots set</span>}
                    </div>
                    <span style={{ fontSize: 18, color: "var(--color-text-secondary)", marginLeft: 8 }}>{expandedDate === d.id ? "▲" : "▼"}</span>
                  </div>
                  </div>
                </div>
                {expandedDate === d.id && (
                  <div style={{ padding: "12px 16px 16px", borderTop: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-secondary)" }}>
                    <div style={{ fontSize: 12, color: "var(--color-text-secondary)", marginBottom: 6 }}>Time slots:</div>
                    <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 12 }}>
                      {PRESET_TIMES.map(t => (
                        <SlotPill key={t} time={t} selected={(d.slots || []).includes(t)} onClick={() => toggleSlot(d.id, t)} />
                      ))}
                    </div>
                    <div style={{ fontSize: 12, color: "var(--color-text-secondary)", marginBottom: 6 }}>Venues:</div>
                    <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 12 }}>
                      {VENUES.map(v => {
                        const active = (d.venues || []).includes(v.id);
                        return (
                          <button key={v.id} onClick={() => toggleVenue(d.id, v.id)}
                            style={{ padding: "6px 14px", borderRadius: 20, border: `0.5px solid ${active ? PALETTE.teal.border : "var(--color-border-secondary)"}`, background: active ? PALETTE.teal.bg : "var(--color-background-primary)", color: active ? PALETTE.teal.text : "var(--color-text-primary)", fontSize: 13, fontWeight: active ? 500 : 400, cursor: "pointer" }}>
                            {v.label}
                          </button>
                        );
                      })}
                    </div>
                    <div style={{ fontSize: 12, color: "var(--color-text-secondary)", marginBottom: 6 }}>Set length:</div>
                    <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 14 }}>
                      {SET_LENGTH_OPTIONS.map(opt => (
                        <button key={opt} onClick={() => updateSetLength(d.id, opt)}
                          style={{ padding: "6px 14px", borderRadius: 20, border: `0.5px solid ${(d.setLength || "3 hours") === opt ? PALETTE.teal.border : "var(--color-border-secondary)"}`, background: (d.setLength || "3 hours") === opt ? PALETTE.teal.bg : "var(--color-background-primary)", color: (d.setLength || "3 hours") === opt ? PALETTE.teal.text : "var(--color-text-primary)", fontSize: 13, fontWeight: (d.setLength || "3 hours") === opt ? 500 : 400, cursor: "pointer" }}>
                          {opt}
                        </button>
                      ))}
                    </div>
                    <div style={{ display: "flex", gap: 10 }}>
                      {d.status === "available" && (
                        <button onClick={() => handleBlockDate(d.id)} style={{ fontSize: 12, padding: "5px 12px", borderRadius: 8, border: "0.5px solid var(--color-border-secondary)", background: "transparent", cursor: "pointer", color: "var(--color-text-secondary)" }}>Block date</button>
                      )}
                      {d.status === "booked" && (
                        <button onClick={() => handleUnblockDate(d.id)} style={{ fontSize: 12, padding: "5px 12px", borderRadius: 8, border: `0.5px solid ${PALETTE.teal.border}`, background: PALETTE.teal.bg, cursor: "pointer", color: PALETTE.teal.text }}>Open date</button>
                      )}
                      <button onClick={() => handleDeleteDate(d.id)} style={{ fontSize: 12, padding: "5px 12px", borderRadius: 8, border: `0.5px solid ${PALETTE.coral.border}`, background: "transparent", cursor: "pointer", color: PALETTE.coral.text }}>Delete date</button>
                    </div>
                  </div>
                )}
              </div>
            ))}
          </div>

          {/* Add by month */}
          <div style={{ padding: "18px 20px", borderRadius: 10, border: `0.5px solid ${PALETTE.purple.border}`, background: PALETTE.purple.bg }}>
            <div style={{ fontSize: 13, fontWeight: 500, color: PALETTE.purple.text, marginBottom: 14 }}>Add dates by month</div>
            <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 14, flexWrap: "wrap" }}>
              <div>
                <div style={{ fontSize: 12, color: PALETTE.purple.text, opacity: 0.7, marginBottom: 4 }}>Month</div>
                <input type="month" value={bulkMonth} onChange={e => setBulkMonth(e.target.value)}
                  style={{ padding: "6px 10px", borderRadius: 8, border: `0.5px solid ${PALETTE.purple.border}`, background: "var(--color-background-primary)", fontSize: 13 }} />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 12, color: PALETTE.purple.text, opacity: 0.7, marginBottom: 6 }}>Days of week</div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                  {["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].map((day, i) => {
                    const active = bulkDays.includes(i);
                    return (
                      <button key={day} onClick={() => setBulkDays(prev => active ? prev.filter(d => d !== i) : [...prev, i].sort())}
                        style={{ padding: "5px 11px", borderRadius: 20, border: `0.5px solid ${active ? PALETTE.amber.border : "var(--color-border-secondary)"}`, background: active ? PALETTE.amber.bg : "var(--color-background-primary)", color: active ? PALETTE.amber.text : "var(--color-text-primary)", fontSize: 13, fontWeight: active ? 500 : 400, cursor: "pointer" }}>
                        {day}
                      </button>
                    );
                  })}
                </div>
              </div>
            </div>
            {(() => {
              const preview = getBulkPreviewDates();
              return preview.length > 0 ? (
                <div style={{ fontSize: 13, color: PALETTE.purple.text, marginBottom: 12, opacity: 0.85 }}>
                  {preview.length} date{preview.length !== 1 ? "s" : ""} to add: {preview.slice(0, 6).map(d => new Date(d + "T12:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric" })).join(", ")}{preview.length > 6 ? ` +${preview.length - 6} more` : ""}
                </div>
              ) : (
                <div style={{ fontSize: 13, color: PALETTE.purple.text, marginBottom: 12, opacity: 0.6 }}>
                  {bulkDays.length === 0 ? "Select at least one day." : "All matching dates are already on the calendar."}
                </div>
              );
            })()}
            <div style={{ display: "flex", gap: 12, alignItems: "center" }}>
              <button onClick={handleBulkAddDates} disabled={bulkAdding || getBulkPreviewDates().length === 0}
                style={{ padding: "7px 18px", borderRadius: 8, border: `0.5px solid ${PALETTE.purple.border}`, background: "var(--color-background-primary)", cursor: getBulkPreviewDates().length > 0 && !bulkAdding ? "pointer" : "not-allowed", fontSize: 13, color: PALETTE.purple.text, fontWeight: 500, opacity: getBulkPreviewDates().length === 0 || bulkAdding ? 0.5 : 1 }}>
                {bulkAdding ? "Adding…" : `Add ${getBulkPreviewDates().length} date${getBulkPreviewDates().length !== 1 ? "s" : ""}`}
              </button>
              {bulkConfirm && <span style={{ fontSize: 13, color: PALETTE.teal.text, fontWeight: 500 }}>Done — dates added ✓</span>}
            </div>
          </div>

          {/* Add single date */}
          <div style={{ padding: "16px 18px", borderRadius: 10, border: "0.5px dashed var(--color-border-secondary)", background: "var(--color-background-secondary)" }}>
            <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 10 }}>Add single date</div>
            <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
              {(() => {
                const cy = new Date().getFullYear();
                const selectStyle = { padding: "7px 10px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-primary)", color: "var(--color-text-primary)", fontSize: 13, cursor: "pointer" };
                return (<>
                  <select value={newDateM} onChange={e => setNewDateM(e.target.value)} style={selectStyle}>
                    <option value="">Month</option>
                    {["01","02","03","04","05","06","07","08","09","10","11","12"].map((m, i) => (
                      <option key={m} value={m}>{["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"][i]}</option>
                    ))}
                  </select>
                  <select value={newDateD} onChange={e => setNewDateD(e.target.value)} style={selectStyle}>
                    <option value="">Day</option>
                    {Array.from({length:31},(_,i)=>String(i+1).padStart(2,"0")).map(d => (
                      <option key={d} value={d}>{parseInt(d)}</option>
                    ))}
                  </select>
                  <select value={newDateY} onChange={e => setNewDateY(e.target.value)} style={selectStyle}>
                    <option value="">Year</option>
                    {[cy, cy+1, cy+2].map(y => <option key={y} value={String(y)}>{y}</option>)}
                  </select>
                </>);
              })()}
              <button onClick={handleAddDate} style={{ padding: "7px 16px", borderRadius: 8, border: `0.5px solid ${PALETTE.amber.border}`, background: PALETTE.amber.bg, cursor: "pointer", fontSize: 13, color: PALETTE.amber.text, fontWeight: 500 }}>Add</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function CounterOfferResponse({ action, submissionId }) {
  const [sub, setSub] = useState(null);
  const [loading, setLoading] = useState(true);
  const [selected, setSelected] = useState(action); // "accept" | "decline"
  const [confirming, setConfirming] = useState(false);
  const [done, setDone] = useState(null); // "accepted" | "declined" | "error"

  useEffect(() => {
    const { db, doc, onSnapshot } = window.__firebase;
    return onSnapshot(
      doc(db, "submissions", submissionId),
      snap => { if (snap.exists()) setSub({ id: snap.id, ...snap.data() }); setLoading(false); },
      err  => { console.error(err); setLoading(false); }
    );
  }, [submissionId]);

  if (loading) return (
    <div style={{ textAlign: "center", padding: "80px 24px", color: "var(--color-text-secondary)", fontSize: 14 }}>Loading your offer…</div>
  );

  if (!sub) return (
    <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15 }}>This link is no longer valid.</p>
    </div>
  );

  // Already responded
  if (sub.status !== "countered") {
    const accepted = sub.status === "approved";
    return (
      <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
        <div style={{ width: 56, height: 56, borderRadius: "50%", background: accepted ? PALETTE.teal.bg : PALETTE.gray.bg, display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px", border: `0.5px solid ${accepted ? PALETTE.teal.border : PALETTE.gray.border}` }}>
          {accepted
            ? <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M5 12l5 5L19 7" stroke={PALETTE.teal.text} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
            : <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 18L18 6M6 6l12 12" stroke={PALETTE.gray.text} strokeWidth="2" strokeLinecap="round"/></svg>
          }
        </div>
        <h2 style={{ fontSize: 20, fontWeight: 500, margin: "0 0 10px" }}>{accepted ? "Booking confirmed" : "Offer declined"}</h2>
        <p style={{ color: "var(--color-text-secondary)", fontSize: 15, lineHeight: 1.6 }}>
          {accepted
            ? <>Your booking at Medusa Brewing is confirmed for <strong>{sub.date}</strong> at <strong>{sub.slot}</strong>.{" "}
                {sub.contractSigned
                  ? "You've already signed your performance agreement."
                  : <a href={`?sign=true&id=${submissionId}`} style={{ color: PALETTE.teal.text, fontWeight: 500 }}>Sign your performance agreement →</a>
                }
              </>
            : "You've already declined this offer."
          }
        </p>
      </div>
    );
  }

  if (done) {
    const accepted = done === "accepted";
    return (
      <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
        {done === "error" ? (
          <>
            <h2 style={{ fontSize: 20, fontWeight: 500, margin: "0 0 10px" }}>Something went wrong</h2>
            <p style={{ color: "var(--color-text-secondary)", fontSize: 15 }}>Please try again or contact Medusa Brewing directly.</p>
          </>
        ) : (
          <>
            <div style={{ width: 56, height: 56, borderRadius: "50%", background: accepted ? PALETTE.teal.bg : PALETTE.gray.bg, display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px", border: `0.5px solid ${accepted ? PALETTE.teal.border : PALETTE.gray.border}` }}>
              {accepted
                ? <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M5 12l5 5L19 7" stroke={PALETTE.teal.text} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
                : <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 18L18 6M6 6l12 12" stroke={PALETTE.gray.text} strokeWidth="2" strokeLinecap="round"/></svg>
              }
            </div>
            <h2 style={{ fontSize: 20, fontWeight: 500, margin: "0 0 10px" }}>{accepted ? "Offer accepted!" : "Offer declined"}</h2>
            <p style={{ color: "var(--color-text-secondary)", fontSize: 15, lineHeight: 1.6 }}>
              {accepted
                ? <>You've accepted the offer for <strong>{sub.date}</strong> at <strong>{sub.slot}</strong>. Please sign your performance agreement to confirm the booking:</>
                : "You've declined the counter offer. Thanks for your interest in performing at Medusa Brewing."
              }
            </p>
            {accepted && (
              <a href={`?sign=true&id=${submissionId}`} style={{ display: "inline-block", marginTop: 16, padding: "10px 24px", background: PALETTE.teal.bg, color: PALETTE.teal.text, border: `0.5px solid ${PALETTE.teal.border}`, borderRadius: 8, textDecoration: "none", fontWeight: 500, fontSize: 14 }}>Sign your agreement →</a>
            )}
          </>
        )}
      </div>
    );
  }

  return (
    <div style={{ maxWidth: 520, margin: "60px auto", padding: "0 24px" }}>
      <h2 style={{ fontSize: 22, fontWeight: 500, margin: "0 0 8px" }}>Counter offer from Medusa Brewing</h2>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15, margin: "0 0 24px" }}>
        Hi <strong style={{ color: "var(--color-text-primary)" }}>{sub.name}</strong>, Medusa Brewing has reviewed your booking request and made a counter offer.
      </p>
      <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 12, padding: "18px 20px", marginBottom: 20 }}>
        {[["Date", sub.date], ["Time", sub.slot], ["Set length", sub.setLength], ["Your requested pay", sub.pay], ["Counter offer", sub.counterPay]].map(([k, v]) => v && (
          <div key={k} style={{ display: "flex", justifyContent: "space-between", padding: "6px 0", borderBottom: "0.5px solid var(--color-border-tertiary)", fontSize: 14 }}>
            <span style={{ color: "var(--color-text-secondary)" }}>{k}</span>
            <span style={{ fontWeight: 500, color: k === "Counter offer" ? PALETTE.blue.text : "var(--color-text-primary)" }}>{v}</span>
          </div>
        ))}
        {sub.counterMessage && (
          <div style={{ padding: "10px 0 4px", fontSize: 13, color: "var(--color-text-secondary)", lineHeight: 1.5 }}>
            <strong style={{ color: "var(--color-text-primary)" }}>Note: </strong>{sub.counterMessage}
          </div>
        )}
      </div>
      <div style={{ display: "flex", gap: 8, marginBottom: 14 }}>
        {[["accept", "Accept offer", "teal"], ["decline", "Decline", "coral"]].map(([val, label, color]) => (
          <button key={val} onClick={() => setSelected(val)}
            style={{ flex: 1, padding: "10px 16px", borderRadius: 8, border: `0.5px solid ${selected === val ? PALETTE[color].border : "var(--color-border-secondary)"}`, background: selected === val ? PALETTE[color].bg : "var(--color-background-primary)", color: selected === val ? PALETTE[color].text : "var(--color-text-primary)", fontSize: 14, fontWeight: selected === val ? 500 : 400, cursor: "pointer" }}>
            {label}
          </button>
        ))}
      </div>
      <button disabled={!selected || confirming} onClick={async () => {
        setConfirming(true);
        try {
          const result = await callFn("respondToCounterOffer", {
            id: submissionId,
            response: selected === "accept" ? "accepted" : "declined",
          });
          if (result.success) setDone(selected === "accept" ? "accepted" : "declined");
          else setDone("error");
        } catch { setDone("error"); }
        setConfirming(false);
      }} style={{ width: "100%", padding: "11px 22px", borderRadius: 8, border: `0.5px solid ${selected && !confirming ? (selected === "accept" ? PALETTE.teal.border : PALETTE.coral.border) : "var(--color-border-tertiary)"}`, background: selected && !confirming ? (selected === "accept" ? PALETTE.teal.bg : PALETTE.coral.bg) : "transparent", cursor: selected && !confirming ? "pointer" : "not-allowed", fontSize: 14, color: selected && !confirming ? (selected === "accept" ? PALETTE.teal.text : PALETTE.coral.text) : "var(--color-text-secondary)", fontWeight: 500 }}>
        {confirming ? "Confirming…" : selected === "accept" ? "Confirm — Accept offer" : selected === "decline" ? "Confirm — Decline" : "Select an option above"}
      </button>
    </div>
  );
}

function ArtistManage({ submissionId }) {
  const [sub, setSub]               = useState(null);
  const [loading, setLoading]       = useState(true);
  const [form, setForm]             = useState({ contactName: "", phone: "", payableTo: "", bio: "", links: "", instagram: "", spotify: "", website: "" });
  const [newLogo, setNewLogo]       = useState(null);
  const [newPhoto, setNewPhoto]     = useState(null);
  const [saving, setSaving]         = useState(false);
  const [saved, setSaved]           = useState(false);
  const [saveError, setSaveError]   = useState(null);
  const [requesting, setRequesting] = useState(false);
  const [requested, setRequested]   = useState(false);

  useEffect(() => {
    const { db, doc, onSnapshot } = window.__firebase;
    return onSnapshot(
      doc(db, "submissions", submissionId),
      snap => {
        if (snap.exists()) {
          const d = { id: snap.id, ...snap.data() };
          setSub(d);
          setForm({ contactName: d.contactName || "", phone: d.phone || "", payableTo: d.payableTo || "", bio: d.bio || "", links: d.links || "", instagram: d.instagram || "", spotify: d.spotify || "", website: d.website || "" });
        }
        setLoading(false);
      },
      err => { console.error(err); setLoading(false); }
    );
  }, [submissionId]);

  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const save = async () => {
    setSaving(true); setSaved(false); setSaveError(null);
    try {
      const { storage, ref, uploadBytes, getDownloadURL } = window.__firebase;
      let logoUrl = sub.logoUrl || null, photoUrl = sub.photoUrl || null;
      if (newLogo) {
        const r = ref(storage, `press-kits/${Date.now()}-logo-${newLogo.name}`);
        await uploadBytes(r, newLogo); logoUrl = await getDownloadURL(r);
      }
      if (newPhoto) {
        const r = ref(storage, `press-kits/${Date.now()}-photo-${newPhoto.name}`);
        await uploadBytes(r, newPhoto); photoUrl = await getDownloadURL(r);
      }
      const result = await callFn("updateBooking", { id: submissionId, ...form, logoUrl, photoUrl });
      if (result.success) { setSaved(true); setNewLogo(null); setNewPhoto(null); setTimeout(() => setSaved(false), 3000); }
      else setSaveError("Failed to save. Please try again.");
    } catch { setSaveError("Failed to save. Please try again."); }
    setSaving(false);
  };

  const requestCancel = async () => {
    if (!window.confirm("Send a cancellation request to Medusa Brewing? They will confirm and you'll receive a follow-up email.")) return;
    setRequesting(true);
    try {
      const result = await callFn("requestCancellation", { id: submissionId });
      if (result.success) setRequested(true);
    } catch { /* silent */ }
    setRequesting(false);
  };

  if (loading) return <div style={{ textAlign: "center", padding: "80px 24px", color: "var(--color-text-secondary)", fontSize: 14 }}>Loading your booking…</div>;
  if (!sub || !["approved", "cancelled"].includes(sub.status)) return (
    <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15 }}>This booking management link is no longer valid.</p>
    </div>
  );
  if (sub.status === "cancelled") return (
    <div style={{ maxWidth: 480, margin: "80px auto", textAlign: "center", padding: "0 24px" }}>
      <div style={{ width: 56, height: 56, borderRadius: "50%", background: PALETTE.gray.bg, display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 20px", border: `0.5px solid ${PALETTE.gray.border}` }}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 18L18 6M6 6l12 12" stroke={PALETTE.gray.text} strokeWidth="2" strokeLinecap="round"/></svg>
      </div>
      <h2 style={{ fontSize: 20, fontWeight: 500, margin: "0 0 10px" }}>Booking cancelled</h2>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 15, lineHeight: 1.6, margin: "0 0 24px" }}>Your booking for <strong>{sub.date}</strong> at <strong>{sub.slot}</strong> has been cancelled.</p>
      <a href="https://booking.medusabrewing.com" style={{ fontSize: 14, color: PALETTE.teal.text }}>View available dates →</a>
    </div>
  );

  return (
    <div style={{ maxWidth: 600, margin: "40px auto", padding: "0 24px 60px" }}>
      <h2 style={{ fontSize: 22, fontWeight: 500, margin: "0 0 6px" }}>Manage your booking</h2>
      <p style={{ color: "var(--color-text-secondary)", fontSize: 14, margin: "0 0 24px" }}>Update your contact info, press kit, or request a cancellation.</p>

      {/* Booking summary */}
      <div style={{ background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)", borderRadius: 12, padding: "16px 20px", marginBottom: 20 }}>
        <div style={{ fontSize: 13, fontWeight: 500, color: "var(--color-text-secondary)", marginBottom: 10, textTransform: "uppercase", letterSpacing: 0.5 }}>Your booking</div>
        {[["Date", sub.date], ["Time", sub.slot], ["Set length", sub.setLength], ["Performance fee", sub.counterPay || sub.pay], ["Sound", sub.sound === "house" ? "House system" : "Bringing own sound"]].map(([k, v]) => v && (
          <div key={k} style={{ display: "flex", justifyContent: "space-between", padding: "5px 0", borderBottom: "0.5px solid var(--color-border-tertiary)", fontSize: 14 }}>
            <span style={{ color: "var(--color-text-secondary)" }}>{k}</span>
            <span style={{ fontWeight: 500 }}>{v}</span>
          </div>
        ))}
        <div style={{ marginTop: 10, display: "flex", gap: 8, alignItems: "center" }}>
          {statusBadge(sub.status)}
          {sub.contractSigned && <Badge color="teal">Contract signed ✓</Badge>}
          {!sub.contractSigned && <a href={`?sign=true&id=${submissionId}`} style={{ fontSize: 12, color: PALETTE.teal.text, textDecoration: "underline" }}>Sign contract →</a>}
        </div>
      </div>

      {/* Cancel requested notice */}
      {(sub.cancelRequested || requested) && (
        <div style={{ padding: "12px 16px", borderRadius: 10, background: PALETTE.amber.bg, border: `0.5px solid ${PALETTE.amber.border}`, fontSize: 14, color: PALETTE.amber.text, marginBottom: 20 }}>
          ⚠ Cancellation request sent — Medusa Brewing has been notified and will be in touch.
        </div>
      )}

      {/* Editable fields */}
      <div style={{ display: "flex", flexDirection: "column", gap: 14, marginBottom: 24 }}>
        <div style={{ fontSize: 14, fontWeight: 500, color: "var(--color-text-primary)", borderBottom: "0.5px solid var(--color-border-tertiary)", paddingBottom: 8 }}>Contact information</div>
        {[["Contact person", "contactName", "text"], ["Phone", "phone", "tel"], ["Make payment payable to", "payableTo", "text"]].map(([label, key, type]) => (
          <div key={key}>
            <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>{label}</label>
            <input type={type} value={form[key]} onChange={e => upd(key, e.target.value)} style={{ width: "100%", boxSizing: "border-box" }} />
          </div>
        ))}
        <div style={{ fontSize: 14, fontWeight: 500, color: "var(--color-text-primary)", borderBottom: "0.5px solid var(--color-border-tertiary)", paddingBottom: 8, marginTop: 8 }}>Press kit</div>
        <div>
          <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>Bio / description</label>
          <textarea value={form.bio} onChange={e => upd("bio", e.target.value)} rows={4} style={{ width: "100%", boxSizing: "border-box", padding: "8px 12px", borderRadius: 8, border: "0.5px solid var(--color-border-tertiary)", background: "var(--color-background-primary)", color: "var(--color-text-primary)", fontSize: 14, resize: "vertical" }} />
        </div>
        {[["Instagram handle", "instagram"], ["Spotify / streaming link", "spotify"], ["Website", "website"], ["Other links", "links"]].map(([label, key]) => (
          <div key={key}>
            <label style={{ fontSize: 13, color: "var(--color-text-secondary)", display: "block", marginBottom: 4 }}>{label}</label>
            <input value={form[key]} onChange={e => upd(key, e.target.value)} style={{ width: "100%", boxSizing: "border-box" }} />
          </div>
        ))}
        {[["Logo (PNG or SVG)", "logo", setNewLogo, newLogo, sub.logoUrl, 2], ["Press photo", "photo", setNewPhoto, newPhoto, sub.photoUrl, 5]].map(([label, key, setter, file, existing, maxMB]) => (
          <div key={key} style={{ padding: "16px", borderRadius: 10, border: "0.5px dashed var(--color-border-secondary)", background: "var(--color-background-secondary)" }}>
            <div style={{ fontSize: 13, color: "var(--color-text-secondary)", marginBottom: 6 }}>
              {label} <span style={{ opacity: 0.6 }}>(max {maxMB}MB)</span>
              {existing && <span style={{ color: PALETTE.teal.text, fontWeight: 500 }}> — on file</span>}
            </div>
            <input type="file" accept="image/*" onChange={e => {
              const f = e.target.files[0];
              if (f && f.size > maxMB * 1024 * 1024) {
                alert(`${label} must be under ${maxMB}MB. Your file is ${(f.size / 1024 / 1024).toFixed(1)}MB.`);
                e.target.value = "";
                return;
              }
              setter(f || null);
            }} style={{ fontSize: 13 }} />
            {file && <div style={{ fontSize: 12, color: PALETTE.teal.text, marginTop: 4 }}>New file selected: {file.name}</div>}
          </div>
        ))}
        {saveError && <p style={{ fontSize: 13, color: PALETTE.coral.text, margin: 0 }}>{saveError}</p>}
        <button onClick={save} disabled={saving} style={{ padding: "10px 24px", borderRadius: 8, border: `0.5px solid ${PALETTE.teal.border}`, background: PALETTE.teal.bg, cursor: saving ? "not-allowed" : "pointer", fontSize: 14, color: PALETTE.teal.text, fontWeight: 500 }}>
          {saving ? "Saving…" : saved ? "Saved ✓" : "Save changes"}
        </button>
      </div>

      {/* Cancel request */}
      {!sub.cancelRequested && !requested && (
        <div style={{ padding: "20px", borderRadius: 12, border: `0.5px solid ${PALETTE.coral.border}`, background: PALETTE.coral.bg }}>
          <div style={{ fontSize: 14, fontWeight: 500, color: PALETTE.coral.text, marginBottom: 6 }}>Cancel booking</div>
          <p style={{ fontSize: 13, color: PALETTE.coral.text, margin: "0 0 14px", lineHeight: 1.6, opacity: 0.85 }}>This sends a cancellation request to Medusa Brewing. They will confirm and send you a follow-up email. 14-day notice required.</p>
          <button onClick={requestCancel} disabled={requesting} style={{ padding: "8px 20px", borderRadius: 8, border: `0.5px solid ${PALETTE.coral.border}`, background: "var(--color-background-primary)", cursor: requesting ? "not-allowed" : "pointer", fontSize: 13, color: PALETTE.coral.text, fontWeight: 500 }}>
            {requesting ? "Sending…" : "Request cancellation"}
          </button>
        </div>
      )}
    </div>
  );
}

function App() {
  const params       = new URLSearchParams(window.location.search);
  const respondParam = params.get("respond");
  const respondId    = params.get("id");
  const signParam    = params.get("sign");
  const signId       = params.get("id");
  const manageParam  = params.get("manage");
  const manageId     = params.get("id");
  const adminParam   = params.get("admin");
  const isResponse   = (respondParam === "accept" || respondParam === "decline") && !!respondId;
  const isSign       = signParam === "true" && !!signId;
  const isManage     = manageParam === "true" && !!manageId;
  const isAdmin      = adminParam === "true";

  const [view, setView] = useState(isSign ? "sign" : isManage ? "manage" : isResponse ? "respond" : isAdmin ? "admin" : "artist");
  const [dates, setDates] = useState([]);
  const [datesLoading, setDatesLoading] = useState(true);
  const [pendingCount, setPendingCount] = useState(0);
  const [adminAuthed, setAdminAuthed] = useState(() => localStorage.getItem("adminAuthed") === "true");
  const [showAdminAuth, setShowAdminAuth] = useState(isAdmin && localStorage.getItem("adminAuthed") !== "true");

  useEffect(() => {
    fetch(`${FUNCTIONS_BASE}/getAvailableDates`)
      .then(r => r.json())
      .then(data => { if (data.dates) setDates(data.dates); })
      .catch(err => console.error("Failed to load dates:", err))
      .finally(() => setDatesLoading(false));
  }, []);

  useEffect(() => {
    const { db, onSnapshot, doc } = window.__firebase;
    return onSnapshot(doc(db, "meta/notifications"), d => {
      if (d.exists()) setPendingCount(d.data()?.pendingCount || 0);
    });
  }, []);

  const handleSignOut = () => {
    localStorage.removeItem("adminAuthed");
    setAdminAuthed(false);
    setView("artist");
  };

  return (
    <div style={{ minHeight: "100vh", background: "var(--color-background-tertiary)", fontFamily: "var(--font-sans)" }}>
      {showAdminAuth && (
        <AdminAuthModal
          onSuccess={() => { setAdminAuthed(true); setShowAdminAuth(false); setView("admin"); }}
          onClose={() => { setShowAdminAuth(false); setView("artist"); }}
        />
      )}
      <Nav view={view} setView={setView} />
      {view === "sign"
        ? <ContractSign submissionId={signId} />
        : view === "manage"
        ? <ArtistManage submissionId={manageId} />
        : view === "respond"
        ? <CounterOfferResponse action={respondParam} submissionId={respondId} />
        : datesLoading
          ? <div style={{ textAlign: "center", padding: "60px 24px", color: "var(--color-text-secondary)", fontSize: 14 }}>Loading available dates…</div>
          : view === "artist"
            ? <ArtistPortal dates={dates} />
            : <AdminDashboard dates={dates} setDates={setDates} onSignOut={handleSignOut} />
      }
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
