/* ============================================================
   SVLM — My Bookings + Tracking. Ported from public/index.html's
   loadMyBookings()/renderMyBookingsList()/renderTracker()/cancelBooking()
   — same real GET /bookings/mine, same tracker stages, same PATCH
   /bookings/:id/cancel with the same refund-eligibility confirm copy.
   Crew chat/favorite/edit-booking/photo-upload from that version are
   out of scope for this pass (noted in the plan as a later slice);
   this covers the core list + status tracking + cancel + review entry.
   ============================================================ */
const Pmb = window.PALETTE;

const TRACKER_STAGES = ['confirmed', 'enroute', 'arrived', 'inprogress', 'completed'];
const CANCELLABLE = ['pending', 'confirmed'];
const BADGE_COLORS = { success: ['#e6f6f0', '#0fa37f'], info: ['#e8f0fe', '#2a63d8'], warning: ['#fdf3d9', '#b8790a'], danger: ['#fde8e8', '#c62d2d'], neutral: [Pmb?.lineSoft || '#f5efe7', Pmb?.muted || '#7c6b5b'] };
const BADGE_VARIANT = {
  completed: 'success', paid: 'success', pending: 'warning', confirmed: 'info', enroute: 'info',
  arrived: 'info', inprogress: 'info', cancelled: 'danger',
};

// `label` lets a caller show friendlier text while still colour-coding off the raw status —
// used by DeliveryLegs, whose internal states ('draft', 'in_progress') aren't customer language.
function Badge({ status, label }) {
  const variant = BADGE_VARIANT[String(status || '').toLowerCase()] || 'neutral';
  const [bg, fg] = BADGE_COLORS[variant];
  return <span style={{ background: bg, color: fg, borderRadius: 999, padding: '3px 10px', fontSize: 11, fontWeight: 700, textTransform: 'capitalize' }}>{label || status}</span>;
}

function Tracker({ status }) {
  const idx = TRACKER_STAGES.indexOf(status);
  if (idx === -1) return null;
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', margin: '14px 0 4px' }}>
      {TRACKER_STAGES.map((stage, i) => {
        const state = i < idx ? 'done' : i === idx ? 'current' : 'todo';
        const color = state === 'todo' ? Pmb.line : Pmb.primary;
        return (
          <div key={stage} style={{ flex: 1, textAlign: 'center', position: 'relative' }}>
            {i > 0 && <div style={{ position: 'absolute', top: 5, right: '50%', width: '100%', height: 2, background: i <= idx ? Pmb.primary : Pmb.line, zIndex: 0 }} />}
            <div style={{ width: 12, height: 12, borderRadius: 99, background: color, margin: '0 auto', position: 'relative', zIndex: 1, border: state === 'current' ? `2px solid ${Pmb.primary}` : 'none', boxShadow: state === 'current' ? `0 0 0 3px ${Pmb.tintBlue}` : 'none' }} />
            <div style={{ fontSize: 9.5, fontWeight: state === 'todo' ? 500 : 700, color: state === 'todo' ? Pmb.faint : Pmb.ink, marginTop: 5 }}>{t('customer', `tracker_${stage}`)}</div>
          </div>
        );
      })}
    </div>
  );
}

// Pickup/return legs for services that need items collected or transported (laundry, Move House).
// Only fetched when the booking's service actually uses delivery — every other booking skips the
// request entirely rather than every card firing one.
// Our internal job states aren't customer-facing language — 'draft' means "we've planned this leg
// but haven't dispatched a driver yet", which reads as jargon, and the rest are snake_case.
const DELIVERY_STATUS_LABELS = {
  draft: 'delivery_status_scheduled',
  locating_driver: 'delivery_status_locating',
  driver_accepted: 'delivery_status_assigned',
  in_progress: 'delivery_status_on_the_way',
  completed: 'delivery_status_done',
  cancelled: 'delivery_status_cancelled',
  failed: 'delivery_status_failed',
};
const DELIVERY_STATUS_FALLBACK = {
  draft: 'Scheduled', locating_driver: 'Finding driver', driver_accepted: 'Driver assigned',
  in_progress: 'On the way', completed: 'Done', cancelled: 'Cancelled', failed: 'Failed',
};

function DeliveryLegs({ app, bookingId }) {
  const [legs, setLegs] = React.useState(null);
  React.useEffect(() => {
    api(`/delivery/mine/${bookingId}`).then(setLegs).catch(() => setLegs([]));
  }, [bookingId]);

  if (!legs || legs.length === 0) return null;
  return (
    <div style={{ marginTop: 10, paddingTop: 10, borderTop: `1px solid ${Pmb.lineSoft}` }}>
      {legs.map((leg) => (
        <div key={leg.id} style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 6 }}>
          <span style={{ fontSize: 11.5, color: Pmb.muted, fontWeight: 700 }}>
            {leg.leg === 'pickup' ? (t('customer', 'delivery_pickup') || 'Pickup') : (t('customer', 'delivery_return') || 'Return')}
          </span>
          <Badge status={leg.status} label={t('customer', DELIVERY_STATUS_LABELS[leg.status]) || DELIVERY_STATUS_FALLBACK[leg.status] || leg.status} />
          {leg.driver_name && <span style={{ fontSize: 11.5, color: Pmb.faint }}>{leg.driver_name}</span>}
          {leg.tracking_url && (
            <a href={leg.tracking_url} target="_blank" rel="noopener" style={{ fontSize: 11.5, color: Pmb.primary, fontWeight: 700, textDecoration: 'none' }}>
              {t('customer', 'delivery_track') || 'Track'}
            </a>
          )}
          {leg.failed_delivery_reason && (
            <span style={{ fontSize: 11.5, color: '#c62d2d' }}>{leg.failed_delivery_reason}</span>
          )}
        </div>
      ))}
    </div>
  );
}

function BookingCard({ app, b, onChanged }) {
  const location = [b.area_label, b.city_name].filter(Boolean).join(', ');
  const cancel = async () => {
    const appt = new Date(`${String(b.scheduled_date).slice(0, 10)}T${b.scheduled_time}`);
    const hoursUntil = (appt.getTime() - Date.now()) / 36e5;
    const msgKey = Number.isNaN(hoursUntil)
      ? 'confirm_cancel_booking'
      : hoursUntil >= 5 ? 'confirm_cancel_refund_eligible' : 'confirm_cancel_no_refund_credit';
    const msg = t('customer', msgKey);
    if (!window.confirm(msg)) return;
    try {
      await api(`/bookings/${b.id}/cancel`, { method: 'PATCH' });
      onChanged();
    } catch (e) {
      alert(e.message);
    }
  };

  return (
    <Card style={{ marginBottom: 14 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, color: Pmb.faint, fontWeight: 700, marginBottom: 10 }}>
        <span>ID{b.id}</span><span>{fmtDate(b.scheduled_date, app.lang)}</span>
      </div>
      <div style={{ display: 'flex', gap: 12 }}>
        <Photo src={b.service_image_url} h={54} r={12} style={{ width: 54, flexShrink: 0 }} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <b style={{ fontSize: 13.5, color: Pmb.ink }}>{b.service_name_en}{b.tier_label ? ` - ${b.tier_label}` : ''}</b>
            <Badge status={b.status} />
          </div>
          {location && <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: Pmb.faint, marginTop: 4 }}><Icon name="pin" size={13} color={Pmb.faint} />{location}</div>}
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: Pmb.faint, marginTop: 3 }}><Icon name="clock" size={13} color={Pmb.faint} />{String(b.scheduled_time).slice(0, 5)}</div>
          <div style={{ fontWeight: 800, fontSize: 14, color: Pmb.primary, marginTop: 5 }}>{fmtThb(b.total_thb)}</div>
        </div>
      </div>
      <Tracker status={b.status} />
      {b.delivery_mode && <DeliveryLegs app={app} bookingId={b.id} />}
      {b.staff_name && (
        <div style={{ fontSize: 12, color: Pmb.muted, marginTop: 8 }}>{t('customer', 'crew_label') || 'Crew:'} <b style={{ color: Pmb.ink }}>{b.staff_name}</b></div>
      )}
      <div style={{ display: 'flex', gap: 8, marginTop: 12, flexWrap: 'wrap' }}>
        {b.status === 'completed' && (
          <button onClick={() => app.go('booking', { id: b.service_id })} style={{ padding: '8px 14px', borderRadius: 12, border: `1.5px solid ${Pmb.line}`, background: '#fff', fontWeight: 700, fontSize: 12.5, color: Pmb.ink, cursor: 'pointer' }}>{t('customer', 'book_again') || 'Book again'}</button>
        )}
        {b.status === 'completed' && (
          <button onClick={() => app.go('review', { bookingId: b.id, serviceName: b.service_name_en })} style={{ padding: '8px 14px', borderRadius: 12, border: `1.5px solid ${Pmb.line}`, background: '#fff', fontWeight: 700, fontSize: 12.5, color: Pmb.ink, cursor: 'pointer' }}>{t('customer', 'leave_review') || 'Leave a review'}</button>
        )}
        {CANCELLABLE.includes(b.status) && (
          <button onClick={cancel} style={{ padding: '8px 14px', borderRadius: 12, border: '1.5px solid #f3caca', background: '#fff', fontWeight: 700, fontSize: 12.5, color: '#d23a3a', cursor: 'pointer' }}>{t('customer', 'cancel_booking') || 'Cancel booking'}</button>
        )}
        {b.staff_id && (
          <button onClick={() => app.go('chat-thread', { kind: 'booking', bookingId: b.id, name: b.staff_name, online: null })} style={{ padding: '8px 14px', borderRadius: 12, border: `1.5px solid ${Pmb.line}`, background: '#fff', fontWeight: 700, fontSize: 12.5, color: Pmb.ink, cursor: 'pointer' }}>{t('customer', 'chat_with_svlm') || 'Chat'}</button>
        )}
        {b.bill_type && b.pay_status === 'paid' && (
          <button onClick={() => downloadBookingInvoice(b.id)} style={{ padding: '8px 14px', borderRadius: 12, border: `1.5px solid ${Pmb.line}`, background: '#fff', fontWeight: 700, fontSize: 12.5, color: Pmb.ink, cursor: 'pointer' }}>{t('customer', 'download_invoice') || 'Download tax invoice'}</button>
        )}
      </div>
    </Card>
  );
}

async function downloadBookingInvoice(bookingId) {
  const token = localStorage.getItem('svlm_token');
  const res = await fetch(`/api/bookings/${bookingId}/invoice.pdf`, { headers: { Authorization: `Bearer ${token}` } });
  if (!res.ok) { const body = await res.json().catch(() => ({})); alert(body.error || (t('customer', 'invoice_generate_failed') || 'Could not generate invoice.')); return; }
  const blob = await res.blob();
  window.open(URL.createObjectURL(blob), '_blank');
}

function MyBookingsScreen({ app }) {
  const [filter, setFilter] = React.useState('upcoming');
  const [bookings, setBookings] = React.useState(null);

  const load = () => api('/bookings/mine').then(setBookings).catch(() => setBookings([]));
  React.useEffect(() => { load(); }, []);

  if (bookings === null) return <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', color: Pmb.muted }}>Loading…</div>;

  const filtered = bookings.filter(b => {
    if (filter === 'completed') return b.status === 'completed';
    if (filter === 'cancelled') return b.status === 'cancelled';
    return b.status !== 'completed' && b.status !== 'cancelled';
  });

  return (
    <div>
      <AppHeader onBack={app.back} title={t('customer', 'my_bookings_title') || 'My bookings'} />
      <div style={{ padding: '0 20px 10px', display: 'flex', gap: 8 }}>
        <Chip on={filter === 'upcoming'} onClick={() => setFilter('upcoming')}>{app.lang === 'th' ? 'กำลังจะถึง' : 'Upcoming'}</Chip>
        <Chip on={filter === 'completed'} onClick={() => setFilter('completed')}>{app.lang === 'th' ? 'เสร็จสิ้น' : 'Completed'}</Chip>
        <Chip on={filter === 'cancelled'} onClick={() => setFilter('cancelled')}>{app.lang === 'th' ? 'ยกเลิกแล้ว' : 'Cancelled'}</Chip>
      </div>
      <div style={{ padding: '10px 20px 40px' }}>
        {filtered.length === 0 ? (
          <div style={{ textAlign: 'center', padding: '50px 0', color: Pmb.faint }}>
            <Icon name="cal" size={42} color={Pmb.line} />
            <div style={{ marginTop: 12, fontSize: 14, fontWeight: 600 }}>
              {filter === 'upcoming' ? (t('customer', 'no_bookings') || 'No upcoming bookings yet.')
                : filter === 'completed' ? (t('customer', 'no_bookings_completed') || 'No completed bookings yet.')
                : (t('customer', 'no_bookings_cancelled') || 'No cancelled bookings.')}
            </div>
            {filter === 'upcoming' && (
              <Btn style={{ marginTop: 16, maxWidth: 200, margin: '16px auto 0' }} onClick={() => app.go('tab-home')}>{t('customer', 'tab_home') || 'Home'}</Btn>
            )}
          </div>
        ) : (
          filtered.map(b => <BookingCard key={b.id} app={app} b={b} onChanged={load} />)
        )}
      </div>
    </div>
  );
}

Object.assign(window, { MyBookingsScreen, Tracker, Badge });
