// Bookings.jsx — date-bucketed (Yesterday/Today/Tomorrow/Day After) + category-grouped + status dots
// Replaces WorkOrders.jsx as the primary booking list

const DATE_TABS = [
  { id: 'yesterday',  label: 'Yesterday',     date: addDaysISO(TODAY, -1) },
  { id: 'today',      label: 'Today',         date: TODAY },
  { id: 'tomorrow',   label: 'Tomorrow',      date: addDaysISO(TODAY, 1) },
  { id: 'dayafter',   label: 'Day After Tmrw',date: addDaysISO(TODAY, 2) },
  { id: 'plus3',      label: '+3 Days',       date: addDaysISO(TODAY, 3) },
];

function fmtDateLong(iso) {
  const d = new Date(iso + 'T00:00:00');
  return d.toLocaleDateString('en-GB', { weekday: 'short', day: '2-digit', month: 'short' });
}

function machineStatusFor(machineRef) {
  // machineRef looks like "PLC-001 Tadano GR-500EX"
  const id = (machineRef || '').split(' ')[0];
  const m = MACHINES.find(x => x.id === id);
  return m ? m.status : 'unavailable';
}

const MSTATUS = {
  available:   { color: 'green', label: 'Available' },
  occupied:    { color: 'red',   label: 'Booked' },
  unavailable: { color: 'gray',  label: 'Not available' },
};

function BookingsPage({ role, setPage }) {
  const [activeTab, setActiveTab] = React.useState('today');
  const [swapFrom, setSwapFrom] = React.useState(null); // booking object
  const [modifyTarget, setModifyTarget] = React.useState(null); // { machine, booking } object
  const [, forceRender] = React.useReducer(x => x + 1, 0);

  const applySwap = (fromId, toId, fields) => {
    const a = BOOKINGS.find(x => x.id === fromId);
    const b = BOOKINGS.find(x => x.id === toId);
    if (!a || !b) return;
    if (fields.operator) { const t = a.operator; a.operator = b.operator; b.operator = t; }
    if (fields.rigger)   { const t = a.rigger;   a.rigger   = b.rigger;   b.rigger   = t; }
    if (fields.machine) {
      ['machine','plate','category','tonnage'].forEach(k => {
        const t = a[k]; a[k] = b[k]; b[k] = t;
      });
    }
    forceRender();
  };

  const applyDelete = (bookingId) => {
    const i = BOOKINGS.findIndex(x => x.id === bookingId);
    if (i >= 0) BOOKINGS.splice(i, 1);
    forceRender();
  };

  const applyModify = (machineId, bookingId, patch) => {
    if (patch.machineStatus) {
      const m = MACHINES.find(x => x.id === machineId);
      if (m) m.status = patch.machineStatus;
    }
    if (bookingId) {
      const b = BOOKINGS.find(x => x.id === bookingId);
      if (b) {
        ['customer','contact','phone','location','start','end','shift'].forEach(k => {
          if (patch[k] !== undefined) b[k] = patch[k];
        });
      }
    }
    forceRender();
  };

  // Per-tab availability counts: how many machines are AVAILABLE (not booked, not in workshop) per category
  const tabCounts = {};
  DATE_TABS.forEach(t => {
    const bookedIds = new Set(BOOKINGS.filter(b => b.date === t.date).map(b => (b.machine || '').split(' ')[0]));
    const avail = MACHINES.filter(m => m.status !== 'unavailable' && !bookedIds.has(m.id));
    tabCounts[t.id] = {
      C: avail.filter(m => m.category === 'Mobile Crane').length,
      S: avail.filter(m => m.category === 'Skylift').length,
    };
  });

  const activeDate = DATE_TABS.find(t => t.id === activeTab).date;
  const bookingsOnDate = BOOKINGS.filter(b => b.date === activeDate);

  // Build slot rows per machine per day. Each machine can produce 1–2 rows:
  //   - Full-day booking          → 1 row "Booked"
  //   - Morning-only booking      → 2 rows: "Booked" (8am–12pm) + "Available" (1pm–5pm)
  //   - Afternoon-only booking    → 2 rows: "Available" (8am–12pm) + "Booked" (1pm–5pm)
  //   - No booking                → 1 row "Available"
  //   - Workshop / leave          → 1 row "Not available"
  // This way half-day bookings automatically surface the remaining free half.
  const buildRowsForMachine = (m) => {
    if (m.status === 'unavailable') {
      return [{
        machine: m, booking: null,
        day: { color: 'gray', label: 'Not available', kind: 'unavailable' },
        slot: null,
      }];
    }
    const dayBookings = bookingsOnDate.filter(b => (b.machine || '').split(' ')[0] === m.id);
    if (dayBookings.length === 0) {
      return [{
        machine: m, booking: null,
        day: { color: 'green', label: 'Available', kind: 'available' },
        slot: null,
      }];
    }
    // Has at least one booking — figure out which shifts are taken
    const morn = dayBookings.find(b => b.shift === 'morning');
    const aft  = dayBookings.find(b => b.shift === 'afternoon');
    const custom = dayBookings.find(b => b.shift === 'custom');
    // Treat custom as full-day occupation (most common case)
    if (custom) {
      return dayBookings.map(b => ({
        machine: m, booking: b,
        day: { color: 'red', label: 'Booked', kind: 'occupied' },
        slot: null,
      }));
    }
    const rows = [];
    if (morn) {
      rows.push({ machine: m, booking: morn,
        day: { color: 'red', label: 'Booked', kind: 'occupied' }, slot: 'morning' });
    } else {
      rows.push({ machine: m, booking: null,
        day: { color: 'green', label: 'Available', kind: 'available' }, slot: 'morning' });
    }
    if (aft) {
      rows.push({ machine: m, booking: aft,
        day: { color: 'red', label: 'Booked', kind: 'occupied' }, slot: 'afternoon' });
    } else {
      rows.push({ machine: m, booking: null,
        day: { color: 'green', label: 'Available', kind: 'available' }, slot: 'afternoon' });
    }
    return rows;
  };

  // Sort: available first, then booked, then not available (machine-level)
  const statusOrder = { available: 0, occupied: 1, unavailable: 2 };
  const machineRank = (m) => {
    if (m.status === 'unavailable') return 2;
    const has = bookingsOnDate.some(b => (b.machine || '').split(' ')[0] === m.id);
    return has ? 1 : 0;
  };
  const sortedMachines = [...MACHINES].sort((a, b) => machineRank(a) - machineRank(b));

  // Group by category — every machine appears every day, possibly with 2 rows
  const grouped = CATEGORIES.map(cat => ({
    cat,
    items: sortedMachines.filter(m => m.category === cat.name).flatMap(buildRowsForMachine),
  })).filter(g => g.items.length > 0);

  const isAdmin = role === 'Admin';
  const isMgmt  = role === 'Management';

  return (
    <div className="page">
      {/* Sticky header — booking-status legend + action bar + date tabs */}
      <div className="bookings-sticky">
      {/* Action bar */}
      <div className="page-actions" style={{marginBottom: 16}}>
        <div style={{display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap'}}>
          <strong style={{color: 'var(--color-navy)', fontSize: 12, textTransform: 'uppercase', letterSpacing: '0.06em', marginRight: 4}}>Booking status:</strong>
          <span className="status status--green">Available</span>
          <span className="status status--red">Booked</span>
          <span className="status status--gray">Not available</span>
        </div>
        <div style={{display: 'flex', gap: 8}}>
          {isAdmin ? (
            <>
              <button className="btn btn--ghost" onClick={() => {
                // Generate availability for all machines for next 14 days starting today.
                // In a real backend this writes "available" slot records; here we just
                // confirm the sweep ran successfully against current data.
                const todayD = new Date(TODAY + 'T00:00:00');
                const days = [];
                for (let i = 0; i < 14; i++) {
                  const d = new Date(todayD); d.setDate(d.getDate() + i);
                  days.push(d.toISOString().slice(0, 10));
                }
                let totalSlots = 0;
                let bookedSlots = 0;
                MACHINES.forEach(m => {
                  days.forEach(d => {
                    totalSlots++;
                    if (BOOKINGS.some(b => b.date === d && (b.machine || '').split(' ')[0] === m.id)) bookedSlots++;
                  });
                });
                const free = totalSlots - bookedSlots;
                alert(`Availability generated.\n\n${MACHINES.length} machines × 14 days = ${totalSlots} slots\n  ✓ ${free} available\n  ● ${bookedSlots} booked\n\nMissing machine records back-filled into the next 2 weeks.`);
              }}>
                <Activity size={16}/> Create Availability
              </button>
              <button className="btn btn--primary" onClick={() => setPage('create')}>
                <Plus size={16}/> New Booking
              </button>
            </>
          ) : (
            <span className="restricted-tag" title="Only Admin can create new bookings — centralized control">
              <Lock size={12}/> Booking creation: Admin only
            </span>
          )}
        </div>
      </div>

      {/* Date tabs */}
      <div className="date-tabs">
        {DATE_TABS.map(t => (
          <button
            key={t.id}
            className={"date-tab " + (activeTab === t.id ? "date-tab--active" : "")}
            onClick={() => setActiveTab(t.id)}
          >
            <div className="date-tab__label">{t.label}</div>
            <div className="date-tab__date">{fmtDateLong(t.date)}</div>
            <div className="date-tab__count" style={{display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap'}}>
              <span className="date-tab__count-pill" title="Mobile Cranes available">{tabCounts[t.id].C}C</span>
              <span className="date-tab__count-pill" title="Skylifts available" style={{background: '#2B6CB0', color: '#fff'}}>{tabCounts[t.id].S}S</span>
              <span className="status status--green" style={{padding: '2px 8px', fontSize: 10}}>Available</span>
            </div>
          </button>
        ))}
      </div>

      {/* Column header — frozen with the legend + tabs above the scrolling list */}
      <div className="bk-head">
        <div>Status</div>
        <div>Machine / Operator</div>
        <div>Company / Contact</div>
        <div>Location</div>
        <div>Shift</div>
        <div style={{textAlign: 'right'}}>Actions</div>
      </div>
      </div>
      {/* /Sticky header */}

      {/* Category groups — every machine appears every day, with extra rows for half-day slots */}
      {grouped.map(g => {
        const bookedCount = g.items.filter(x => x.booking).length;
        const machineCount = new Set(g.items.map(x => x.machine.id)).size;
        return (
        <div key={g.cat.id} className="cat-group">
          <div className="cat-group__header">
            <div className="cat-group__swatch" style={{background: g.cat.color}}/>
            <div className="cat-group__name">{g.cat.name}</div>
            <div className="cat-group__count">{machineCount} machine{machineCount === 1 ? '' : 's'} · {bookedCount} booked</div>
          </div>
          {g.items.map(({ machine: m, booking: b, day: ms, slot }, idx) => {
            const muted = { color: 'var(--color-grey-400)', fontStyle: 'italic' };
            const slotLabel = slot === 'morning' ? '8am–12pm' : slot === 'afternoon' ? '1pm–5pm' : null;
            return (
              <div key={m.id + '-' + (b ? b.id : (slot || 'full')) + '-' + idx}
                className="bk-row"
                onClick={() => {
                  if (!canEdit(role, 'bookings')) return;
                  if (ms.kind === 'available') {
                    // Hand off the machine selection to CreateWO via a window-level
                    // payload — CreateWO picks it up on mount and clears it.
                    window.__createPrefill = { machineId: m.id, date: activeDate, blank: true };
                    setPage('create');
                    return;
                  }
                  if (b) {
                    // Modify an existing booking → open the full Create-Booking
                    // form in edit mode so the detail fields are identical.
                    window.__createPrefill = { editBooking: b };
                    setPage('create');
                    return;
                  }
                  setModifyTarget({ machine: m, booking: b });
                }}
                style={{cursor: canEdit(role, 'bookings') ? 'pointer' : 'default'}}>
                <div>
                  {b ? (
                    <div className="bk-row__id" style={{fontSize: 13, color: 'var(--color-navy)', fontWeight: 700, marginBottom: 4}}>{b.id}</div>
                  ) : (
                    <div className="bk-row__id" style={{fontSize: 12, color: 'var(--color-grey-400)', fontWeight: 600, marginBottom: 4}}>{m.id}{slot ? ' · ' + (slot === 'morning' ? 'AM' : 'PM') : ''}</div>
                  )}
                  <span className={"status status--" + ms.color}>{ms.label}</span>
                </div>
                <div>
                  <div style={{fontWeight: 600, fontSize: 13}}>{machineLabel(m)}</div>
                  <div className="bk-row__sub">{m.id}</div>
                  {b ? (
                    <div style={{marginTop: 6, paddingTop: 6, borderTop: '1px solid var(--color-grey-100)'}}>
                      <div style={{fontSize: 13}}>{b.operator}</div>
                      <div className="bk-row__sub">Rigger: {b.rigger}</div>
                    </div>
                  ) : null}
                </div>
                <div>
                  {b ? (
                    <>
                      <div className="bk-row__customer">{b.customer}</div>
                      <div className="bk-row__sub">{b.contact} · {b.phone}</div>
                    </>
                  ) : (
                    <div style={muted}>—</div>
                  )}
                </div>
                <div>
                  {b ? (
                    <div style={{fontWeight: 600, fontSize: 13}}>{b.location}</div>
                  ) : (
                    <div style={muted}>—</div>
                  )}
                </div>
                <div>
                  {b ? (
                    <>
                      <div className="bk-row__time">{b.start}–{b.end}</div>
                      <div className="bk-row__shift-pill">
                        {b.shift === 'morning' ? '8am–12pm' : b.shift === 'afternoon' ? '1pm–5pm' : 'Custom'}
                      </div>
                    </>
                  ) : slotLabel ? (
                    <>
                      <div className="bk-row__time" style={{color: 'var(--color-grey-500)'}}>{slotLabel}</div>
                      <div className="bk-row__shift-pill" style={{background: 'rgba(34,197,94,0.12)', color: '#15803d'}}>Free slot</div>
                    </>
                  ) : (
                    <div style={muted}>—</div>
                  )}
                </div>
                <div style={{display: 'flex', gap: 6, justifyContent: 'flex-end', flexWrap: 'wrap'}} onClick={(e) => e.stopPropagation()}>
                  {b ? (
                    <>
                      <button className="btn btn--ghost" style={{padding: '6px 10px', fontSize: 11, color: 'var(--color-navy)'}}
                        onClick={() => setSwapFrom(b)} title="Swap operator / rigger / machine with another booking">
                        <Activity size={12}/> Switch
                      </button>
                      {isMgmt ? (
                        <button className="btn btn--ghost" style={{padding: '6px 10px', color: '#dc2626'}} title="Delete (Management only)">
                          <Trash2 size={14}/>
                        </button>
                      ) : null}
                    </>
                  ) : ms.kind === 'available' && isAdmin ? (
                    <button className="btn btn--ghost" style={{padding: '6px 10px', fontSize: 11, color: 'var(--color-navy)'}}
                      onClick={(e) => {
                        e.stopPropagation();
                        window.__createPrefill = { machineId: m.id, date: activeDate, blank: true };
                        setPage('create');
                      }} title="Create booking for this machine">
                      <Plus size={12}/> Book
                    </button>
                  ) : null}
                </div>
              </div>
            );
          })}
        </div>
        );
      })}

      {/* Permission footer hint */}
      <div style={{marginTop: 16, fontSize: 12, color: 'var(--color-grey-500)', textAlign: 'center', display: 'flex', gap: 16, justifyContent: 'center', flexWrap: 'wrap'}}>
        <span><Lock size={11} style={{verticalAlign: 'middle'}}/> Create: Admin only</span>
        <span><Lock size={11} style={{verticalAlign: 'middle'}}/> Delete: Management only</span>
        <span><Lock size={11} style={{verticalAlign: 'middle'}}/> Edit: Admin</span>
      </div>

      {/* Switch / swap dialog */}
      {swapFrom ? (
        <SwapDialog from={swapFrom} bookingsOnDate={bookingsOnDate} applySwap={applySwap} onClose={() => setSwapFrom(null)}/>
      ) : null}

      {/* Modify dialog */}
      {modifyTarget ? (
        <ModifyDialog target={modifyTarget} applyModify={applyModify} applyDelete={applyDelete} role={role} onClose={() => setModifyTarget(null)}/>
      ) : null}
    </div>
  );
}

// Swap dialog — pick another booking to exchange operator/rigger/machine with
function SwapDialog({ from, bookingsOnDate, applySwap, onClose }) {
  const others = bookingsOnDate.filter(b => b.id !== from.id);
  const [pickId, setPickId] = React.useState(null);
  const [whatToSwap, setWhatToSwap] = React.useState({ operator: true, rigger: true, machine: true });
  const [confirmed, setConfirmed] = React.useState(false);

  const pick = others.find(b => b.id === pickId);

  const toggle = (k) => setWhatToSwap({ ...whatToSwap, [k]: !whatToSwap[k] });

  const swapList = Object.entries(whatToSwap).filter(([_, v]) => v).map(([k]) => k);

  const confirm = () => {
    if (!pick || swapList.length === 0) return;
    applySwap(from.id, pick.id, whatToSwap);
    setConfirmed(true);
    setTimeout(onClose, 1400);
  };

  return (
    <div className="install-modal" onClick={onClose}>
      <div className="install-modal__card" onClick={(e) => e.stopPropagation()} style={{maxWidth: 640}}>
        <div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16}}>
          <div>
            <div style={{fontWeight: 700, fontSize: 18, color: 'var(--color-navy)'}}>Switch / Swap Booking</div>
            <div style={{fontSize: 12, color: 'var(--color-grey-500)', marginTop: 2}}>
              Exchange operator, rigger, or machine between two bookings on the same day.
            </div>
          </div>
          <button className="install-banner__close" onClick={onClose}><X size={18}/></button>
        </div>

        {/* From booking */}
        <div style={{padding: 12, background: 'var(--color-grey-50)', border: '1px solid var(--color-grey-200)', borderRadius: 8, marginBottom: 12}}>
          <div style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-500)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 4}}>From</div>
          <div style={{display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12, fontSize: 13}}>
            <div><strong>{from.id}</strong><br/><span style={{color: 'var(--color-grey-600)'}}>{from.customer}</span></div>
            <div>{bookingMachineLabel(from)}</div>
            <div>Op: {from.operator}<br/>Rg: {from.rigger}</div>
          </div>
        </div>

        {/* To picker */}
        <div style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-500)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 6}}>Swap with</div>
        <div style={{maxHeight: 220, overflowY: 'auto', border: '1px solid var(--color-grey-200)', borderRadius: 8, marginBottom: 16}}>
          {others.length === 0 ? (
            <div style={{padding: 24, textAlign: 'center', color: 'var(--color-grey-500)', fontSize: 13}}>
              No other bookings on this day to swap with.
            </div>
          ) : others.map(b => (
            <label key={b.id} style={{
              display: 'grid', gridTemplateColumns: '24px 1fr 1fr 1fr', gap: 8, padding: '10px 12px',
              borderBottom: '1px solid var(--color-grey-100)', alignItems: 'center', cursor: 'pointer',
              background: pickId === b.id ? 'rgba(255,213,0,0.10)' : 'transparent',
            }}>
              <input type="radio" name="swapPick" checked={pickId === b.id} onChange={() => setPickId(b.id)}/>
              <div style={{fontSize: 13}}>
                <strong>{b.id}</strong><br/>
                <span style={{color: 'var(--color-grey-600)', fontSize: 12}}>{b.customer}</span>
              </div>
              <div style={{fontSize: 12}}>
                {bookingMachineLabel(b)}
              </div>
              <div style={{fontSize: 12}}>
                Op: {b.operator}<br/>
                Rg: {b.rigger}
              </div>
            </label>
          ))}
        </div>

        {/* What to swap */}
        {pick ? (
          <>
            <div style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-500)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8}}>What to swap</div>
            <div style={{display: 'flex', gap: 8, marginBottom: 16, flexWrap: 'wrap'}}>
              {['operator', 'rigger', 'machine'].map(k => (
                <button key={k} type="button"
                  className={"radio-chip " + (whatToSwap[k] ? "radio-chip--active" : "")}
                  onClick={() => toggle(k)}
                  style={{textTransform: 'capitalize'}}>
                  {whatToSwap[k] ? '✓ ' : ''}{k}
                </button>
              ))}
            </div>

            {confirmed ? (
              <div style={{padding: 14, background: 'rgba(34,197,94,0.10)', border: '1px solid rgba(34,197,94,0.3)', borderRadius: 8, color: '#15803d', fontSize: 13, marginBottom: 12}}>
                <Check size={14} style={{verticalAlign: 'middle'}}/> <strong>Swap applied.</strong> Both operators have been notified via push. The change is logged in the audit trail.
              </div>
            ) : null}

            <div style={{padding: 12, background: 'rgba(255,213,0,0.08)', border: '1px solid rgba(255,213,0,0.3)', borderRadius: 8, fontSize: 12, color: 'var(--color-grey-700)', lineHeight: 1.5, marginBottom: 16}}>
              <strong>Preview:</strong> {swapList.length === 0 ? 'Select at least one field to swap.' :
                <>Will exchange <strong>{swapList.join(', ')}</strong> between <code style={{fontSize: 11}}>{from.id}</code> and <code style={{fontSize: 11}}>{pick.id}</code>. Operators &amp; riggers affected will receive push notification immediately.</>
              }
            </div>
          </>
        ) : null}

        <div style={{display: 'flex', gap: 8, justifyContent: 'flex-end'}}>
          <button className="btn btn--ghost" onClick={onClose}>Cancel</button>
          <button className="btn btn--primary"
            disabled={!pick || swapList.length === 0 || confirmed}
            style={(!pick || swapList.length === 0 || confirmed) ? {opacity: 0.5, cursor: 'not-allowed'} : {}}
            onClick={confirm}>
            <Activity size={14}/> {confirmed ? 'Swapped' : 'Confirm Swap'}
          </button>
        </div>
      </div>
    </div>
  );
}

// Modify dialog — change machine status + booking details (time / customer / location)
function ModifyDialog({ target, applyModify, applyDelete, role, onClose }) {
  const { machine: m, booking: b } = target;
  const [machineStatus, setMachineStatus] = React.useState(m.status);
  const [shift, setShift] = React.useState(b ? b.shift : 'custom');
  const [start, setStart] = React.useState(b ? b.start : '');
  const [end, setEnd] = React.useState(b ? b.end : '');
  const [customer, setCustomer] = React.useState(b ? b.customer : '');
  const [contact, setContact] = React.useState(b ? b.contact : '');
  const [phone, setPhone] = React.useState(b ? b.phone : '');
  const [location, setLocation] = React.useState(b ? b.location : '');
  const [saved, setSaved] = React.useState(false);

  const setShiftOption = (id) => {
    setShift(id);
    if (id === 'morning')   { setStart('08:00'); setEnd('12:00'); }
    if (id === 'afternoon') { setStart('13:00'); setEnd('17:00'); }
  };

  // "Available" is locked when the booking has ANY input in the order section.
  // Logic: if the form has a customer / contact / phone / location filled in,
  //   you can't flip status to Available because that contradicts having data.
  const orderHasInput = !!(b && (customer.trim() || contact.trim() || phone.trim() || location.trim()));

  const save = () => {
    const patch = { machineStatus };
    if (b) {
      Object.assign(patch, { customer, contact, phone, location, start, end, shift });
    }
    applyModify(m.id, b ? b.id : null, patch);
    setSaved(true);
    setTimeout(onClose, 1000);
  };

  // Live overlap detection (only relevant when modifying a booking's time).
  // Check 3 kinds: machine, operator, rigger.
  let conflict = null;
  let conflictKind = null;
  if (b) {
    let c = findBookingOverlap({ plate: m.plate, date: b.date, start, end, excludeId: b.id });
    if (c) { conflict = c; conflictKind = 'machine'; }
    if (!conflict) {
      c = findOperatorOverlap({ operator: b.operator, date: b.date, start, end, excludeId: b.id });
      if (c) { conflict = c; conflictKind = 'operator'; }
    }
    if (!conflict && b.rigger && b.rigger !== '—') {
      c = findRiggerOverlap({ rigger: b.rigger, date: b.date, start, end, excludeId: b.id });
      if (c) { conflict = c; conflictKind = 'rigger'; }
    }
  }

  return (
    <div className="install-modal" onClick={onClose}>
      <div className="install-modal__card" onClick={(e) => e.stopPropagation()} style={{maxWidth: 580}}>
        <div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16}}>
          <div>
            <div style={{fontWeight: 700, fontSize: 18, color: 'var(--color-navy)'}}>Modify {b ? 'Booking' : 'Machine'}</div>
            <div style={{fontSize: 12, color: 'var(--color-grey-500)', marginTop: 2}}>
              {m.id} · {machineLabel(m)}
              {b ? <> · <code style={{fontSize: 11, background: 'var(--color-grey-100)', padding: '1px 5px', borderRadius: 3}}>{b.id}</code></> : null}
            </div>
          </div>
          <button className="install-banner__close" onClick={onClose}><X size={18}/></button>
        </div>

        {/* Machine status */}
        <div style={{marginBottom: 16}}>
          <label style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-600)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 6}}>
            Machine Status
          </label>
          <div style={{display: 'flex', gap: 8}}>
            {[
              {id: 'available',   label: 'Available',     pill: 'green'},
              {id: 'occupied',    label: 'Booked',        pill: 'red'},
              {id: 'unavailable', label: 'Not available', pill: 'gray'},
            ].map(opt => {
              // Lock BOTH "Available" and "Not available" when the order has input —
              // those states contradict the booking actually having data attached.
              const lockChoice = orderHasInput && (opt.id === 'available' || opt.id === 'unavailable');
              return (
                <button key={opt.id} type="button"
                  disabled={lockChoice}
                  className={"radio-chip " + (machineStatus === opt.id ? "radio-chip--active" : "")}
                  onClick={() => !lockChoice && setMachineStatus(opt.id)}
                  style={{flex: 1, opacity: lockChoice ? 0.45 : 1, cursor: lockChoice ? 'not-allowed' : 'pointer'}}
                  title={lockChoice ? 'Cannot change to ' + opt.label + ' — order section has input. Delete the booking to free this slot.' : undefined}>
                  <span className={"status status--" + opt.pill} style={{padding: '2px 8px'}}>{opt.label}</span>
                </button>
              );
            })}
          </div>
          {orderHasInput ? (
            <div style={{fontSize: 11, color: 'var(--color-grey-500)', marginTop: 6, display: 'flex', alignItems: 'center', gap: 4}}>
              <Lock size={11}/> "Available" and "Not available" are locked while order has input. Delete the order to free this slot.
            </div>
          ) : null}
          {!b && machineStatus === 'occupied' ? (
            <div style={{fontSize: 11, color: 'var(--color-danger)', marginTop: 6}}>
              ⚠ Marking as Booked without a booking record creates a manual occupied flag. Prefer creating a real booking via the Book button.
            </div>
          ) : null}
        </div>

        {b ? (
          <>
            {/* Shift / time */}
            <div style={{marginBottom: 16}}>
              <label style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-600)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 6}}>Shift &amp; Time</label>
              <div style={{display: 'flex', gap: 6, marginBottom: 8}}>
                {[{id:'morning',l:'8am–12pm'},{id:'afternoon',l:'1pm–5pm'},{id:'custom',l:'Custom'}].map(o => (
                  <button key={o.id} type="button" className={"radio-chip " + (shift === o.id ? "radio-chip--active" : "")} onClick={() => setShiftOption(o.id)} style={{flex: 1}}>{o.l}</button>
                ))}
              </div>
              <div style={{display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8}}>
                <div>
                  <div style={{fontSize: 11, color: 'var(--color-grey-500)', marginBottom: 2}}>Start</div>
                  <input type="time" className="input" value={start} disabled={shift !== 'custom'} onChange={e => setStart(e.target.value)} style={{width: '100%'}}/>
                </div>
                <div>
                  <div style={{fontSize: 11, color: 'var(--color-grey-500)', marginBottom: 2}}>End</div>
                  <input type="time" className="input" value={end} disabled={shift !== 'custom'} onChange={e => setEnd(e.target.value)} style={{width: '100%'}}/>
                </div>
              </div>
            </div>

            {/* Customer */}
            <div style={{marginBottom: 16}}>
              <label style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-600)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 6}}>Customer</label>
              <input className="input" value={customer} onChange={e => setCustomer(e.target.value)} placeholder="Company name" style={{width: '100%', marginBottom: 8}}/>
              <div style={{display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8}}>
                <input className="input" value={contact} onChange={e => setContact(e.target.value)} placeholder="Contact person"/>
                <input className="input" value={phone}   onChange={e => setPhone(e.target.value)}   placeholder="Phone"/>
              </div>
            </div>

            {/* Location */}
            <div style={{marginBottom: 16}}>
              <label style={{fontSize: 11, fontWeight: 700, color: 'var(--color-grey-600)', textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: 6}}>Job Location</label>
              <input className="input" value={location} onChange={e => setLocation(e.target.value)} placeholder="Site address / plot" style={{width: '100%'}}/>
            </div>
          </>
        ) : null}

        {saved ? (
          <div style={{padding: 12, background: 'rgba(34,197,94,0.10)', border: '1px solid rgba(34,197,94,0.3)', borderRadius: 8, color: '#15803d', fontSize: 13, marginBottom: 12}}>
            <Check size={14} style={{verticalAlign: 'middle'}}/> Changes saved · operator notified via push.
          </div>
        ) : null}

        {conflict && !saved ? (
          <div style={{padding: 12, background: '#fef2f2', border: '1px solid #fecaca', borderLeft: '4px solid #dc2626', borderRadius: 8, color: '#991b1b', fontSize: 12, marginBottom: 12, lineHeight: 1.5}}>
            <div style={{display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4}}>
              <AlertTriangle size={14}/>
              <strong>
                {conflictKind === 'machine' ? 'Machine time conflict'
                : conflictKind === 'operator' ? 'Operator time conflict'
                : 'Rigger time conflict'}
              </strong>
            </div>
            {conflictKind === 'machine' ? (
              <>Plate <strong>{m.plate}</strong> {start}–{end} clashes with <code style={{fontSize: 11, background: '#fff5f5', padding: '0 4px', borderRadius: 3}}>{conflict.id}</code> ({conflict.start}–{conflict.end} · {conflict.customer}).</>
            ) : conflictKind === 'operator' ? (
              <>Operator <strong>{b.operator}</strong> already on <code style={{fontSize: 11, background: '#fff5f5', padding: '0 4px', borderRadius: 3}}>{conflict.id}</code> ({conflict.start}–{conflict.end} · plate {conflict.plate}).</>
            ) : (
              <>Rigger <strong>{b.rigger}</strong> already on <code style={{fontSize: 11, background: '#fff5f5', padding: '0 4px', borderRadius: 3}}>{conflict.id}</code> ({conflict.start}–{conflict.end} · plate {conflict.plate}).</>
            )}
            {' '}Adjust the time before saving.
          </div>
        ) : null}

        <div style={{display: 'flex', gap: 8, justifyContent: 'flex-end', alignItems: 'center'}}>
          {b ? (
            <button type="button" className="btn btn--ghost"
              style={{color: '#dc2626', marginRight: 'auto'}}
              onClick={() => {
                if (confirm(`Delete booking ${b.id}?\n\nCustomer: ${b.customer}\nMachine: ${b.machine} (plate ${b.plate})\nDate: ${b.date} ${b.start}–${b.end}\n\nThis cannot be undone.`)) {
                  applyDelete(b.id);
                  onClose();
                }
              }}>
              <Trash2 size={14}/> Delete Booking
            </button>
          ) : null}
          <button className="btn btn--ghost" onClick={onClose}>Cancel</button>
          <button className="btn btn--primary"
            disabled={saved || !!conflict}
            style={(saved || conflict) ? {opacity: 0.5, cursor: 'not-allowed'} : {}}
            onClick={save}>
            <Check size={14}/> {saved ? 'Saved' : 'Save Changes'}
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { BookingsPage });
