/* global React, Icons, AppContext, DB, SB */
const { useState, useRef, useEffect, useContext, useMemo, useCallback, createElement: h, Fragment } = React;

const escapePrintableHtml = (value) => typeof window.escapeHtml === 'function'
  ? window.escapeHtml(value)
  : String(value ?? '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');

const printableText = (value, fallback = '—') => {
  const normalized = String(value ?? '').trim();
  return escapePrintableHtml(normalized || fallback);
};

const printableMultiline = (value, fallback = '') => printableText(value, fallback).replace(/\r?\n/g, '<br/>');

const openPrintableWindow = ({ title, bodyHtml, features }) => {
  if (typeof window.openPrintWindow === 'function') {
    return window.openPrintWindow({ title, bodyHtml, features });
  }
  return null;
};

const GLOBAL_XRAY_STORAGE_KEY = 'senan-global-xrays';

function makeGlobalPreviewDataUrl(title, subtitle) {
  const safeTitle = String(title || '').replace(/[<>&]/g, '');
  const safeSubtitle = String(subtitle || '').replace(/[<>&]/g, '');
  const svg = `
    <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="900" viewBox="0 0 1200 900">
      <defs>
        <linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
          <stop offset="0%" stop-color="#0891b2" stop-opacity="0.2"/>
          <stop offset="100%" stop-color="#0f172a" stop-opacity="0.92"/>
        </linearGradient>
      </defs>
      <rect width="1200" height="900" rx="40" fill="url(#g)"/>
      <text x="600" y="350" text-anchor="middle" fill="#ffffff" font-size="78" font-family="Arial" font-weight="700">${safeTitle}</text>
      <text x="600" y="440" text-anchor="middle" fill="#dbeafe" font-size="40" font-family="Arial">${safeSubtitle}</text>
      <text x="600" y="580" text-anchor="middle" fill="#e2e8f0" font-size="32" font-family="Arial">SENAN CLINIC</text>
    </svg>`;
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
}

async function readFileAsDataUrl(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result || ''));
    reader.onerror = () => reject(reader.error || new Error('File read failed'));
    reader.readAsDataURL(file);
  });
}

async function compressImageDataUrl(dataUrl, maxSize = 1600, quality = 0.82) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      const scale = Math.min(1, maxSize / Math.max(img.width || maxSize, img.height || maxSize));
      const width = Math.max(1, Math.round((img.width || maxSize) * scale));
      const height = Math.max(1, Math.round((img.height || maxSize) * scale));
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      const ctx = canvas.getContext('2d');
      if (!ctx) {
        resolve(dataUrl);
        return;
      }
      ctx.drawImage(img, 0, 0, width, height);
      try {
        resolve(canvas.toDataURL('image/jpeg', quality));
      } catch (error) {
        resolve(dataUrl);
      }
    };
    img.onerror = reject;
    img.src = dataUrl;
  });
}

async function fileToStoredDataUrl(file) {
  const dataUrl = await readFileAsDataUrl(file);
  return file.type.startsWith('image/') ? compressImageDataUrl(dataUrl) : dataUrl;
}

function loadGlobalXrays() {
  try {
    const raw = window.localStorage.getItem(GLOBAL_XRAY_STORAGE_KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      if (Array.isArray(parsed) && parsed.length) return parsed;
    }
  } catch (error) {
    console.warn('[Senan] failed to read global xrays:', error);
  }
  return [
    { id: 1, patient: 'أحمد محمد', date: '2026-04-10', type: 'بانوراما', label: 'فحص شامل', dataUrl: makeGlobalPreviewDataUrl('فحص شامل', 'بانوراما · 2026-04-10') },
    { id: 2, patient: 'فاطمة علي', date: '2026-04-15', type: 'ديجيتال', label: 'ضرس 36', dataUrl: makeGlobalPreviewDataUrl('ضرس 36', 'ديجيتال · 2026-04-15') },
    { id: 3, patient: 'محمد عبد الرحمن', date: '2026-04-12', type: 'بانوراما', label: 'قبل التقويم', dataUrl: makeGlobalPreviewDataUrl('قبل التقويم', 'بانوراما · 2026-04-12') },
    { id: 4, patient: 'نورهان إبراهيم', date: '2026-03-28', type: 'ديجيتال', label: 'قناة جذر 26', dataUrl: makeGlobalPreviewDataUrl('قناة جذر 26', 'ديجيتال · 2026-03-28') },
    { id: 5, patient: 'يوسف طارق', date: '2026-04-14', type: 'ديجيتال', label: 'لبنية', dataUrl: makeGlobalPreviewDataUrl('لبنية', 'ديجيتال · 2026-04-14') },
    { id: 6, patient: 'سلمى حسام', date: '2026-04-16', type: 'بانوراما', label: 'تركيب تاج', dataUrl: makeGlobalPreviewDataUrl('تركيب تاج', 'بانوراما · 2026-04-16') },
    { id: 7, patient: 'رنا أشرف', date: '2026-04-17', type: 'ديجيتال', label: 'تسوس أمامي', dataUrl: makeGlobalPreviewDataUrl('تسوس أمامي', 'ديجيتال · 2026-04-17') },
    { id: 8, patient: 'عمر شريف', date: '2026-02-20', type: 'بانوراما', label: 'فحص دوري', dataUrl: makeGlobalPreviewDataUrl('فحص دوري', 'بانوراما · 2026-02-20') },
  ];
}

function saveGlobalXrays(xrays) {
  try {
    window.localStorage.setItem(GLOBAL_XRAY_STORAGE_KEY, JSON.stringify(xrays));
  } catch (error) {
    console.warn('[Senan] failed to save global xrays:', error);
  }
}

function buildWhatsAppUrl(phone, message) {
  const digits = String(phone || '').replace(/\D/g, '');
  if (!digits) return '';
  return `https://wa.me/${digits}?text=${encodeURIComponent(message || '')}`;
}

const WA_TEMPLATE_STORAGE_PREFIX = 'senan-whatsapp-templates';
const WA_DEFAULT_CLINIC_NAME = 'سِنان كلينيك';

const WA_DEFAULT_TEMPLATES = [
  { id: 'reminder', label: 'تذكير بالموعد', icon: '📅', body: 'مرحباً {name}، نذكّركم بموعدكم في {clinic} غداً {date} الساعة {time} مع {doctor}. نرجو الحضور في الوقت المحدد. 🦷', locked: true },
  { id: 'recall', label: 'استدعاء دوري', icon: '🔁', body: 'مرحباً {name}، حان موعد الفحص الدوري في {clinic}. يسعدنا حجز موعد مناسب لكم. تواصلوا معنا لتحديد الموعد. 📅', locked: true },
  { id: 'lab', label: 'جاهزية التاج', icon: '👑', body: 'مرحباً {name}، نحيطكم علماً بأن التاج أو التركيبة أصبح جاهزاً. يمكنكم التواصل معنا لحجز موعد التركيب المناسب. ✨', locked: true },
  { id: 'followup', label: 'متابعة بعد العلاج', icon: '💊', body: 'مرحباً {name}، نطمئن عليكم بعد زيارتكم الأخيرة في {clinic}. إذا كان لديكم أي ألم أو استفسار يمكنكم التواصل معنا في أي وقت. 💙', locked: true },
  { id: 'confirm', label: 'تأكيد الحجز', icon: '✅', body: 'مرحباً {name}، تم تأكيد موعدكم في {clinic} بتاريخ {date} الساعة {time} مع {doctor}. في انتظاركم 🌷', locked: true },
  { id: 'reschedule', label: 'إعادة جدولة', icon: '🕒', body: 'مرحباً {name}، نعتذر ونود إعادة جدولة موعدكم في {clinic}. يرجى التواصل معنا لاختيار وقت بديل مناسب لكم.', locked: true },
];

const WA_TEMPLATE_VARIABLES = [
  { token: '{name}', label: 'اسم المريض' },
  { token: '{date}', label: 'التاريخ' },
  { token: '{time}', label: 'الوقت' },
  { token: '{doctor}', label: 'الطبيب' },
  { token: '{clinic}', label: 'اسم العيادة' },
  { token: '{phone}', label: 'رقم الهاتف' },
  { token: '{room}', label: 'الغرفة' },
];

function waStorageKey(clinicId) {
  return `${WA_TEMPLATE_STORAGE_PREFIX}:${clinicId || 'default'}`;
}

function cloneWaTemplate(template) {
  return {
    id: String(template?.id || `wa-template-${Date.now()}`),
    label: String(template?.label || 'رسالة جديدة').trim() || 'رسالة جديدة',
    icon: String(template?.icon || '💬'),
    body: String(template?.body || '').trim(),
    locked: Boolean(template?.locked),
  };
}

function loadWaTemplates(clinicId) {
  const defaults = WA_DEFAULT_TEMPLATES.map(cloneWaTemplate);
  try {
    const raw = window.localStorage.getItem(waStorageKey(clinicId));
    if (!raw) return defaults;
    const parsed = JSON.parse(raw);
    if (!Array.isArray(parsed)) return defaults;
    const normalized = parsed.map(cloneWaTemplate);
    const byId = new Map(normalized.map(t => [t.id, t]));
    const mergedDefaults = WA_DEFAULT_TEMPLATES.map((template) => {
      const existing = byId.get(template.id);
      return existing
        ? { ...existing, locked: true, icon: existing.icon || template.icon }
        : cloneWaTemplate(template);
    });
    const custom = normalized.filter(t => !WA_DEFAULT_TEMPLATES.some(def => def.id === t.id));
    return [...mergedDefaults, ...custom];
  } catch (error) {
    console.warn('[WhatsApp Templates] failed to load templates:', error);
    return defaults;
  }
}

function saveWaTemplates(clinicId, templates) {
  try {
    window.localStorage.setItem(waStorageKey(clinicId), JSON.stringify(templates.map(cloneWaTemplate)));
  } catch (error) {
    console.warn('[WhatsApp Templates] failed to save templates:', error);
  }
}

function getCairoTodayStr() {
  return new Intl.DateTimeFormat('en-CA', { timeZone: 'Africa/Cairo' }).format(new Date());
}

function addDaysToIsoDate(isoDate, days) {
  const [year, month, day] = String(isoDate || '').split('-').map(Number);
  if (!year || !month || !day) return isoDate;
  const date = new Date(Date.UTC(year, month - 1, day + Number(days || 0)));
  return new Intl.DateTimeFormat('en-CA', { timeZone: 'UTC' }).format(date);
}

function formatWaDate(dateValue) {
  if (!dateValue) return '—';
  const parsed = new Date(dateValue);
  if (Number.isNaN(parsed.getTime())) return String(dateValue);
  return parsed.toLocaleDateString('ar-EG', { weekday: 'long', day: 'numeric', month: 'long' });
}

function normalizeWhatsAppPhone(phone) {
  let digits = String(phone || '').replace(/\D/g, '');
  if (!digits) return '';
  if (digits.startsWith('00')) digits = digits.slice(2);
  if (digits.startsWith('0')) digits = `20${digits.slice(1)}`;
  else if (digits.length === 10 && digits.startsWith('1')) digits = `20${digits}`;
  return digits;
}

function isValidWhatsAppPhone(phone) {
  return normalizeWhatsAppPhone(phone).length >= 11;
}

function interpolateWaTemplate(body, payload) {
  return String(body || '').replace(/\{(\w+)\}/g, (_, key) => {
    const value = payload?.[key];
    return value == null || value === '' ? '—' : String(value);
  });
}

async function copyText(text) {
  const value = String(text || '');
  if (!value) return false;
  try {
    if (navigator.clipboard?.writeText) {
      await navigator.clipboard.writeText(value);
      return true;
    }
  } catch (error) {
    console.warn('[Clipboard] writeText failed:', error);
  }
  try {
    const textarea = document.createElement('textarea');
    textarea.value = value;
    textarea.setAttribute('readonly', '');
    textarea.style.position = 'fixed';
    textarea.style.opacity = '0';
    document.body.appendChild(textarea);
    textarea.select();
    const copied = document.execCommand('copy');
    document.body.removeChild(textarea);
    return copied;
  } catch (error) {
    console.warn('[Clipboard] fallback copy failed:', error);
    return false;
  }
}

function extractLegacyInventoryPackMeta(item) {
  const name = String(item?.name || '').trim();
  const match = name.match(/^(.*?)(?:\s*-\s*)(\d+(?:\.\d+)?)\s*حالة$/u);
  if (!match) return { cleanName: name, usageUnitsPerPack: 0 };
  return {
    cleanName: String(match[1] || '').trim() || name,
    usageUnitsPerPack: Math.max(0, Number(match[2]) || 0),
  };
}

function getInventoryUsageUnitsPerPack(item, usageUnitsMap = {}) {
  // أولوية: 1) القيمة من Supabase (usage_units_per_pack) 2) localStorage 3) الاسم القديم
  const fromDB = Math.max(0, Number(item?.usageUnitsPerPack) || 0);
  if (fromDB > 0) return fromDB;
  const mapped = Math.max(0, Number(usageUnitsMap?.[item?.id]) || 0);
  if (mapped > 0) return mapped;
  return extractLegacyInventoryPackMeta(item).usageUnitsPerPack;
}

function getInventoryDisplayName(item) {
  return extractLegacyInventoryPackMeta(item).cleanName;
}

function getInventoryActualUsageUnits(item, usageUnitsMap = {}) {
  const stockQty = Math.max(0, Number(item?.stock) || 0);
  const usageUnitsPerPack = getInventoryUsageUnitsPerPack(item, usageUnitsMap);
  return usageUnitsPerPack > 0 ? stockQty * usageUnitsPerPack : 0;
}

function getInventoryMeasureUnitPrice(item, usageUnitsMap = {}) {
  const packPrice = Math.max(0, Number(item?.price) || 0);
  const usageUnitsPerPack = getInventoryUsageUnitsPerPack(item, usageUnitsMap);
  return usageUnitsPerPack > 0 ? packPrice / usageUnitsPerPack : packPrice;
}

function loadInventoryUsageUnitsMap(clinicId) {
  try {
    const raw = window.localStorage.getItem(`senan-inventory-usage-units:${clinicId || 'default'}`);
    return raw ? JSON.parse(raw) : {};
  } catch (error) {
    console.warn('[Inventory Usage Units] failed to load map:', error);
    return {};
  }
}

// ==================== Quick Add Patient Modal ====================
function QuickAddPatientModal({ onClose, onSaved }) {
  const { toast, clinicId, setPatients, patients } = useContext(AppContext);
  const [form, setForm] = useState({ name: '', phone: '', gender: 'ذكر', age: '', location: '', email: '', notes: '' });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const knownLocations = useMemo(() => [...new Set(
    ((patients && patients.length) ? patients : (window.PATIENTS || []))
      .map(p => (p.location || '').trim())
      .filter(Boolean)
  )].sort(), [patients]);

  const handleSave = async () => {
    if (!form.name.trim()) { toast('الرجاء إدخال اسم المريض'); return; }
    setSaving(true);
    try {
      const newP = await DB.addPatient(clinicId, {
        name: form.name.trim(),
        phone: form.phone.trim() || null,
        gender: form.gender,
        age: parseInt(form.age) || null,
        location: form.location.trim() || null,
        email: form.email.trim() || null,
        notes: form.notes.trim() || null,
        balance: 0,
        status: 'active',
      });
      setPatients(prev => [newP, ...prev]);
      toast('تم إضافة المريض ✅');
      onSaved(newP);
      onClose();
    } catch(e) { console.error(e); toast('خطأ في الحفظ'); }
    finally { setSaving(false); }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:400 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:480, maxWidth:'calc(100vw - 24px)', padding:28, maxHeight:'90vh', overflowY:'auto' } },
      h('div', { style: { display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:20 } },
        h('div', { style: { fontWeight:800,fontSize:16 } }, 'إضافة مريض جديد'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, { size:16 })),
      ),
      h('div', { style: { display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 } },
        h('div', { style: { gridColumn: '1/-1' } },
          h('div', { className:'label' }, 'الاسم الكامل *'),
          h('input', { className:'input', placeholder:'اسم المريض', value:form.name, onChange:e=>set('name',e.target.value) }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'العمر'),
          h('input', { className:'input', type:'number', placeholder:'25', value:form.age, onChange:e=>set('age',e.target.value) }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'الجنس'),
          h('select', { className:'input', value:form.gender, onChange:e=>set('gender',e.target.value) },
            h('option', { value:'ذكر' }, 'ذكر'),
            h('option', { value:'أنثى' }, 'أنثى'),
          ),
        ),
        h('div', null,
          h('div', { className:'label' }, 'رقم الهاتف'),
          h('input', { className:'input', placeholder:'07XX XXX XXXX', value:form.phone, onChange:e=>set('phone',e.target.value), dir:'ltr' }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'المنطقة'),
          h('input', {
            className:'input',
            placeholder:'الرحمانية، دسوق...',
            value:form.location,
            onChange:e=>set('location',e.target.value),
            list:'quick-patient-locations',
          }),
          h('datalist', { id:'quick-patient-locations' }, knownLocations.map(loc => h('option', { key: loc, value: loc }))),
        ),
        h('div', null,
          h('div', { className:'label' }, 'البريد الإلكتروني'),
          h('input', { className:'input', type:'email', placeholder:'email@...', value:form.email, onChange:e=>set('email',e.target.value) }),
        ),
        h('div', { style: { gridColumn: '1/-1' } },
          h('div', { className:'label' }, 'ملاحظات'),
          h('textarea', { className:'textarea', rows:2, placeholder:'أي ملاحظات...', value:form.notes, onChange:e=>set('notes',e.target.value) }),
        ),
      ),
      h('div', { style: { display:'flex',gap:10 } },
        h('button', { className:'btn outline', style:{flex:1}, onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', style:{flex:2}, disabled:saving, onClick:handleSave }, saving ? 'جاري الحفظ...' : '✅ حفظ وتحديد المريض'),
      ),
    ),
  );
}
window.QuickAddPatientModal = QuickAddPatientModal;

// ==================== New Appointment ====================
function NewAppointment({ onClose } = {}) {
  const { setScreen, toast, clinicId, setAppointments, appointments, screenParams, patients, doctors, invoices } = useContext(AppContext);
  const handleClose = () => onClose ? onClose() : setScreen('appointments');
  const allPatientsForAppt = (patients && patients.length) ? patients : (window.PATIENTS || []);
  const allDoctorsForAppt  = (doctors  && doctors.length)  ? doctors  : (window.DOCTORS  || []);
  const allAppointmentsForAppt = (appointments && appointments.length) ? appointments : (window.APPOINTMENTS || []);
  const allInvoicesForAppt = (invoices && invoices.length) ? invoices : (window.INVOICES || []);
  const [saving, setSaving] = useState(false);
  const [showQuickAdd, setShowQuickAdd] = useState(false);
  const today = new Date().toISOString().split('T')[0];
  const startHour = parseInt(localStorage.getItem('senan-start-hour') || '9', 10);
  const endHour = parseInt(localStorage.getItem('senan-end-hour') || '17', 10);
  const roomCount = parseInt(localStorage.getItem('senan-rooms') || '1', 10);
  // If coming from patient file, pre-fill patient and skip to step 2
  const initPatientId   = screenParams?.patientId   || null;
  const initPatientName = screenParams?.patientName || '';
  const [step, setStep] = useState(initPatientId ? 2 : 1);
  const [data, setData] = useState({ patient: initPatientName, patientId: initPatientId, doctor: '', doctorId: null, type: '', date: today, time: String(startHour).padStart(2, '0') + ':00', room: roomCount === 1 ? 'الغرفة' : 'غرفة 1', notes: '', reminder: true, duration: 30 });
  const steps = ['المريض', 'الحالة', 'الموعد', 'تأكيد'];
  const normalizeRoomKey = (roomName) => {
    const raw = String(roomName || '').trim();
    if (!raw) return roomCount === 1 ? 'room-1' : '';
    if (raw === 'الغرفة' || raw === 'غرفة 1') return 'room-1';
    const match = raw.match(/\d+/);
    return match ? 'room-' + match[0] : raw;
  };
  const availableRooms = useMemo(() => (
    Array.from({ length: Math.max(1, roomCount) }, (_, i) => roomCount === 1 ? 'الغرفة' : 'غرفة ' + (i + 1))
  ), [roomCount]);
  const availableTimeSlots = useMemo(() => {
    const slotMinutes = 30;
    const duration = Math.max(slotMinutes, parseInt(data.duration || 30, 10) || 30);
    const startMinutes = startHour * 60;
    const endMinutes = endHour * 60;
    const lastStart = Math.max(startMinutes, endMinutes - duration);
    const slots = [];

    for (let mins = startMinutes; mins <= lastStart; mins += slotMinutes) {
      const hours = String(Math.floor(mins / 60)).padStart(2, '0');
      const minutes = String(mins % 60).padStart(2, '0');
      slots.push(hours + ':' + minutes);
    }

    return slots.length ? slots : [String(startHour).padStart(2, '0') + ':00'];
  }, [data.duration, startHour, endHour]);
  const selectedRoomKey = normalizeRoomKey(data.room);
  const occupiedTimeSlots = useMemo(() => {
    return new Set(
      allAppointmentsForAppt
        .filter(appt => appt.date === data.date)
        .filter(appt => appt.status !== 'cancelled')
        .filter(appt => normalizeRoomKey(appt.room) === selectedRoomKey)
        .map(appt => String(appt.time || '').substring(0, 5))
        .filter(Boolean)
    );
  }, [allAppointmentsForAppt, data.date, selectedRoomKey]);
  const firstFreeTimeSlot = useMemo(() => (
    availableTimeSlots.find(slot => !occupiedTimeSlots.has(slot)) || null
  ), [availableTimeSlots, occupiedTimeSlots]);

  const latestInvoice = useMemo(() => {
    if (!data.patientId && !data.patient) return null;
    const patientKey = String(data.patientId || data.patient || '').trim().toLowerCase();
    const matches = allInvoicesForAppt.filter(inv => {
      const invPatientId = String(inv.patientId || inv.patient_id || '').trim().toLowerCase();
      const invPatientName = String(inv.patient || '').trim().toLowerCase();
      return (patientKey && invPatientId === patientKey) || (patientKey && invPatientName === patientKey);
    });
    matches.sort((a, b) => {
      const dateDelta = new Date(b.date || b.created_at || 0) - new Date(a.date || a.created_at || 0);
      if (dateDelta !== 0) return dateDelta;
      return new Date(b.created_at || 0) - new Date(a.created_at || 0);
    });
    return matches[0] || null;
  }, [allInvoicesForAppt, data.patientId, data.patient]);

  const latestInvoiceTotal = latestInvoice ? (parseFloat(latestInvoice.total) || 0) : 0;
  const latestInvoicePaid = latestInvoice ? (parseFloat(latestInvoice.paid) || 0) : 0;
  const latestInvoiceRemaining = latestInvoice ? Math.max(0, latestInvoiceTotal - latestInvoicePaid) : 0;
  const latestInvoiceServices = latestInvoice ? (latestInvoice.items || []).map(item => item.name).filter(Boolean) : [];
  const latestInvoiceServiceChips = latestInvoiceServices.length ? latestInvoiceServices : ['خدمة غير محددة'];

  useEffect(() => {
    if (!availableTimeSlots.includes(data.time)) {
      setData(prev => ({ ...prev, time: availableTimeSlots[0] }));
    }
  }, [availableTimeSlots, data.time]);

  useEffect(() => {
    if (!availableRooms.includes(data.room)) {
      setData(prev => ({ ...prev, room: availableRooms[0] }));
    }
  }, [availableRooms, data.room]);

  useEffect(() => {
    if (occupiedTimeSlots.has(data.time) && firstFreeTimeSlot && firstFreeTimeSlot !== data.time) {
      setData(prev => ({ ...prev, time: firstFreeTimeSlot }));
    }
  }, [occupiedTimeSlots, data.time, firstFreeTimeSlot]);

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', { className: 'flex gap-12 ai-c' },
        h('button', { className: 'icon-btn', onClick: handleClose }, h(Icons.ChevronRight, { size: 18 })),
        h('div', null,
          h('div', { className: 'page-title' }, 'حجز موعد جديد'),
          h('div', { className: 'page-subtitle' }, `الخطوة ${step} من ${steps.length}: ${steps[step-1]}`),
        ),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { style: { maxWidth: 800, margin: '0 auto' } },
        // Stepper
        h('div', { className: 'flex ai-c mb-24', style: { gap: 0 } },
          steps.map((s, i) => h(Fragment, { key: i },
            h('div', { className: 'flex ai-c gap-8' },
              h('div', {
                style: {
                  width: 32, height: 32, borderRadius: '50%', display: 'grid', placeItems: 'center',
                  background: i + 1 <= step ? 'var(--accent)' : 'var(--bg-subtle)',
                  color: i + 1 <= step ? '#fff' : 'var(--text-tertiary)',
                  fontWeight: 800, fontSize: 14,
                },
              }, i + 1 < step ? h(Icons.Check, { size: 16 }) : i + 1),
              h('div', { style: { fontSize: 13, fontWeight: 600, color: i + 1 <= step ? 'var(--text-primary)' : 'var(--text-tertiary)' } }, s),
            ),
            i < steps.length - 1 ? h('div', { style: { flex: 1, height: 2, background: i + 1 < step ? 'var(--accent)' : 'var(--border)', margin: '0 12px' } }) : null,
          )),
        ),

        h('div', { className: 'card p-24' },
          step === 1 && h('div', null,
            h('div', { className: 'label' }, 'ابحث عن مريض'),
            h('input', { className: 'input mb-16', placeholder: 'اسم، رقم هاتف، أو ID...', value: data.patient, onChange: (e) => setData({ ...data, patient: e.target.value }) }),
            h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 8 } }, 'مرضى مقترحون'),
            h('div', { className: 'grid', style: { gap: 8 } },
              allPatientsForAppt.filter(p => !data.patient || p.name.includes(data.patient) || (p.phone||'').includes(data.patient)).slice(0, 4).map(p => h('div', {
                key: p.id,
                onClick: () => setData({ ...data, patient: p.name, patientId: p.id }),
                style: {
                  padding: 12, border: '1px solid ' + (data.patient === p.name ? 'var(--accent)' : 'var(--border)'),
                  background: data.patient === p.name ? 'var(--accent-soft)' : 'transparent',
                  borderRadius: 'var(--radius)', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 12,
                },
              },
                h('div', { className: 'avatar sm' }, p.avatar),
                h('div', { style: { flex: 1 } },
                  h('div', { style: { fontWeight: 700, fontSize: 14 } }, p.name),
                  h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, `${p.phone} · ${p.id}`),
                ),
              )),
            ),
            h('button', { className: 'btn outline mt-16', style: { width: '100%' }, onClick: () => setShowQuickAdd(true) }, h(Icons.UserPlus, { size: 16 }), 'إضافة مريض جديد'),
            showQuickAdd ? h(QuickAddPatientModal, {
              onClose: () => setShowQuickAdd(false),
              onSaved: (newP) => { setData(d => ({ ...d, patient: newP.name, patientId: newP.id })); },
            }) : null,
          ),
          step === 2 && h('div', null,
            h('div', { className: 'label' }, 'هل هو كشف جديد أم مريض متابعة؟'),
            h('div', { className: 'grid cols-2 mb-16', style: { gap: 12 } },
              [
                { key: 'كشف جديد', title: 'كشف جديد', subtitle: 'حجز سريع بدون تفاصيل إضافية' },
                { key: 'مريض متابعة', title: 'مريض متابعة', subtitle: 'عرض آخر فاتورة والرصيد المتبقي' },
              ].map(option => h('button', {
                key: option.key,
                type: 'button',
                onClick: () => setData(prev => ({ ...prev, type: option.key })),
                className: 'card',
                style: {
                  textAlign: 'right',
                  padding: 18,
                  border: '1px solid ' + (data.type === option.key ? 'var(--accent)' : 'var(--border)'),
                  background: data.type === option.key ? 'var(--accent-soft)' : 'var(--bg-elevated)',
                  boxShadow: 'none',
                  cursor: 'pointer',
                },
              },
                h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 6 } }, option.title),
                h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, option.subtitle),
              )),
            ),
            data.type === 'مريض متابعة' ? h('div', {
              style: {
                border: '1px solid var(--border)',
                borderRadius: 'var(--radius-lg)',
                background: 'var(--bg-subtle)',
                padding: 16,
                marginBottom: 16,
              },
            },
              latestInvoice ? [
                h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 6 } }, 'آخر فاتورة'),
                h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 4 } },
                  latestInvoiceServiceChips.map((service, index) => h('span', {
                    key: index,
                    style: {
                      display: 'inline-flex',
                      alignItems: 'center',
                      padding: '4px 10px',
                      borderRadius: 999,
                      background: 'var(--bg-elevated)',
                      border: '1px solid var(--border)',
                      fontSize: 12,
                      fontWeight: 700,
                      color: 'var(--text-primary)',
                      lineHeight: 1.4,
                    },
                  }, service)),
                ),
                h('div', { style: { fontSize: 13, color: 'var(--text-secondary)', marginBottom: 4 } }, latestInvoice.date ? `التاريخ: ${latestInvoice.date}` : 'التاريخ غير متاح'),
                h('div', { style: { fontSize: 14, fontWeight: 700 } }, `المبلغ المتبقي: ${window.fmtEGP(latestInvoiceRemaining)}`),
              ] : h('div', { style: { fontSize: 13, color: 'var(--text-secondary)' } }, 'لا توجد فاتورة سابقة مسجلة لهذا المريض.'),
            ) : null,
          ),
            step === 3 && h('div', null,
              h('div', { className: 'label' }, 'الطبيب'),
              h('div', { className: 'grid cols-2 mb-16', style: { gap: 8 } },
                allDoctorsForAppt.map(d => h('div', {
                  key: d.id,
                  onClick: () => setData({ ...data, doctor: d.name, doctorId: d.id }),
                  style: {
                    padding: 10, border: '1px solid ' + (data.doctor === d.name ? 'var(--accent)' : 'var(--border)'),
                    background: data.doctor === d.name ? 'var(--accent-soft)' : 'transparent',
                    borderRadius: 'var(--radius)', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 10,
                  },
                },
                  h('div', { className: 'avatar sm', style: { background: d.color } }, d.avatar),
                  h('div', null,
                    h('div', { style: { fontWeight: 700, fontSize: 13 } }, d.name),
                    h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, d.specialty),
                  ),
                )),
              ),
              h('div', { className: 'grid cols-2 mb-16', style: { gap: 12 } },
                h('div', null, h('div', { className: 'label' }, 'التاريخ'), h('input', { className: 'input', type: 'date', value: data.date, onChange: (e) => setData({ ...data, date: e.target.value }) })),
                h('div', null, h('div', { className: 'label' }, 'الوقت'), h('input', { className: 'input', type: 'time', min: availableTimeSlots[0], max: availableTimeSlots[availableTimeSlots.length - 1], step: 1800, value: data.time, onChange: (e) => setData({ ...data, time: e.target.value }) })),
              ),
              h('div', { className: 'label' }, 'الأوقات المتاحة'),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 10 } }, `حسب إعدادات العيادة: من ${availableTimeSlots[0]} إلى ${availableTimeSlots[availableTimeSlots.length - 1]}`),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 10 } }, 'الوقت المحجوز في نفس الغرفة يظهر بعلامة × ولا يمكن اختياره.'),
              h('div', { className: 'flex gap-8 wrap mb-16' },
                availableTimeSlots.map(t => {
                  const isBooked = occupiedTimeSlots.has(t);
                  return h('button', {
                    key: t,
                    disabled: isBooked,
                    className: 'btn sm ' + (data.time === t && !isBooked ? 'primary' : 'outline'),
                    style: isBooked ? {
                      color: 'var(--danger)',
                      borderColor: 'color-mix(in oklab, var(--danger) 45%, var(--border))',
                      background: 'var(--danger-soft)',
                      opacity: 0.7,
                      cursor: 'not-allowed',
                      textDecoration: 'line-through',
                    } : null,
                    onClick: () => {
                      if (isBooked) return;
                      setData({ ...data, time: t });
                    },
                  }, isBooked ? '× ' + t : t);
                }),
              ),
              h('div', { className: 'label' }, 'الغرفة'),
              h('div', { className: 'flex gap-8 mb-16' },
                availableRooms.map(r => h('button', {
                  key: r,
                  className: 'btn sm ' + (data.room === r ? 'primary' : 'outline'),
                  onClick: () => setData({ ...data, room: r }),
                }, r)),
            ),
            h('div', { className: 'label' }, 'ملاحظات'),
            h('textarea', { className: 'textarea', rows: 3, placeholder: 'أي ملاحظات خاصة بالموعد...', value: data.notes, onChange: (e) => setData({ ...data, notes: e.target.value }) }),
            h('label', { className: 'flex ai-c gap-8 mt-16', style: { cursor: 'pointer' } },
              h('input', { type: 'checkbox', checked: data.reminder, onChange: (e) => setData({ ...data, reminder: e.target.checked }) }),
              h('span', { style: { fontSize: 13 } }, 'إرسال تذكير تلقائي عبر WhatsApp قبل الموعد بـ 24 ساعة'),
            ),
          ),
          step === 4 && h('div', null,
            h('div', { style: { textAlign: 'center', marginBottom: 20 } },
              h('div', { style: { width: 64, height: 64, borderRadius: '50%', background: 'var(--success-soft)', color: 'var(--success)', display: 'grid', placeItems: 'center', margin: '0 auto 12px' } },
                h(Icons.Check, { size: 32 })),
              h('div', { style: { fontSize: 18, fontWeight: 800 } }, 'تأكيد الموعد'),
              h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, 'راجع التفاصيل قبل الحفظ'),
            ),
            h('div', { style: { padding: 16, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)' } },
              [
                { label: 'المريض', value: data.patient || '—' },
                { label: 'حالة المريض', value: data.type || '—' },
                { label: 'الطبيب', value: data.doctor },
                { label: 'التاريخ والوقت', value: `${data.date} · ${data.time}` },
                { label: 'الغرفة', value: data.room },
              ].map((r, i) => h('div', { key: i, style: { display: 'flex', justifyContent: 'space-between', padding: '10px 0', borderBottom: i < 5 ? '1px solid var(--border)' : 'none' } },
                h('span', { style: { fontSize: 13, color: 'var(--text-tertiary)' } }, r.label),
                h('span', { style: { fontSize: 13, fontWeight: 700 } }, r.value),
              )),
            ),
          ),

          h('div', { className: 'flex jc-sb mt-24' },
            h('button', { className: 'btn outline', onClick: () => step > 1 ? setStep(step - 1) : handleClose() }, step === 1 ? 'إلغاء' : 'السابق'),
              h('button', {
                className: 'btn primary',
                disabled: saving,
                onClick: async () => {
                  if (step < 4) { setStep(step + 1); return; }
                  if (!data.patientId) { toast('اختر مريضاً أولاً'); return; }
                  if (!data.type) { toast('اختار هل هو كشف جديد أم مريض متابعة'); return; }
                  if (!data.doctorId) { toast('اختار الطبيب أولاً'); return; }
                  if (occupiedTimeSlots.has(data.time)) { toast('هذا الموعد محجوز بالفعل في الغرفة المحددة'); return; }
                  setSaving(true);
                  try {
                    const appt = await DB.addAppointment(clinicId, {
                    patient_id: data.patientId,
                    doctor_id: data.doctorId || (window.DOCTORS[0] && window.DOCTORS[0].id),
                    date: data.date,
                    time: data.time + ':00',
                    duration: data.duration || 30,
                    type: data.type,
                    status: 'pending',
                    room: data.room,
                    notes: data.notes,
                  });
                  setAppointments([appt, ...appointments]);
                  toast('تم حجز الموعد بنجاح 🎉');
                  handleClose();
                } catch(e) {
                  console.error(e);
                  toast('حدث خطأ أثناء الحفظ');
                } finally { setSaving(false); }
              },
            }, saving ? 'جاري الحفظ...' : step === 4 ? 'تأكيد الحجز' : 'التالي'),
          ),
        ),
      ),
    ),
  );
}

// ==================== Billing ====================

// تسجيل جلسة/دفعة مع شرائط تقدم الخدمات وخصم المخزون
function AddSessionModal({ inv, onClose, onSaved }) {
  const { toast, clinicId, appointments, setAppointments, services, inventory, setInventory } = useContext(AppContext);
  const today = window.getCurrentClinicDateKey ? window.getCurrentClinicDateKey() : new Date().toISOString().split('T')[0];
  const remaining = inv.total - inv.paid;
  const invoiceItems = Array.isArray(inv.items) ? inv.items : [];

  const [form, setForm] = useState({
    date: today,
    paid_amount: remaining > 0 ? remaining : 0,
    next_appt: '',
    next_appt_time: '10:00',
    notes: '',
  });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  // per-item progress (new delta this session)
  const [itemProgress, setItemProgress] = useState(() => {
    const init = {};
    invoiceItems.forEach((_, i) => { init[i] = 0; });
    return init;
  });
  // cumulative progress from all previous sessions
  const [prevProgress, setPrevProgress] = useState({});
  // BOM items per invoice item index
  const [itemBoms, setItemBoms] = useState({});
  const [loadingPrev, setLoadingPrev] = useState(true);
  // which item card is open (null = all collapsed)
  const [expandedIdx, setExpandedIdx] = useState(null);
  const toggleExpand = (i) => setExpandedIdx(prev => prev === i ? null : i);

  useEffect(() => {
    let cancelled = false;
    async function load() {
      try {
        // 1. Load previous sessions → compute cumulative progress per item index
        const prevSessions = await DB.getInvoiceSessions(inv.id);
        if (!cancelled) {
          const cumulative = {};
          invoiceItems.forEach((_, i) => { cumulative[i] = 0; });
          prevSessions.forEach(sess => {
            try {
              const parsed = JSON.parse(sess.workDone || '{}');
              if (parsed && parsed.items) {
                Object.entries(parsed.items).forEach(([idx, pct]) => {
                  const i = Number(idx);
                  if (!isNaN(i)) cumulative[i] = Math.min(100, (cumulative[i] || 0) + (Number(pct) || 0));
                });
              }
            } catch (_) {}
          });
          setPrevProgress(cumulative);
        }

        // 2. Load BOM per item by matching item name → services list
        const bomMap = {};
        await Promise.all(invoiceItems.map(async (item, i) => {
          const svc = (services || []).find(s => s.name === item.name);
          if (svc) {
            try {
              const boms = await DB.getBomForService(svc.id);
              if (!cancelled) bomMap[i] = boms;
            } catch (_) { bomMap[i] = []; }
          } else {
            bomMap[i] = [];
          }
        }));
        if (!cancelled) setItemBoms(bomMap);
      } catch (e) {
        console.error('[AddSessionModal] load error:', e);
      } finally {
        if (!cancelled) setLoadingPrev(false);
      }
    }
    load();
    return () => { cancelled = true; };
  }, [inv.id]);

  const setItemProg = (i, v) => setItemProgress(p => ({ ...p, [i]: Number(v) }));

  // Calculate what will be deducted for a given item index
  // deductUsageUnits = وحدات الاستخدام (الحالات)
  // deductPacks      = ما يُخصم فعلاً من stock (عبوات)
  const getDeductions = (itemIdx) => {
    const delta = itemProgress[itemIdx] || 0;
    if (!delta) return [];
    const item = invoiceItems[itemIdx];
    const itemQty = Number(item?.qty) || 1;
    const boms = itemBoms[itemIdx] || [];
    return boms.map(bom => {
      const usageUnits = Math.round(bom.standardQty * itemQty * (delta / 100) * 1000) / 1000;
      if (usageUnits <= 0) return null;
      // نجيب usageUnitsPerPack من قائمة المخزون في الـ context
      const invItem = (inventory || []).find(x => x.id === bom.inventoryId);
      const uup = Number(invItem?.usageUnitsPerPack) || 0;
      // إذا فيه usageUnitsPerPack: نقسم عليه للحصول على عبوات
      // إذا مفيش: نخصم وحدات مباشرة من stock
      const deductPacks = uup > 0
        ? Math.round((usageUnits / uup) * 10000) / 10000
        : usageUnits;
      return {
        inventoryId: bom.inventoryId,
        name: bom.itemName,
        unit: bom.unit,
        usageUnits,          // للعرض: كام حالة/وحدة استخدام
        deductPacks,         // للخصم الفعلي من stock
        uup,                 // عدد الوحدات في العبوة (للعرض)
      };
    }).filter(Boolean);
  };

  const activeItems = Object.values(itemProgress).filter(v => v > 0).length;

  const handleSave = async () => {
    const amt = parseFloat(form.paid_amount) || 0;
    if (amt < 0) { toast('أدخل مبلغ صحيح'); return; }
    setSaving(true);
    try {
      // Store progress as JSON in work_done
      const workDoneJson = JSON.stringify({ items: itemProgress });

      // جمع الخصومات by inventoryId قبل أي call
      const stockDeltas = {};
      for (let i = 0; i < invoiceItems.length; i++) {
        for (const d of getDeductions(i)) {
          if (d.deductPacks > 0) {
            stockDeltas[d.inventoryId] = (stockDeltas[d.inventoryId] || 0) - d.deductPacks;
          }
        }
      }
      const deductedCount = Object.keys(stockDeltas).length;

      // شغّل addSession + كل خصومات المخزون في نفس الوقت
      const [session] = await Promise.all([
        DB.addSession(clinicId, {
          invoice_id: inv.id,
          patient_id: inv.patientId,
          doctor_id: inv.doctorId || null,
          date: form.date,
          paid_amount: amt,
          work_done: workDoneJson,
          next_appt: form.next_appt || null,
          doctor_commission: 0,
          notes: form.notes,
        }),
        ...Object.entries(stockDeltas).map(([invId, delta]) =>
          window.adjustInventoryStock(invId, delta)
        ),
      ]);

      // حدّث الـ UI فوراً بدون انتظار refresh
      if (setInventory && deductedCount > 0) {
        setInventory(prev => (prev || []).map(item =>
          stockDeltas[item.id] !== undefined
            ? { ...item, stock: Math.max(0, item.stock + stockDeltas[item.id]) }
            : item
        ));
      }

      // Create next appointment if provided
      let nextAppointment = null;
      if (form.next_appt) {
        nextAppointment = await DB.addAppointment(clinicId, {
          patient_id: inv.patientId,
          doctor_id: inv.doctorId || null,
          date: form.next_appt,
          time: `${form.next_appt_time || '10:00'}:00`,
          duration: 30,
          type: 'متابعة',
          status: 'pending',
          room: '',
          notes: `متابعة جلسة فاتورة ${typeof inv.id === 'string' && inv.id.startsWith('INV') ? inv.id : 'INV-' + String(inv.id).slice(-6)}`,
        });
        if (setAppointments && nextAppointment) {
          setAppointments(prev => [nextAppointment, ...((prev && prev.length) ? prev : (appointments || []))]);
        }
      }

      const msg = deductedCount > 0
        ? `تم تسجيل الجلسة وخصم ${deductedCount} مادة من المخزون ✅`
        : nextAppointment ? 'تم تسجيل الجلسة وحجز الموعد القادم ✅'
        : 'تم تسجيل الجلسة ✅';
      toast(msg);
      onSaved(session, amt);
      onClose();
    } catch(e) { console.error(e); toast('خطأ في الحفظ'); }
    finally { setSaving(false); }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:600 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:520, padding:28, maxHeight:'92vh', overflowY:'auto' } },
      // ── Header
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16} },
        h('div', { style:{fontWeight:800,fontSize:17} }, 'تسجيل جلسة / دفعة'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      // ── Patient card
      h('div', { style:{padding:'10px 14px',background:'var(--bg-subtle)',borderRadius:'var(--radius)',marginBottom:16,fontSize:13,display:'flex',justifyContent:'space-between',alignItems:'center'} },
        h('span', { style:{fontWeight:700} }, inv.patient),
        h('span', { style:{color:'var(--danger)',fontWeight:800} }, `متبقي: ${window.fmtEGP(remaining)}`),
      ),
      // ── Date + Amount
      h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12,marginBottom:16} },
        h('div', null,
          h('div', { className:'label' }, 'التاريخ'),
          h('input', { className:'input', type:'date', value:form.date, onChange:e=>set('date',e.target.value) }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'المبلغ المدفوع'),
          h('input', { className:'input', type:'number', min:0, value:form.paid_amount, onChange:e=>set('paid_amount',e.target.value) }),
        ),
      ),

      // ── Per-service progress bars (collapsible cards)
      invoiceItems.length > 0 && h('div', { style:{marginBottom:16} },
        h('div', { style:{fontWeight:700,fontSize:13,marginBottom:8,color:'var(--text-primary)'} }, '📊 تقدم الخدمات'),
        loadingPrev
          ? h('div', { style:{textAlign:'center',padding:'14px',color:'var(--text-secondary)',fontSize:13,background:'var(--bg-subtle)',borderRadius:'var(--radius)'} }, '⏳ جاري تحميل...')
          : invoiceItems.map((item, i) => {
              const prev = Math.min(100, prevProgress[i] || 0);
              const delta = itemProgress[i] || 0;
              const maxDelta = Math.max(0, 100 - prev);
              const total = Math.min(100, prev + delta);
              const boms = itemBoms[i] || [];
              const deductions = getDeductions(i);
              const completed = prev >= 100;
              const isOpen = expandedIdx === i;

              return h('div', { key:i, style:{marginBottom:8,borderRadius:'var(--radius)',border:`1px solid ${isOpen ? 'var(--accent)' : 'var(--border)'}`,overflow:'hidden',transition:'border-color 0.15s'} },

                // ── Collapsed header (always visible, clickable)
                h('div', {
                  onClick: () => toggleExpand(i),
                  style:{display:'flex',alignItems:'center',gap:10,padding:'10px 14px',background: isOpen ? 'var(--bg-subtle)' : 'transparent',cursor:'pointer',userSelect:'none'},
                },
                  // thin progress bar on the left edge
                  h('div', { style:{width:4,height:32,borderRadius:2,background:'var(--border)',flexShrink:0,overflow:'hidden',position:'relative'} },
                    prev > 0 && h('div', { style:{position:'absolute',bottom:0,left:0,width:'100%',height:`${prev}%`,background:'var(--text-secondary)',opacity:0.5} }),
                    delta > 0 && h('div', { style:{position:'absolute',bottom:`${prev}%`,left:0,width:'100%',height:`${delta}%`,background:'var(--accent)'} }),
                  ),
                  // service name + qty
                  h('div', { style:{flex:1,minWidth:0} },
                    h('div', { style:{fontWeight:700,fontSize:13,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'} },
                      item.name + (Number(item.qty) > 1 ? ` ×${item.qty}` : ''),
                    ),
                    // mini bar
                    h('div', { style:{height:4,borderRadius:2,background:'var(--border)',marginTop:4,overflow:'hidden',position:'relative'} },
                      prev > 0 && h('div', { style:{position:'absolute',left:0,top:0,height:'100%',width:`${prev}%`,background:'var(--text-secondary)',opacity:0.4} }),
                      delta > 0 && h('div', { style:{position:'absolute',left:`${prev}%`,top:0,height:'100%',width:`${delta}%`,background:'var(--accent)'} }),
                    ),
                  ),
                  // % badge
                  h('div', { style:{fontSize:12,fontWeight:800,color: completed ? 'var(--success)' : delta > 0 ? 'var(--accent)' : 'var(--text-secondary)',flexShrink:0,minWidth:38,textAlign:'left'} },
                    completed ? '✅' : total > 0 ? `${total}%` : '—',
                  ),
                  // chevron
                  h('div', { style:{fontSize:11,color:'var(--text-secondary)',transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',transition:'transform 0.15s',flexShrink:0} }, '▼'),
                ),

                // ── Expanded body (slider + BOM preview)
                isOpen && h('div', { style:{padding:'12px 14px',borderTop:'1px solid var(--border)',background:'var(--bg-subtle)'} },
                  !completed && h(Fragment, null,
                    h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:6,fontSize:12,color:'var(--text-secondary)'} },
                      h('span', null, `سابق: ${prev}%`),
                      h('span', { style:{color:'var(--accent)',fontWeight:700} }, delta > 0 ? `+ ${delta}% هذه الجلسة` : 'اسحب لتحديد التقدم'),
                    ),
                    h('input', {
                      type:'range', min:0, max:maxDelta, step:5, value:delta,
                      onChange: e => setItemProg(i, e.target.value),
                      style:{width:'100%',marginBottom:10,accentColor:'var(--accent)',cursor:'pointer'},
                    }),
                    // BOM deduction preview
                    deductions.length > 0 && h('div', { style:{padding:'8px 10px',background:'rgba(100,160,255,0.08)',borderRadius:6,fontSize:12,borderRight:'3px solid var(--accent)'} },
                      h('div', { style:{fontWeight:700,marginBottom:5,fontSize:11,color:'var(--accent)'} }, '📦 سيُخصم تلقائياً من المخزون:'),
                      ...deductions.map((d, di) =>
                        h('div', { key:di, style:{color:'var(--text-secondary)',lineHeight:1.8} },
                          d.uup > 0
                            // عندنا usageUnitsPerPack: نعرض الحالات والعبوات
                            ? `• ${d.name}: ${d.usageUnits} حالة (${d.deductPacks} ${d.unit} من المخزون)`
                            // مفيش usageUnitsPerPack: نخصم مباشرة
                            : `• ${d.name}: ${d.usageUnits} ${d.unit}`
                        )
                      ),
                    ),
                    delta > 0 && boms.length === 0 && h('div', { style:{fontSize:11,color:'var(--text-secondary)',fontStyle:'italic'} }, '⚠️ لا يوجد مواد مرتبطة بهذه الخدمة في BOM'),
                  ),
                  completed && h('div', { style:{fontSize:12,color:'var(--text-secondary)',fontStyle:'italic',textAlign:'center',padding:'4px 0'} }, '✅ مكتملة 100% من جلسات سابقة'),
                ),
              );
            }),
      ),

      // ── Notes
      h('div', { style:{marginBottom:16} },
        h('div', { className:'label' }, 'ملاحظات'),
        h('textarea', { className:'textarea', rows:2, placeholder:'...', value:form.notes, onChange:e=>set('notes',e.target.value) }),
      ),

      // ── Next appointment
      h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12,marginBottom:20} },
        h('div', null,
          h('div', { className:'label' }, 'الموعد الجاي (اختياري)'),
          h('input', { className:'input', type:'date', value:form.next_appt, onChange:e=>set('next_appt',e.target.value) }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'وقت الموعد الجاي'),
          h('input', { className:'input', type:'time', value:form.next_appt_time, disabled: !form.next_appt, onChange:e=>set('next_appt_time',e.target.value) }),
        ),
      ),

      // ── Actions
      h('div', { className:'flex gap-8 jc-sb' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave },
          saving ? 'جاري الحفظ...' :
          activeItems > 0 ? `حفظ + خصم مخزون (${activeItems} خدمة)` : 'حفظ الجلسة',
        ),
      ),
    ),
  );
}

// تفاصيل الفاتورة مع كل الجلسات
function InvoiceDetailModal({ inv, onClose, onInvoiceUpdated }) {
  const { toast, setInvoices, services, inventory, setInventory } = useContext(AppContext);
  const [sessions, setSessions] = useState([]);
  const [loading, setLoading] = useState(true);
  const [showAdd, setShowAdd] = useState(false);
  const noteMeta = inv.noteMeta || (window.decodeInvoiceNotes ? window.decodeInvoiceNotes(inv.notes) : {});
  const invoiceItems = Array.isArray(inv.items) ? inv.items : [];
  const invoiceSubtotal = invoiceItems.reduce((sum, item) => sum + ((Number(item.qty) || 0) * (Number(item.price) || 0)), 0);
  const invoiceDiscountAmount = Number(noteMeta.discountAmount || inv.discountAmount || 0) || 0;
  const hasDiscount = invoiceDiscountAmount > 0;

  useEffect(() => {
    DB.getInvoiceSessions(inv.id)
      .then(setSessions)
      .catch(e => console.error(e))
      .finally(() => setLoading(false));
  }, [inv.id]);

  const handleSessionSaved = (session, amt) => {
    setSessions(prev => [...prev, session]);
    const newPaid = Math.min(inv.paid + amt, inv.total);
    const newStatus = newPaid >= inv.total ? 'paid' : newPaid > 0 ? 'partial' : 'unpaid';
    const updatedInv = { ...inv, paid: newPaid, status: newStatus };
    setInvoices(prev => (prev||[]).map(i => i.id === inv.id ? updatedInv : i));
    onInvoiceUpdated(updatedInv);
  };

  const handleDeleteSession = async (session) => {
    if (!confirm('حذف هذه الجلسة؟ سيتم استرجاع المخزون المخصوم.')) return;
    try {
      // ── حساب ما يجب استرجاعه من المخزون ──
      let itemProgress = {};
      try {
        const parsed = JSON.parse(session.workDone || '{}');
        if (parsed && parsed.items) itemProgress = parsed.items;
      } catch(_) {}

      const restoreDeltas = {};
      await Promise.all(
        Object.entries(itemProgress)
          .filter(([, pct]) => Number(pct) > 0)
          .map(async ([idx, pct]) => {
            const itemIdx = Number(idx);
            const item = invoiceItems[itemIdx];
            if (!item) return;
            const svc = (services || []).find(s => s.name === item.name);
            if (!svc) return;
            try {
              const boms = await DB.getBomForService(svc.id);
              const itemQty = Number(item.qty) || 1;
              for (const bom of boms) {
                const usageUnits = Math.round(bom.standardQty * itemQty * (Number(pct) / 100) * 1000) / 1000;
                if (usageUnits <= 0) continue;
                const invItem = (inventory || []).find(x => x.id === bom.inventoryId);
                const uup = Number(invItem?.usageUnitsPerPack) || 0;
                const deductPacks = uup > 0
                  ? Math.round((usageUnits / uup) * 10000) / 10000
                  : usageUnits;
                if (deductPacks > 0) {
                  restoreDeltas[bom.inventoryId] = (restoreDeltas[bom.inventoryId] || 0) + deductPacks;
                }
              }
            } catch(_) {}
          })
      );

      // ── حذف الجلسة + استرجاع المخزون بالتوازي ──
      await Promise.all([
        DB.deleteSession(session.id),
        ...Object.entries(restoreDeltas).map(([invId, delta]) =>
          window.adjustInventoryStock(invId, +delta)
        ),
      ]);

      // ── تحديث UI ──
      setSessions(prev => prev.filter(s => s.id !== session.id));
      const restoredCount = Object.keys(restoreDeltas).length;
      if (setInventory && restoredCount > 0) {
        setInventory(prev => (prev || []).map(item =>
          restoreDeltas[item.id] !== undefined
            ? { ...item, stock: item.stock + restoreDeltas[item.id] }
            : item
        ));
      }
      const newPaid = Math.max(inv.paid - (session.paidAmount || 0), 0);
      const newStatus = newPaid >= inv.total ? 'paid' : newPaid > 0 ? 'partial' : 'unpaid';
      const updatedInv = { ...inv, paid: newPaid, status: newStatus };
      setInvoices(prev => (prev||[]).map(i => i.id === inv.id ? updatedInv : i));
      onInvoiceUpdated(updatedInv);
      toast(restoredCount > 0 ? `تم الحذف · تم استرجاع ${restoredCount} مادة في المخزون` : 'تم حذف الجلسة');
    } catch(e) {
      console.error('[handleDeleteSession]', e);
      toast('خطأ في الحذف');
    }
  };

  const statusColor = { paid:'success', partial:'warning', unpaid:'danger' };
  const statusLabel = { paid:'مدفوعة', partial:'جزئية', unpaid:'غير مدفوعة' };

  return h(Fragment, null,
    showAdd ? h(AddSessionModal, { inv, onClose:()=>setShowAdd(false), onSaved:handleSessionSaved }) : null,
    h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:200 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:560, maxHeight:'85vh', display:'flex', flexDirection:'column' } },
      // Header
      h('div', { style:{padding:'20px 24px 16px',borderBottom:'1px solid var(--border)',display:'flex',justifyContent:'space-between',alignItems:'center'} },
        h('div', null,
          h('div', { style:{fontWeight:800,fontSize:16} },
            typeof inv.id==='string'&&inv.id.startsWith('INV') ? inv.id : 'INV-'+String(inv.id).slice(-6),
            h('span', { className:'chip '+statusColor[inv.status], style:{marginRight:8} }, statusLabel[inv.status]),
          ),
          h('div', { style:{fontSize:13,color:'var(--text-tertiary)',marginTop:2} },
            inv.patient
            + (inv.doctorName ? ' · ' + inv.doctorName : '')
            + (inv.date ? ' · ' + inv.date : '')
          ),
        ),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      // Summary
      h('div', { style:{padding:'12px 24px',background:'var(--bg-subtle)',display:'grid',gridTemplateColumns:'1fr 1fr 1fr',gap:12} },
        [
          { label:'الإجمالي', val: inv.total, color:'var(--text-primary)' },
          { label:'مدفوع', val: inv.paid, color:'var(--success)' },
          { label:'متبقي', val: inv.total - inv.paid, color:'var(--danger)' },
        ].map((k,i) => h('div', { key:i, style:{textAlign:'center'} },
          h('div', { style:{fontSize:11,color:'var(--text-tertiary)'} }, k.label),
          h('div', { style:{fontSize:16,fontWeight:800,color:k.color} }, window.fmtEGP(k.val)),
        )),
      ),
      // Work done + discount
      h('div', { style:{padding:'16px 24px',borderBottom:'1px solid var(--border)'} },
        h('div', { style:{fontWeight:800,fontSize:14,marginBottom:10} }, 'الشغل المنجز'),
        invoiceItems.length ? h('div', { style:{display:'flex',flexWrap:'wrap',gap:8} },
          invoiceItems.map((item, index) => h('span', {
            key: item.id || index,
            style: {
              display: 'inline-flex',
              alignItems: 'center',
              gap: 6,
              padding: '4px 10px',
              borderRadius: 999,
              background: 'var(--bg-subtle)',
              border: '1px solid var(--border)',
              fontSize: 12,
              fontWeight: 700,
            },
          }, `${item.name}${Number(item.qty) > 1 ? ` × ${item.qty}` : ''}`))
        ) : h('div', { style:{fontSize:13,color:'var(--text-tertiary)'} }, 'لا توجد خدمات مسجلة'),
        h('div', { style:{fontSize:12,marginTop:10,color:hasDiscount ? 'var(--warning)' : 'var(--text-tertiary)',fontWeight:600} },
          hasDiscount
            ? `الخصم: ${window.fmtEGP(invoiceDiscountAmount)}`
            : `لا يوجد خصم مسجل${invoiceSubtotal ? ` · إجمالي الشغل قبل الخصم: ${window.fmtEGP(invoiceSubtotal)}` : ''}`,
        ),
      ),
      // Sessions list
      h('div', { style:{flex:1,overflowY:'auto',padding:'16px 24px'} },
        h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12} },
          h('div', { style:{fontWeight:700,fontSize:14} }, `الجلسات (${sessions.length})`),
          h('button', { className:'btn sm primary', onClick:()=>setShowAdd(true) },
            h(Icons.Plus, {size:14}), 'جلسة جديدة'
          ),
        ),
        loading ? h('div', { style:{textAlign:'center',padding:24,color:'var(--text-tertiary)'} }, 'جاري التحميل...') :
        sessions.length === 0 ? h('div', { style:{textAlign:'center',padding:24,color:'var(--text-tertiary)',border:'2px dashed var(--border)',borderRadius:'var(--radius)'} },
          h('div', null, 'لا توجد جلسات مسجلة'),
          h('button', { className:'btn sm primary mt-12', onClick:()=>setShowAdd(true) }, h(Icons.Plus, {size:14}), 'أضف أول جلسة'),
        ) :
        h('div', { style:{display:'flex',flexDirection:'column',gap:8} },
          sessions.map(s => h('div', { key:s.id, style:{padding:'12px 14px',border:'1px solid var(--border)',borderRadius:'var(--radius)',display:'grid',gridTemplateColumns:'1fr 1fr auto',gap:8,alignItems:'center'} },
            h('div', null,
              h('div', { style:{fontSize:13,fontWeight:700} }, window.fmtDate(s.date)),
              s.workDone ? h('div', { style:{fontSize:12,color:'var(--text-tertiary)',marginTop:2} }, s.workDone) : null,
            ),
            h('div', null,
              h('div', { style:{fontSize:15,fontWeight:800,color:'var(--success)'} }, window.fmtEGP(s.paidAmount)),
              s.doctorCommission > 0 ? h('div', { style:{fontSize:11,color:'var(--text-tertiary)'} }, `عمولة: ${window.fmtEGP(s.doctorCommission)}`) : null,
            ),
            h('button', { className:'icon-btn', style:{color:'var(--danger)'}, onClick:()=>handleDeleteSession(s) },
              h(Icons.Trash, {size:13}),
            ),
          )),
        ),
      ),
      h('div', { style:{padding:'12px 24px',borderTop:'1px solid var(--border)'} },
        h('button', { className:'btn outline', style:{width:'100%'}, onClick:onClose }, 'إغلاق'),
      ),
    ),
    ),
  );
}

function Billing() {
  const { setScreen, invoices, setInvoices, toast, clinicName, screenParams, services, inventory, setInventory } = useContext(AppContext);
  const [showNewInvoice, setShowNewInvoice] = React.useState(false);
  const [detailInv, setDetailInv] = useState(null);
  const [editInv, setEditInv] = useState(null);
  const [tabFilter, setTabFilter] = useState('all');
  const [billSearch, setBillSearch] = useState('');
  const [dateFrom, setDateFrom] = useState('');
  const [dateTo, setDateTo] = useState('');
  const [showDateFilter, setShowDateFilter] = useState(false);
  const [activeDatePreset, setActiveDatePreset] = useState('all');
  const setBillingRange = (fromValue, toValue, presetKey = 'custom') => {
    setDateFrom(fromValue || '');
    setDateTo(toValue || '');
    setActiveDatePreset(presetKey);
  };
  const applyBillingPreset = (presetKey) => {
    const { fromValue, toValue } = window.resolveDateRangePreset
      ? window.resolveDateRangePreset(presetKey)
      : { fromValue: '', toValue: '' };
    setBillingRange(fromValue, toValue, presetKey);
    setShowDateFilter(false);
  };
  const clearBillingRange = () => {
    setBillingRange('', '', 'all');
    setShowDateFilter(false);
  };
  const selectedRangeLabel = window.getDateRangeLabel
    ? window.getDateRangeLabel(dateFrom, dateTo)
    : 'كل التواريخ';
  const allInvoices = (invoices && invoices.length) ? invoices : (window.INVOICES || []);
  const handledRouteRef = useRef('');

  useEffect(() => {
    const invoiceId = screenParams?.invoiceId ? String(screenParams.invoiceId) : '';
    const patientName = String(screenParams?.patientName || '').trim();
    const routeKey = `${invoiceId}|${patientName}`;
    if (!routeKey || handledRouteRef.current === routeKey) return;
    handledRouteRef.current = routeKey;
    if (patientName) setBillSearch(patientName);
    if (invoiceId) {
      const target = allInvoices.find(item => String(item.id || '') === invoiceId);
      if (target) {
        setDetailInv(target);
      } else if (patientName) {
        toast('لم يتم العثور على الفاتورة المطلوبة، عرضنا فواتير المريض بدلاً منها');
      }
    }
  }, [allInvoices, screenParams, toast]);

  const dateFilteredInvoices = allInvoices.filter(i => {
    const invDate = String(i.date || '').slice(0, 10);
    if (dateFrom && (!invDate || invDate < dateFrom)) return false;
    if (dateTo && (!invDate || invDate > dateTo)) return false;
    return true;
  });
  const filtered = dateFilteredInvoices.filter(i => {
    if (tabFilter !== 'all' && i.status !== tabFilter) return false;
    if (billSearch) {
      const q = billSearch.toLowerCase();
      const nameMatch = (i.patient || '').toLowerCase().includes(q);
      const doctorMatch = (i.doctorName || '').toLowerCase().includes(q);
      const phoneMatch = (i.phone || i.patient_phone || '').includes(q);
      const idMatch = String(i.id || '').toLowerCase().includes(q);
      if (!nameMatch && !doctorMatch && !phoneMatch && !idMatch) return false;
    }
    return true;
  });
  const total = dateFilteredInvoices.reduce((s, i) => s + i.total, 0);
  const paid  = dateFilteredInvoices.reduce((s, i) => s + i.paid,  0);
  const outstanding = total - paid;

  // حذف الفاتورة مع استرجاع المخزون من جميع الجلسات المرتبطة بها
  const handleDeleteInvoice = async (inv) => {
    if (!confirm(`حذف الفاتورة ${inv.id}؟ سيتم استرجاع المخزون من كل الجلسات.`)) return;
    try {
      const invoiceItems = Array.isArray(inv.items) ? inv.items : [];
      const sessions = await DB.getInvoiceSessions(inv.id);
      const restoreDeltas = {};

      if (sessions.length > 0 && invoiceItems.length > 0) {
        await Promise.all(sessions.map(async (session) => {
          let itemProgress = {};
          try { const p = JSON.parse(session.workDone || '{}'); if (p && p.items) itemProgress = p.items; } catch(_) {}
          await Promise.all(
            Object.entries(itemProgress)
              .filter(([, pct]) => Number(pct) > 0)
              .map(async ([idx, pct]) => {
                const item = invoiceItems[Number(idx)];
                if (!item) return;
                const svc = (services || []).find(s => s.name === item.name);
                if (!svc) return;
                try {
                  const boms = await DB.getBomForService(svc.id);
                  const iqty = Number(item.qty) || 1;
                  for (const bom of boms) {
                    const uu = Math.round(bom.standardQty * iqty * (Number(pct) / 100) * 1000) / 1000;
                    if (uu <= 0) continue;
                    const invItem = (inventory || []).find(x => x.id === bom.inventoryId);
                    const uup = Number(invItem?.usageUnitsPerPack) || 0;
                    const dp = uup > 0 ? Math.round(uu / uup * 10000) / 10000 : uu;
                    if (dp > 0) restoreDeltas[bom.inventoryId] = (restoreDeltas[bom.inventoryId] || 0) + dp;
                  }
                } catch(_) {}
              })
          );
        }));
        // تطبيق الاسترجاع على DB + UI
        const rc = Object.keys(restoreDeltas).length;
        if (rc > 0) {
          await Promise.all(Object.entries(restoreDeltas).map(([id, d]) => window.adjustInventoryStock(id, +d)));
          if (setInventory) {
            setInventory(prev => (prev || []).map(item =>
              restoreDeltas[item.id] !== undefined ? { ...item, stock: item.stock + restoreDeltas[item.id] } : item
            ));
          }
        }
      }

      await SB.from('invoice_items').delete().eq('invoice_id', inv.id);
      await SB.from('invoices').delete().eq('id', inv.id);
      setInvoices(prev => prev.filter(i => i.id !== inv.id));
      const rc = Object.keys(restoreDeltas).length;
      toast(rc > 0 ? `تم حذف الفاتورة · تم استرجاع ${rc} مادة في المخزون` : 'تم حذف الفاتورة');
    } catch(e) { console.error(e); toast('خطأ في الحذف'); }
  };

  return h('div', { className: 'fade-in' },
    detailInv ? h(InvoiceDetailModal, { inv: detailInv, onClose:()=>setDetailInv(null), onInvoiceUpdated:(upd)=>setDetailInv(upd) }) : null,
    editInv ? h(EditInvoiceModal, { inv: editInv, onClose:()=>setEditInv(null), onSaved:(upd)=>{ setInvoices(prev=>prev.map(i=>i.id===upd.id?upd:i)); setEditInv(null); } }) : null,
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الفواتير والمدفوعات'),
        h('div', { className: 'page-subtitle' }, `${dateFilteredInvoices.length} فاتورة · ${window.fmtEGP(outstanding)} مستحقة${dateFrom || dateTo ? ' ضمن الفترة المحددة' : ''}`),
      ),
      h('div', { className: 'flex gap-8' },
        h('button', { className: 'btn outline' }, h(Icons.Download, { size: 16 }), 'تصدير'),
        h('button', { className: 'btn primary', onClick: () => setShowNewInvoice(true) }, h(Icons.Plus, { size: 16 }), 'فاتورة جديدة'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'grid cols-3 mb-16' },
        [
          { label: 'إجمالي الفواتير', value: total, icon: Icons.CreditCard, color: 'var(--accent)', soft: 'var(--accent-soft)' },
          { label: 'مدفوع', value: paid, icon: Icons.Check, color: 'var(--success)', soft: 'var(--success-soft)' },
          { label: 'مستحق', value: outstanding, icon: Icons.AlertTriangle, color: 'var(--danger)', soft: 'var(--danger-soft)' },
        ].map((k, i) => h('div', { key: i, className: 'card kpi' },
          h('div', { className: 'flex jc-sb ai-c' },
            h('div', null,
              h('div', { className: 'label' }, k.label),
              h('div', { className: 'value' }, window.fmtEGP(k.value)),
            ),
            h('div', { className: 'kpi-icon', style: { background: k.soft, color: k.color } }, h(k.icon, { size: 20 })),
          ),
        )),
      ),
      h('div', { className: 'card', style: { overflow: 'visible' } },
        h('div', { style: { padding: '12px 16px', borderBottom: '1px solid var(--border)' } },
          h(Shell.DateRangeFilter, {
            title: 'فلتر التاريخ',
            subtitle: 'اختر فترة جاهزة أو حدد من يوم إلى يوم',
            dateFrom,
            dateTo,
            open: showDateFilter,
            onToggle: () => setShowDateFilter(prev => !prev),
            onClose: () => setShowDateFilter(false),
            onPresetSelect: applyBillingPreset,
            activePreset: activeDatePreset,
            onFromChange: (value) => {
              setDateFrom(value);
              setActiveDatePreset('custom');
            },
            onToChange: (value) => {
              setDateTo(value);
              setActiveDatePreset('custom');
            },
            onClear: clearBillingRange,
            onApply: () => setShowDateFilter(false),
          }),
          h('div', { style: { position: 'relative' } },
            h('input', {
              className: 'input',
              placeholder: 'ابحث باسم المريض أو رقم الهاتف...',
              value: billSearch,
              onChange: e => setBillSearch(e.target.value),
              style: { paddingInlineEnd: 38 },
            }),
            billSearch ? h('button', {
              onClick: () => setBillSearch(''),
              style: {
                position: 'absolute', insetInlineEnd: 10, top: '50%', transform: 'translateY(-50%)',
                background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-tertiary)', padding: 2,
              },
            }, h(Icons.X, { size: 14 })) :
            h('span', {
              style: { position: 'absolute', insetInlineEnd: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-tertiary)', pointerEvents: 'none' },
            }, h(Icons.Search, { size: 15 })),
          ),
        ),
        h('div', { className: 'tabs', style: { padding: '0 16px', marginBottom: 0 } },
          [['all','الكل'],['paid','مدفوعة'],['partial','جزئية'],['unpaid','غير مدفوعة']].map(([v,l]) => h('button', {
            key: v, className: 'tab' + (tabFilter===v?' active':''), onClick:()=>setTabFilter(v),
          }, l)),
        ),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null, ['رقم الفاتورة', 'المريض', 'الطبيب', 'التاريخ', 'الإجمالي', 'المدفوع', 'المتبقي', 'الحالة', ''].map((t, i) => h('th', { key: i }, t)))),
          h('tbody', null,
            filtered.length ? filtered.map(inv => h('tr', { key: inv.id, style: { cursor: 'pointer' }, onClick:()=>setDetailInv(inv) },
              h('td', { style: { fontFamily: 'monospace', fontSize: 12, fontWeight: 700 } }, typeof inv.id === 'string' && inv.id.startsWith('INV') ? inv.id : 'INV-' + String(inv.id).slice(-6)),
              h('td', null, inv.patient),
              h('td', null, inv.doctorName || '—'),
              h('td', { style: { fontSize: 13, color: 'var(--text-secondary)' } }, inv.date),
              h('td', { style: { fontWeight: 700 } }, window.fmtEGP(inv.total)),
              h('td', { style: { color: 'var(--success)', fontWeight: 600 } }, window.fmtEGP(inv.paid)),
              h('td', { style: { color: inv.total - inv.paid > 0 ? 'var(--danger)' : 'var(--text-muted)', fontWeight: 700 } }, window.fmtEGP(inv.total - inv.paid)),
              h('td', null, h('span', { className: 'chip ' + (inv.status === 'paid' ? 'success' : inv.status === 'partial' ? 'warning' : 'danger') },
                inv.status === 'paid' ? 'مدفوعة' : inv.status === 'partial' ? 'جزئية' : 'غير مدفوعة')),
              h('td', null,
                h('div', { className: 'flex gap-4' },
                  h('button', { className:'btn sm primary', onClick:e=>{e.stopPropagation();setDetailInv(inv);} }, h(Icons.Plus,{size:12}), 'جلسة'),
                  h('button', { className: 'icon-btn', title: 'عرض وتعديل', onClick: e => { e.stopPropagation(); setEditInv(inv); } }, h(Icons.Edit, { size: 14 })),
                  h('button', { className: 'icon-btn', title: 'طباعة', onClick: e => { e.stopPropagation(); printInvoice(inv, clinicName); } }, h(Icons.Printer, { size: 14 })),
                  h('button', {
                    className: 'icon-btn',
                    title: 'حذف الفاتورة',
                    style: { color: 'var(--danger)' },
                    onClick: (e) => { e.stopPropagation(); handleDeleteInvoice(inv); },
                  }, h(Icons.Trash, { size: 14 })),
                ),
              ),
            )) : h('tr', null, h('td', { colSpan:9, style:{textAlign:'center',padding:32,color:'var(--text-tertiary)'} }, 'لا توجد فواتير')),
          ),
        ),
      ),
    ),
    showNewInvoice && h('div', { className:'modal-backdrop', onClick:()=>setShowNewInvoice(false), style:{zIndex:200} },
      h('div', { className:'gm-box', onClick:e=>e.stopPropagation(), style:{width:'min(1020px, calc(100vw - 32px))', maxHeight:'calc(100dvh - 40px)', overflowY:'auto', padding:0} },
        h(NewInvoice, { onClose:()=>setShowNewInvoice(false) }),
      ),
    ),
  );
}

function Sessions() {
  const { sessions, invoices, setScreen } = useContext(AppContext);
  const [query, setQuery] = useState('');
  const [dateFrom, setDateFrom] = useState('');
  const [dateTo, setDateTo] = useState('');
  const [showDateFilter, setShowDateFilter] = useState(false);
  const [activeDatePreset, setActiveDatePreset] = useState('all');

  const setSessionRange = (fromValue, toValue, presetKey = 'custom') => {
    setDateFrom(fromValue || '');
    setDateTo(toValue || '');
    setActiveDatePreset(presetKey);
  };

  const applySessionPreset = (presetKey) => {
    const { fromValue, toValue } = window.resolveDateRangePreset
      ? window.resolveDateRangePreset(presetKey)
      : { fromValue: '', toValue: '' };
    setSessionRange(fromValue, toValue, presetKey);
    setShowDateFilter(false);
  };

  const clearSessionRange = () => {
    setSessionRange('', '', 'all');
    setShowDateFilter(false);
  };

  const selectedRangeLabel = window.getDateRangeLabel
    ? window.getDateRangeLabel(dateFrom, dateTo)
    : 'كل التواريخ';

  const allSessions = (sessions && sessions.length) ? sessions : (window.SESSIONS || []);
  const allInvoices = (invoices && invoices.length) ? invoices : (window.INVOICES || []);
  const invoiceMap = new Map(allInvoices.map(invoice => [String(invoice.id || ''), invoice]));
  const groupedSessions = new Map();
  const remainingBySessionId = new Map();

  allSessions.forEach(session => {
    const invoiceKey = String(session?.invoiceId || '');
    if (!invoiceKey) return;
    if (!groupedSessions.has(invoiceKey)) groupedSessions.set(invoiceKey, []);
    groupedSessions.get(invoiceKey).push(session);
  });

  const formatInvoiceCode = (invoiceId) => (
    typeof invoiceId === 'string' && invoiceId.startsWith('INV')
      ? invoiceId
      : `INV-${String(invoiceId || '').slice(-6)}`
  );

  const sessionRows = [];
  allSessions.forEach(session => {
    const invoiceKey = String(session?.invoiceId || '');
    const invoice = invoiceMap.get(invoiceKey);
    const siblings = [...(groupedSessions.get(invoiceKey) || [session])].sort((a, b) => {
      const aDate = String(a?.date || a?.created_at || '');
      const bDate = String(b?.date || b?.created_at || '');
      if (aDate !== bDate) return aDate.localeCompare(bDate);
      return String(a?.created_at || '').localeCompare(String(b?.created_at || ''));
    });
    let cumulativePaid = 0;
    siblings.forEach(item => {
      cumulativePaid += Number(item?.paidAmount) || 0;
      remainingBySessionId.set(item?.id, Math.max(0, (Number(invoice?.total) || 0) - cumulativePaid));
    });

    sessionRows.push({
      id: session.id,
      patientId: session.patientId || invoice?.patientId || invoice?.patient_id || '',
      patient: session.patient || invoice?.patient || '—',
      date: session.date || invoice?.date || '',
      invoiceCode: formatInvoiceCode(session.invoiceId),
      doctorName: session.doctor || invoice?.doctorName || '—',
      services: String(session.workDone || '').trim() || (invoice?.items || []).map(item => item.name).filter(Boolean).join('، ') || 'خدمة غير محددة',
      total: Number(invoice?.total) || Number(session.paidAmount) || 0,
      paid: Number(session.paidAmount) || 0,
      remaining: Number.isFinite(remainingBySessionId.get(session.id))
        ? remainingBySessionId.get(session.id)
        : Math.max(0, (Number(invoice?.total) || 0) - (Number(session.paidAmount) || 0)),
      notes: session.notes || '',
      nextAppt: session.nextAppt || '',
      source: 'session',
    });
  });

  const dateFilteredSessions = sessionRows.filter(session => {
    const sessionDate = String(session.date || '').slice(0, 10);
    if (dateFrom && (!sessionDate || sessionDate < dateFrom)) return false;
    if (dateTo && (!sessionDate || sessionDate > dateTo)) return false;
    return true;
  });

  const normalizedQuery = query.trim().toLowerCase();
  const filtered = dateFilteredSessions.filter(session => {
    if (!normalizedQuery) return true;
    return [
      session.patient,
      session.doctorName,
      session.services,
      session.notes,
      session.nextAppt,
      session.invoiceCode,
      session.id,
    ].some(value => String(value || '').toLowerCase().includes(normalizedQuery));
  });

  const totalCollected = filtered.reduce((sum, session) => sum + (Number(session.paid) || 0), 0);
  const uniquePatients = new Set(filtered.map(session => String(session.patientId || session.patient || '').trim()).filter(Boolean)).size;
  const uniqueDoctors = new Set(filtered.map(session => String(session.doctorName || '').trim()).filter(Boolean)).size;

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الجلسات'),
        h('div', { className: 'page-subtitle' }, `${filtered.length} ${'جلسة فعلية'}${dateFrom || dateTo ? ` · ${selectedRangeLabel}` : ''}`),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'grid cols-3 mb-16' },
        [
          { label: 'عدد الجلسات', value: window.fmtNum(filtered.length), icon: Icons.FileText, color: 'var(--accent)', soft: 'var(--accent-soft)' },
          { label: 'المحصل الفعلي', value: window.fmtEGP(totalCollected), icon: Icons.CreditCard, color: 'var(--success)', soft: 'var(--success-soft)' },
          { label: 'مرضى الجلسات', value: window.fmtNum(uniquePatients), icon: Icons.Users, color: 'var(--warning)', soft: 'var(--warning-soft)' },
        ].map((card) => h('div', { key: card.label, className: 'card kpi' },
          h('div', { className: 'flex jc-sb ai-c' },
            h('div', null,
              h('div', { className: 'label' }, card.label),
              h('div', { className: 'value' }, card.value),
              card.label === 'مرضى الجلسات'
                ? h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 6 } }, `${window.fmtNum(uniqueDoctors)} ${'طبيب ضمن النتائج'}`)
                : null,
            ),
            h('div', { className: 'kpi-icon', style: { background: card.soft, color: card.color } }, h(card.icon, { size: 20 })),
          ),
        )),
      ),
      h('div', { className: 'card', style: { overflow: 'visible' } },
        h('div', { style: { padding: '12px 16px', borderBottom: '1px solid var(--border)' } },
          h('div', { className: 'flex gap-12 ai-c wrap' },
            h('div', { style: { flex: 1, minWidth: 240, position: 'relative' } },
              h('input', {
                className: 'input',
                placeholder: 'ابحث باسم المريض أو الطبيب أو العمل المنجز...',
                value: query,
                onChange: e => setQuery(e.target.value),
                style: { paddingInlineEnd: 38 },
              }),
              query ? h('button', {
                onClick: () => setQuery(''),
                style: {
                  position: 'absolute', insetInlineEnd: 10, top: '50%', transform: 'translateY(-50%)',
                  background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-tertiary)', padding: 2,
                },
              }, h(Icons.X, { size: 14 })) :
              h('span', {
                style: { position: 'absolute', insetInlineEnd: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-tertiary)', pointerEvents: 'none' },
              }, h(Icons.Search, { size: 15 })),
            ),
            h('div', { style: { flex: '1 1 320px', maxWidth: 'min(320px, 100%)' } },
              h(Shell.DateRangeFilter, {
                title: 'فلتر تاريخ الجلسات',
                subtitle: 'نفس الفلتر الموحد المستخدم في المرضى والفواتير',
                dateFrom,
                dateTo,
                open: showDateFilter,
                onToggle: () => setShowDateFilter(prev => !prev),
                onClose: () => setShowDateFilter(false),
                onPresetSelect: applySessionPreset,
                activePreset: activeDatePreset,
                onFromChange: (value) => {
                  setDateFrom(value);
                  setActiveDatePreset('custom');
                },
                onToChange: (value) => {
                  setDateTo(value);
                  setActiveDatePreset('custom');
                },
                onClear: clearSessionRange,
                onApply: () => setShowDateFilter(false),
                align: 'start',
                buttonWidth: '100%',
                menuWidth: 'min(420px, calc(100vw - 48px))',
              }),
            ),
          ),
        ),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null, [
            'التاريخ',
            'المريض',
            'رقم الفاتورة',
            'الطبيب',
            'الخدمة / الشغل المنجز',
            'إجمالي الفاتورة',
            'مدفوع الجلسة',
            'المتبقي',
            'النوع',
          ].map((title, index) => h('th', { key: index }, title)))),
          h('tbody', null,
            filtered.length ? filtered.map(session => h('tr', { key: session.id },
              h('td', { style: { fontWeight: 700 } }, session.date || '—'),
              h('td', null,
                session.patientId
                  ? h('button', {
                    className: 'btn ghost sm',
                    style: { padding: 0, minHeight: 'auto', color: 'var(--accent)', fontWeight: 700 },
                    onClick: () => setScreen('patient-file', { patientId: session.patientId }),
                  }, session.patient || '—')
                  : (session.patient || '—'),
              ),
              h('td', { style: { fontFamily: 'monospace', fontSize: 12, fontWeight: 700 } }, session.invoiceCode),
              h('td', null, session.doctorName || '—'),
              h('td', null,
                h('div', { style: { fontWeight: 700 } }, session.services || 'خدمة غير محددة'),
                session.nextAppt ? h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, `الموعد القادم: ${session.nextAppt}`) : null,
                session.notes ? h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, session.notes) : null,
              ),
              h('td', { style: { fontWeight: 700 } }, window.fmtEGP(session.total)),
              h('td', { style: { color: 'var(--success)', fontWeight: 700 } }, window.fmtEGP(session.paid)),
              h('td', { style: { color: session.remaining > 0 ? 'var(--danger)' : 'var(--text-muted)', fontWeight: 700 } }, window.fmtEGP(session.remaining)),
              h('td', null, h('span', { className: 'chip accent' }, 'جلسة فعلية')),
            )) : h('tr', null, h('td', { colSpan: 9, style: { textAlign: 'center', padding: 32, color: 'var(--text-tertiary)' } }, 'لا توجد جلسات مطابقة للفلاتر الحالية')),
          ),
        ),
      ),
    ),
  );
}

// ==================== Edit Invoice Notes / Paid Amount ====================
function EditInvoiceModal({ inv, onClose, onSaved }) {
  const { toast, clinicName, services, doctors } = useContext(AppContext);
  const noteMeta = window.decodeInvoiceNotes ? window.decodeInvoiceNotes(inv.notes) : {};
  const allSvcs = (services && services.length) ? services : (window.TREATMENT_TYPES || []);
  const allDoctors = (doctors && doctors.length) ? doctors : (window.DOCTORS || []);
  const [items, setItems] = useState(() => (
    (inv.items && inv.items.length ? inv.items : [{ id: Date.now(), service_id: null, name: '', qty: 1, price: 0, discount: 0 }])
      .map((item, index) => ({
        id: item.id || `edit-item-${index}-${Date.now()}`,
        service_id: item.service_id || null,
        name: item.name || '',
        qty: Math.max(1, Number(item.qty) || 1),
        price: Math.max(0, Number(item.price) || 0),
        discount: Math.max(0, Number(item.discount) || 0),
      }))
  ));
  const [doctorId, setDoctorId] = useState(String(inv.doctorId || noteMeta.doctorId || ''));
  const [payMethod, setPayMethod] = useState(inv.paymentMethod || noteMeta.paymentMethod || 'نقدي');
  const [notes, setNotes] = useState(noteMeta.memo || '');
  const [discount, setDiscount] = useState(Number(inv.discountAmount || noteMeta.discountAmount || 0) || 0);
  const [saving, setSaving] = useState(false);
  const selectedDoctor = allDoctors.find(d => String(d.id || '') === String(doctorId || '')) || null;
  const subtotal = items.reduce((sum, item) => sum + ((Number(item.qty) || 0) * (Number(item.price) || 0)), 0);
  const discountAmt = Math.min(Math.max(Number(discount) || 0, 0), subtotal);
  const discountPercentValue = subtotal > 0 ? (discountAmt / subtotal) * 100 : 0;
  const total = subtotal - discountAmt;
  const addItem = () => setItems(prev => [...prev, { id: `edit-item-${Date.now()}`, service_id: null, name: '', qty: 1, price: 0, discount: 0 }]);
  const removeItem = (id) => setItems(prev => prev.filter(item => item.id !== id));
  const updateItem = (id, patch) => setItems(prev => prev.map(item => item.id === id ? { ...item, ...patch } : item));

  const handleSave = async () => {
    const cleanedItems = items
      .map(item => ({
        service_id: item.service_id || null,
        name: String(item.name || '').trim(),
        qty: Math.max(1, Number(item.qty) || 1),
        price: Math.max(0, Number(item.price) || 0),
        discount: Math.max(0, Number(item.discount) || 0),
      }))
      .filter(item => item.name);
    if (!cleanedItems.length) { toast('أضف خدمة واحدة على الأقل'); return; }
    setSaving(true);
    try {
      const encodedNotes = window.encodeInvoiceNotes
        ? window.encodeInvoiceNotes({
            paymentMethod: payMethod,
            doctorId: selectedDoctor ? selectedDoctor.id : null,
            doctorName: selectedDoctor ? selectedDoctor.name : '',
            memo: notes,
            discountPercent: discountPercentValue,
            discountAmount: discountAmt,
            subtotal,
            total,
          })
        : notes;
      const updatedInvoice = await DB.updateInvoice(inv.id, {
        patient_id: inv.patientId || inv.patient_id || null,
        date: inv.date || new Date().toISOString().split('T')[0],
        notes: encodedNotes,
        doctor_id: selectedDoctor ? selectedDoctor.id : null,
        doctor_name: selectedDoctor ? selectedDoctor.name : '',
        total,
        paid: Number(inv.paid) || 0,
      }, cleanedItems);
      toast('تم الحفظ ✅');
      onSaved(updatedInvoice);
      onClose();
    } catch(e) { toast('خطأ: ' + (e.message || 'غير متوقع')); }
    finally { setSaving(false); }
  };

  const invId = typeof inv.id === 'string' && inv.id.startsWith('INV') ? inv.id : 'INV-' + String(inv.id).slice(-6);

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:'min(960px, calc(100vw - 32px))', maxHeight:'calc(100dvh - 40px)', overflowY:'auto', padding:24 } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16} },
        h('div', null,
          h('div', { style:{fontWeight:800,fontSize:16} }, 'تعديل الفاتورة'),
          h('div', { style:{fontSize:13,color:'var(--text-tertiary)',marginTop:2} }, invId + ' · ' + inv.patient),
        ),
        h('div', { className:'flex gap-8' },
          h('button', {
            className:'btn sm outline',
            onClick:()=>printInvoice({
              ...inv,
              items,
              total,
              doctorName: selectedDoctor ? selectedDoctor.name : inv.doctorName,
              paymentMethod: payMethod,
              notes,
            }, clinicName),
          }, h(Icons.Printer,{size:14}), 'طباعة'),
          h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
        ),
      ),
      h('div', { style: { display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 20 } },
        h('div', null,
          h('div', { className:'card mb-14', style:{padding:16} },
            h('div', { className:'grid cols-2', style:{gap:12} },
              h('div', null,
                h('div', { className:'label' }, 'المريض'),
                h('div', { className:'input', style:{display:'flex',alignItems:'center',background:'var(--bg-subtle)',fontWeight:700} }, inv.patient || '—'),
              ),
              h('div', null,
                h('div', { className:'label' }, 'الطبيب'),
                h('select', { className:'select', value:doctorId, onChange:e=>setDoctorId(e.target.value) },
                  h('option', { value:'' }, allDoctors.length ? '— اختر الطبيب —' : 'لا يوجد أطباء'),
                  allDoctors.map(d => h('option', { key:d.id || d.name, value:String(d.id || '') }, `${d.name}${d.specialty ? ' — ' + d.specialty : ''}`)),
                ),
              ),
            ),
          ),
          h('div', { className:'card mb-14', style:{overflow:'hidden'} },
            h('table', { className:'data-table', style:{fontSize:12} },
              h('thead', null, h('tr', null, ['الخدمة','الكمية','السعر','الإجمالي',''].map((t,i)=>h('th',{key:i},t)))),
              h('tbody', null,
                items.length === 0
                  ? h('tr', null, h('td', { colSpan:5, style:{textAlign:'center',color:'var(--text-tertiary)',padding:16} }, 'لا توجد بنود مسجلة'))
                  : items.map((it) => h('tr',{key:it.id},
                    h('td', null,
                      h('select', {
                        className:'select',
                        style:{padding:'5px 8px',fontSize:12},
                        value: it.service_id || '',
                        onChange: e => {
                          const svc = allSvcs.find(s => String(s.id) === String(e.target.value));
                          if (svc) {
                            updateItem(it.id, {
                              service_id: svc.id,
                              name: svc.name,
                              price: Number(svc.price) || 0,
                            });
                          } else {
                            updateItem(it.id, { service_id: null });
                          }
                        },
                      },
                        h('option', { value:'' }, it.name || '— اختر خدمة —'),
                        allSvcs.map(s => h('option', { key:s.id, value:s.id }, `${s.name} · ${window.fmtEGP(s.price)}`)),
                      ),
                      h('input', {
                        className:'input mt-8',
                        style:{padding:6,fontSize:12},
                        value: it.name,
                        placeholder:'أو اكتب اسم خدمة يدويًا',
                        onChange: e => updateItem(it.id, { name: e.target.value }),
                      }),
                    ),
                    h('td', { style:{width:80} }, h('input', {
                      className:'input',
                      type:'number',
                      min:1,
                      style:{padding:6,fontSize:13},
                      value: it.qty,
                      onChange: e => updateItem(it.id, { qty: Math.max(1, Number(e.target.value) || 1) }),
                    })),
                    h('td', { style:{width:110} }, h('input', {
                      className:'input',
                      type:'number',
                      min:0,
                      style:{padding:6,fontSize:13},
                      value: it.price,
                      onChange: e => updateItem(it.id, { price: Math.max(0, Number(e.target.value) || 0) }),
                    })),
                    h('td', { style:{fontWeight:700,width:110} }, window.fmtEGP((Number(it.qty) || 0) * (Number(it.price) || 0))),
                    h('td', { style:{width:40} }, h('button', {
                      className:'icon-btn',
                      onClick: () => removeItem(it.id),
                      disabled: items.length === 1,
                    }, h(Icons.Trash, { size:14 }))),
                  )),
              ),
            ),
            h('div', { style:{padding:12,borderTop:'1px solid var(--border)'} },
              h('button', { className:'btn outline sm', onClick:addItem }, h(Icons.Plus, { size:14 }), 'إضافة خدمة'),
            ),
          ),
          h('div', null,
            h('div', { className:'label' }, 'ملاحظات الفاتورة'),
            h('textarea', { className:'textarea', rows:4, value:notes, onChange:e=>setNotes(e.target.value) }),
          ),
        ),
        h('div', { className:'card p-20', style:{height:'fit-content'} },
          h('div', { style:{fontWeight:800,fontSize:15,marginBottom:16} }, 'الملخص'),
          h('div', { style:{display:'flex',flexDirection:'column',gap:10} },
            h('div', { className:'flex jc-sb', style:{fontSize:13} },
              h('span', { style:{color:'var(--text-tertiary)'} }, 'إجمالي الخدمات'),
              h('span', { style:{fontWeight:700} }, window.fmtEGP(subtotal)),
            ),
            h('div', { className:'flex jc-sb ai-c' },
              h('span', { style:{fontSize:13,color:'var(--text-tertiary)'} }, 'الخصم'),
              h('input', {
                type:'number',
                className:'input',
                style:{width:100,padding:6,fontSize:13},
                value: discount,
                onChange:e=>setDiscount(e.target.value),
              }),
            ),
            h('div', { className:'flex jc-sb', style:{fontSize:13,color:'var(--danger)'} },
              h('span', null, 'قيمة الخصم'),
              h('span', null, '- ' + window.fmtEGP(discountAmt)),
            ),
            h('div', { className:'divider' }),
            h('div', { className:'flex jc-sb', style:{fontSize:20,fontWeight:800} },
              h('span', null, 'الإجمالي النهائي'),
              h('span', { style:{color:'var(--accent)'} }, window.fmtEGP(total)),
            ),
          ),
          h('div', { className:'label mt-16' }, 'طريقة الدفع'),
          h('div', { className:'grid cols-2', style:{gap:6} },
            ['نقدي', 'فيزا', 'تحويل', 'تأمين'].map(method => h('button', {
              key: method,
              className: 'btn sm ' + (payMethod === method ? 'primary' : 'outline'),
              onClick: () => setPayMethod(method),
            }, method)),
          ),
        ),
      ),
      h('div', { className:'flex gap-8 jc-sb mt-16' },
        h('button', { className:'btn outline', onClick:onClose }, 'إغلاق'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave },
          saving ? 'جاري الحفظ...' : 'حفظ التعديلات'),
      ),
    ),
  );
}

// ==================== New Invoice ====================
function NewInvoice({ onClose } = {}) {
  const { setScreen, toast, clinicId, setInvoices, invoices, patients, doctors, services } = useContext(AppContext);
  const handleClose = () => onClose ? onClose() : setScreen('billing');
  const allPts  = (patients && patients.length) ? patients : (window.PATIENTS || []);
  const allDoctors = (doctors && doctors.length) ? doctors : (window.DOCTORS || []);
  const allSvcs = (services && services.length) ? services : (window.TREATMENT_TYPES || []);
  const [items, setItems] = useState([{ id: 1, service_id: null, name: 'كشف وفحص', qty: 1, price: 150 }]);
  const [patient, setPatient] = useState(null);
  const [patientQuery, setPatientQuery] = useState('');
  const [doctorId, setDoctorId] = useState('');
  const nextInvNum = `INV-${new Date().getFullYear()}-${String((invoices ? invoices.length : 0) + 1).padStart(4, '0')}`;
  const [payMethod, setPayMethod] = useState('نقدي');
  const [showQuickAdd, setShowQuickAdd] = useState(false);
  useEffect(() => {
    if (!doctorId && allDoctors.length) setDoctorId(String(allDoctors[0].id || ''));
  }, [allDoctors.length, doctorId]);
  const [saving, setSaving] = useState(false);
  const [discount, setDiscount] = useState(0);
  const subtotal = items.reduce((s, i) => s + i.qty * i.price, 0);
  const discountAmt = Math.min(Math.max(Number(discount) || 0, 0), subtotal);
  const discountPercentValue = subtotal > 0 ? (discountAmt / subtotal) * 100 : 0;
  const total = subtotal - discountAmt;
  const selectedDoctor = allDoctors.find(d => String(d.id || '') === String(doctorId || '')) || null;
  const filteredPatients = useMemo(() => {
    const q = String(patientQuery || '').trim().toLowerCase();
    const source = allPts.slice(0, q ? allPts.length : 6);
    return source.filter(p => {
      if (!q) return true;
      return [p.name, p.phone, p.id].join(' ').toLowerCase().includes(q);
    }).slice(0, 8);
  }, [allPts, patientQuery]);

  const addItem = () => setItems([...items, { id: Date.now(), service_id: null, name: '', qty: 1, price: 0 }]);
  const removeItem = (id) => setItems(items.filter(i => i.id !== id));
  const updateItem = (id, field, val) => setItems(items.map(i => i.id === id ? { ...i, [field]: val } : i));

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', { className: 'flex gap-12 ai-c' },
        h('button', { className: 'icon-btn', onClick: handleClose }, h(Icons.ChevronRight, { size: 18 })),
        h('div', null,
          h('div', { className: 'page-title' }, 'فاتورة جديدة'),
          h('div', { className: 'page-subtitle' }, nextInvNum),
        ),
      ),
      h('div', { className: 'flex gap-8' },
        h('button', { className: 'btn outline', onClick: handleClose }, 'إلغاء'),
        h('button', {
          className: 'btn primary',
          disabled: saving,
          onClick: async () => {
            if (!patient) { toast('اختر مريضاً أولاً'); return; }
            if (allDoctors.length && !selectedDoctor) { toast('اختر الطبيب أولاً'); return; }
            setSaving(true);
            try {
              const encodedNotes = window.encodeInvoiceNotes
                ? window.encodeInvoiceNotes({
                    paymentMethod: payMethod,
                    doctorId: selectedDoctor ? selectedDoctor.id : null,
                    doctorName: selectedDoctor ? selectedDoctor.name : '',
                    memo: '',
                    discountPercent: discountPercentValue,
                    discountAmount: discountAmt,
                    subtotal,
                    total,
                  })
                : JSON.stringify({
                    paymentMethod: payMethod,
                    doctorId: selectedDoctor ? selectedDoctor.id : null,
                    doctorName: selectedDoctor ? selectedDoctor.name : '',
                    memo: '',
                    discountPercent: discountPercentValue,
                    discountAmount: discountAmt,
                    subtotal,
                    total,
                  });
              const inv = await DB.addInvoice(clinicId,
                {
                  patient_id: patient.id,
                  date: new Date().toISOString().split('T')[0],
                  notes: encodedNotes,
                  doctor_id: selectedDoctor ? selectedDoctor.id : null,
                  doctor_name: selectedDoctor ? selectedDoctor.name : '',
                  total,
                },
                items.map(it => ({ service_id: it.service_id || null, name: it.name, qty: it.qty, price: it.price, discount: 0 }))
              );
              setInvoices([inv, ...invoices]);
              toast('تم إنشاء الفاتورة بنجاح ✅');
              handleClose();
            } catch(e) {
              console.error(e);
              toast('حدث خطأ أثناء الحفظ');
            } finally { setSaving(false); }
          },
        }, h(Icons.Check, { size: 16 }), saving ? 'جاري الحفظ...' : 'حفظ الفاتورة'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { style: { display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 20 } },
        h('div', { className: 'card p-20' },
          h('div', { className: 'label' }, 'المريض'),
          h('div', { className: 'mb-16' },
            h('div', { className: 'flex gap-8', style: { alignItems: 'center' } },
              h('input', {
                className: 'input',
                style: { flex: 1 },
                value: patientQuery,
                placeholder: 'اكتب اسم المريض أو رقم الهاتف...',
                onChange: (e) => {
                  setPatientQuery(e.target.value);
                  setPatient(null);
                },
              }),
              h('button', {
                className: 'icon-btn',
                onClick: () => setShowQuickAdd(true),
                title: 'إضافة مريض جديد',
                style: { width: 44, height: 44, flex: '0 0 44px' },
              },
                h(Icons.UserPlus, { size: 18 }),
              ),
            ),
            h('div', {
              style: {
                marginTop: 6,
                maxHeight: 220,
                overflowY: 'auto',
                border: '1px solid var(--border)',
                borderRadius: 'var(--radius)',
                background: 'var(--bg-elevated)',
              },
            },
              filteredPatients.length === 0
                ? h('div', { style: { padding: '12px 14px', color: 'var(--text-tertiary)', fontSize: 13 } }, 'لا توجد نتائج')
                : filteredPatients.map(p => h('button', {
                    key: p.id,
                    type: 'button',
                    onClick: () => {
                      setPatient(p);
                      setPatientQuery(p.name || '');
                    },
                    style: {
                      width: '100%',
                      padding: '10px 12px',
                      display: 'flex',
                      alignItems: 'center',
                      gap: 10,
                      textAlign: 'right',
                      border: 0,
                      borderBottom: '1px solid var(--border)',
                      background: patient?.id === p.id ? 'var(--accent-soft)' : 'transparent',
                      cursor: 'pointer',
                    },
                  },
                    h('div', { className: 'avatar sm', style: { flexShrink: 0 } }, p.avatar || (p.name || '?').charAt(0)),
                    h('div', { style: { flex: 1, minWidth: 0 } },
                      h('div', { style: { fontWeight: 700, fontSize: 13 } }, p.name),
                      h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, p.phone || p.id || 'لا يوجد هاتف'),
                    ),
                    patient?.id === p.id ? h(Icons.Check, { size: 16 }) : null,
                  )),
            ),
          ),
          showQuickAdd ? h(QuickAddPatientModal, {
            onClose: () => setShowQuickAdd(false),
            onSaved: (newP) => { setPatient(newP); setPatientQuery(newP.name || ''); },
          }) : null,
          h('div', { className: 'label' }, 'الطبيب'),
          h('select', {
            className: 'select mb-16',
            value: doctorId,
            onChange: (e) => setDoctorId(e.target.value),
          },
            h('option', { value: '' }, allDoctors.length ? '— اختر الطبيب —' : 'لا يوجد أطباء مضافين'),
            allDoctors.map(d => h('option', { key: d.id || d.name, value: String(d.id || '') }, `${d.name}${d.specialty ? ' — ' + d.specialty : ''}`)),
          ),
          h('div', { className: 'label' }, 'البنود'),
          h('div', { className: 'card', style: { overflow: 'hidden', marginBottom: 8 } },
            h('table', { className: 'data-table', style: { fontSize: 13 } },
              h('thead', null, h('tr', null, ['الإجراء', 'الكمية', 'السعر', 'الإجمالي', ''].map((t, i) => h('th', { key: i }, t)))),
              h('tbody', null,
                items.map(it => h('tr', { key: it.id },
                  h('td', null,
                    h('select', {
                      className: 'select',
                      style: { padding: '5px 8px', fontSize: 12 },
                      value: it.service_id || '',
                      onChange: e => {
                        const svc = allSvcs.find(s => s.id === e.target.value);
                        if (svc) setItems(prev => prev.map(i => i.id === it.id ? { ...i, service_id: svc.id, name: svc.name, price: svc.price } : i));
                        else setItems(prev => prev.map(i => i.id === it.id ? { ...i, service_id: null } : i));
                      },
                    },
                      h('option', { value: '' }, it.name || '— اختر خدمة —'),
                      allSvcs.map(s => h('option', { key: s.id, value: s.id }, s.name + ' · ' + window.fmtEGP(s.price))),
                    ),
                  ),
                  h('td', { style: { width: 70 } }, h('input', { className: 'input', type: 'number', style: { padding: 6, fontSize: 13 }, value: it.qty, onChange: (e) => updateItem(it.id, 'qty', +e.target.value) })),
                  h('td', { style: { width: 100 } }, h('input', { className: 'input', type: 'number', style: { padding: 6, fontSize: 13 }, value: it.price, onChange: (e) => updateItem(it.id, 'price', +e.target.value) })),
                  h('td', { style: { fontWeight: 700, width: 100 } }, window.fmtEGP(it.qty * it.price)),
                  h('td', { style: { width: 40 } }, h('button', { className: 'icon-btn', onClick: () => removeItem(it.id) }, h(Icons.Trash, { size: 14 }))),
                )),
              ),
            ),
          ),
          h('button', { className: 'btn outline sm', onClick: addItem }, h(Icons.Plus, { size: 14 }), 'إضافة بند'),
          h('div', { className: 'mt-16' },
            h('div', { className: 'label' }, 'ملاحظات'),
            h('textarea', { className: 'textarea', rows: 2, placeholder: 'أي ملاحظات على الفاتورة...' }),
          ),
        ),
        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 16 } }, 'الملخص'),
          h('div', { style: { display: 'flex', flexDirection: 'column', gap: 10 } },
            h('div', { className: 'flex jc-sb', style: { fontSize: 13 } },
              h('span', { style: { color: 'var(--text-tertiary)' } }, 'إجمالي الخدمات'), h('span', { style: { fontWeight: 600 } }, window.fmtEGP(subtotal)),
            ),
            h('div', { className: 'flex jc-sb ai-c' },
              h('span', { style: { fontSize: 13, color: 'var(--text-tertiary)' } }, 'الخصم'),
              h('input', { type: 'number', className: 'input', style: { width: 90, padding: 6, fontSize: 13 }, value: discount, onChange: (e) => setDiscount(+e.target.value) }),
            ),
            h('div', { className: 'flex jc-sb', style: { fontSize: 13, color: 'var(--danger)' } },
              h('span', null, 'قيمة الخصم'), h('span', null, '- ' + window.fmtEGP(discountAmt)),
            ),
            h('div', { className: 'divider' }),
            h('div', { className: 'flex jc-sb', style: { fontSize: 20, fontWeight: 800 } },
              h('span', null, 'الإجمالي النهائي'), h('span', { style: { color: 'var(--accent)' } }, window.fmtEGP(total)),
            ),
          ),
          h('div', { className: 'label mt-16' }, 'طريقة الدفع'),
          h('div', { className: 'grid cols-2', style: { gap: 6 } },
            ['نقدي', 'فيزا', 'تحويل', 'تأمين'].map(m => h('button', {
              key: m,
              className: 'btn sm ' + (payMethod === m ? 'primary' : 'outline'),
              onClick: () => setPayMethod(m),
            }, m)),
          ),
        ),
      ),
    ),
  );
}

// ==================== Treatments (plans) ====================
function Treatments() {
  const { setScreen } = useContext(AppContext);
  const plans = [
    { id: 'TP1', patient: 'أحمد محمد السيد', doctor: 'د. سارة', status: 'جارية', progress: 60, procedures: 6, startDate: '2026-02-15', total: 8500, paid: 5000 },
    { id: 'TP2', patient: 'فاطمة علي حسن', doctor: 'د. منى', status: 'جارية', progress: 35, procedures: 18, startDate: '2026-01-10', total: 35000, paid: 12000 },
    { id: 'TP3', patient: 'محمد عبد الرحمن', doctor: 'د. سارة', status: 'جارية', progress: 85, procedures: 4, startDate: '2026-03-20', total: 4500, paid: 1100 },
    { id: 'TP4', patient: 'رنا أشرف', doctor: 'د. منى', status: 'مسودة', progress: 0, procedures: 8, startDate: '2026-04-18', total: 12000, paid: 0 },
    { id: 'TP5', patient: 'سلمى حسام', doctor: 'د. خالد', status: 'مكتملة', progress: 100, procedures: 3, startDate: '2025-11-15', total: 6000, paid: 6000 },
  ];

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'خطط العلاج'),
        h('div', { className: 'page-subtitle' }, `${plans.filter(p => p.status === 'جارية').length} خطة جارية · ${plans.length} خطة إجمالاً`),
      ),
      h('div', { className: 'flex gap-8' },
        h('button', { className: 'btn primary', onClick: () => setScreen('billing') }, h(Icons.Plus, { size: 16 }), 'فاتورة/خطة جديدة'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'grid', style: { gap: 12 } },
        plans.map(p => h('div', { key: p.id, className: 'card p-20', style: { cursor: 'pointer' }, onClick: () => setScreen('billing') },
          h('div', { style: { display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1.5fr 80px', gap: 20, alignItems: 'center' } },
            h('div', null,
              h('div', { style: { fontWeight: 800, fontSize: 15 } }, p.patient),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, `${p.id} · ${p.doctor} · ${p.procedures} إجراءات`),
            ),
            h('div', null,
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'التاريخ'),
              h('div', { style: { fontSize: 13, fontWeight: 600, marginTop: 2 } }, p.startDate),
            ),
            h('div', null,
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'الإجمالي'),
              h('div', { style: { fontSize: 14, fontWeight: 800, marginTop: 2 } }, window.fmtEGP(p.total)),
              h('div', { style: { fontSize: 11, color: 'var(--success)' } }, 'مدفوع: ' + window.fmtEGP(p.paid)),
            ),
            h('div', null,
              h('div', { className: 'flex jc-sb ai-c mb-4' },
                h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'التقدم'),
                h('span', { style: { fontSize: 12, fontWeight: 700 } }, p.progress + '%'),
              ),
              h('div', { className: 'progress' },
                h('div', { className: 'progress-bar', style: { width: p.progress + '%', background: p.status === 'مكتملة' ? 'var(--success)' : 'var(--accent)' } }),
              ),
            ),
            h('span', { className: 'chip ' + (p.status === 'مكتملة' ? 'success' : p.status === 'جارية' ? 'info' : '') }, p.status),
          ),
        )),
      ),
    ),
  );
}

// ==================== Print Invoice ====================
function printInvoice(inv, clinicName) {
  const statusLabel = { paid:'مدفوعة', partial:'جزئية', unpaid:'غير مدفوعة' };
  const invId = typeof inv.id === 'string' && inv.id.startsWith('INV') ? inv.id : 'INV-' + String(inv.id).slice(-6);
  const rows = (inv.items || []).map(it =>
    `<tr><td>${it.name}</td><td style="text-align:center">${it.qty}</td><td style="text-align:left">${window.fmtEGP(it.price)}</td><td style="text-align:left">${window.fmtEGP(it.qty*it.price - (it.discount||0))}</td></tr>`
  ).join('');

  const html = `<!DOCTYPE html><html dir="rtl" lang="ar">
<head><meta charset="UTF-8"><title>فاتورة ${invId}</title>
<style>
  body{font-family:Arial,sans-serif;font-size:13px;color:#222;margin:0;padding:32px;direction:rtl}
  .header{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid #0891b2;padding-bottom:16px;margin-bottom:20px}
  .clinic-name{font-size:22px;font-weight:900;color:#0891b2}
  .inv-meta{text-align:left;font-size:12px;color:#555}
  .inv-id{font-size:18px;font-weight:700;color:#333}
  table{width:100%;border-collapse:collapse;margin-bottom:20px}
  th{background:#0891b2;color:#fff;padding:8px 10px;text-align:right;font-size:12px}
  td{padding:7px 10px;border-bottom:1px solid #eee;font-size:12px}
  tr:nth-child(even) td{background:#f8fafb}
  .totals{float:left;min-width:220px}
  .totals table td{border:none;padding:4px 8px}
  .grand-total td{font-size:16px;font-weight:900;color:#0891b2;border-top:2px solid #0891b2}
  .status-chip{display:inline-block;padding:3px 12px;border-radius:999px;font-size:11px;font-weight:700;
    background:${inv.status==='paid'?'#d1fae5':inv.status==='partial'?'#fef3c7':'#fee2e2'};
    color:${inv.status==='paid'?'#065f46':inv.status==='partial'?'#92400e':'#991b1b'}}
  .footer{margin-top:40px;border-top:1px solid #eee;padding-top:12px;font-size:11px;color:#999;text-align:center}
  @media print{body{padding:16px} button{display:none}}
</style></head>
<body>
<div class="header">
  <div>
    <div class="clinic-name">${clinicName || 'سِنان كلينيك'}</div>
    <div style="font-size:12px;color:#666;margin-top:4px">عيادة أسنان متكاملة</div>
  </div>
  <div class="inv-meta">
    <div class="inv-id">${invId}</div>
    <div>التاريخ: ${inv.date || '—'}</div>
    <div>المريض: <strong>${inv.patient || '—'}</strong></div>
    <div>الطبيب: <strong>${inv.doctorName || '—'}</strong></div>
    <div style="margin-top:6px"><span class="status-chip">${statusLabel[inv.status]||'—'}</span></div>
  </div>
</div>

<table>
  <thead><tr><th>الخدمة / الإجراء</th><th style="text-align:center">الكمية</th><th style="text-align:left">سعر الوحدة</th><th style="text-align:left">الإجمالي</th></tr></thead>
  <tbody>${rows || '<tr><td colspan="4" style="text-align:center;color:#999">لا توجد بنود</td></tr>'}</tbody>
</table>

<div class="totals">
  <table>
    <tr><td>الإجمالي:</td><td><strong>${window.fmtEGP(inv.total)}</strong></td></tr>
    <tr><td>المدفوع:</td><td style="color:#059669"><strong>${window.fmtEGP(inv.paid)}</strong></td></tr>
    <tr class="grand-total"><td>المتبقي:</td><td>${window.fmtEGP(inv.total - inv.paid)}</td></tr>
  </table>
</div>
<div style="clear:both"></div>

<div class="footer">
  شكراً لثقتكم • ${clinicName || 'سِنان كلينيك'} • تم إنشاء هذه الفاتورة إلكترونياً
</div>
</body></html>`;
  const iframe = document.createElement('iframe');
  iframe.style.position = 'fixed';
  iframe.style.right = '0';
  iframe.style.bottom = '0';
  iframe.style.width = '0';
  iframe.style.height = '0';
  iframe.style.border = '0';
  iframe.style.opacity = '0';
  iframe.setAttribute('aria-hidden', 'true');
  const cleanup = () => setTimeout(() => iframe.remove(), 100);
  iframe.onload = () => {
    const win = iframe.contentWindow;
    const doc = iframe.contentDocument;
    if (!win || !doc) {
      cleanup();
      return;
    }
    try {
      doc.open();
      doc.write(html);
      doc.close();
    } catch (error) {
      console.warn('[InvoicePrint] write failed:', error);
      cleanup();
      return;
    }
    let printed = false;
    const triggerPrint = () => {
      if (printed) return;
      printed = true;
      try {
        win.focus();
        win.print();
      } catch (error) {
        console.warn('[InvoicePrint] print failed:', error);
        cleanup();
      }
    };
    win.onafterprint = cleanup;
    setTimeout(triggerPrint, 250);
    setTimeout(() => { if (!printed) cleanup(); }, 5000);
  };
  document.body.appendChild(iframe);
  iframe.src = 'about:blank';
}

// ==================== Add Service Modal ====================
function AddServiceModal({ onClose, onSaved }) {
  const { clinicId, toast } = useContext(AppContext);
  const [form, setForm] = useState({ name: '', price: '', duration: 30, category: '' });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    if (!form.name.trim()) { toast('اسم الخدمة مطلوب'); return; }
    if (!form.price || +form.price <= 0) { toast('السعر مطلوب'); return; }
    setSaving(true);
    try {
      const svc = await DB.addService(clinicId, {
        name: form.name.trim(),
        price: +form.price,
        duration: +form.duration || 30,
        category: form.category.trim() || 'عام',
      });
      toast('تم إضافة الخدمة ✅');
      onSaved(svc);
      onClose();
    } catch(e) { toast('خطأ: ' + (e.message || 'غير متوقع')); }
    finally { setSaving(false); }
  };

  const categories = ['فحص وتشخيص', 'تنظيف', 'حشو', 'علاج عصب', 'خلع', 'تركيبات', 'تقويم', 'تجميل', 'جراحة', 'أشعة', 'عام'];

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:440, padding:24 } },
      h('div', { className:'modal-header' },
        h('div', { className:'modal-title' }, '🦷 إضافة خدمة جديدة'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{padding:'20px 24px', display:'grid', gap:14} },
        h('div', null,
          h('div', { className:'label' }, 'اسم الخدمة *'),
          h('input', { className:'input', placeholder:'حشو عصب، تاج زيركون...', value:form.name, onChange:e=>set('name',e.target.value) }),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null,
            h('div', { className:'label' }, 'السعر (ج.م) *'),
            h('input', { className:'input', type:'number', min:0, placeholder:'500', value:form.price, onChange:e=>set('price',e.target.value) }),
          ),
          h('div', null,
            h('div', { className:'label' }, 'المدة (دقيقة)'),
            h('input', { className:'input', type:'number', min:5, value:form.duration, onChange:e=>set('duration',e.target.value) }),
          ),
        ),
        h('div', null,
          h('div', { className:'label' }, 'الفئة'),
          h('select', { className:'select', value:form.category, onChange:e=>set('category',e.target.value) },
            h('option', { value:'' }, '— اختر فئة —'),
            categories.map(c => h('option', { key:c, value:c }, c)),
          ),
        ),
      ),
      h('div', { className:'modal-footer' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave },
          saving ? 'جاري الحفظ...' : 'إضافة الخدمة'),
      ),
    ),
  );
}

// ==================== Add Inventory Modal ====================
function AddInventoryModal({ onClose, onSaved }) {
  const { clinicId, toast } = useContext(AppContext);
  const [form, setForm] = useState({ name: '', category: '', stock: '', minStock: '', unit: 'قطعة', price: '', usageUnitsPerPack: '', expiry: '' });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    if (!form.name.trim()) { toast('اسم الصنف مطلوب'); return; }
    setSaving(true);
    try {
      const item = await DB.addInventoryItem(clinicId, {
        name: form.name.trim(),
        category: form.category.trim() || 'عام',
        stock: +form.stock || 0,
        min_stock: +form.minStock || 0,
        unit: form.unit || 'قطعة',
        price: +form.price || 0,
        usageUnitsPerPack: Math.max(0, Number(form.usageUnitsPerPack) || 0),
        supplier: null,
        expiry: form.expiry || null,
      });
      toast('تم إضافة الصنف ✅');
      onSaved(item, item.usageUnitsPerPack);
      onClose();
    } catch(e) { toast('خطأ: ' + (e.message || 'غير متوقع')); }
    finally { setSaving(false); }
  };

  const invCategories = ['مواد حشو', 'مواد تنظيف', 'أدوات', 'مواد أشعة', 'تركيبات', 'مواد تخدير', 'قفازات ومستلزمات', 'أدوية', 'عام'];
  const units = ['قطعة', 'علبة', 'زجاجة', 'كيس', 'كرتون', 'أمبول', 'لفة', 'كبسولة', 'مل', 'جرام'];

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:500, padding:24, maxHeight:'90vh', overflowY:'auto' } },
      h('div', { className:'modal-header' },
        h('div', { className:'modal-title' }, '📦 إضافة صنف جديد'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{padding:'20px 24px', display:'grid', gap:12} },
        h('div', null,
          h('div', { className:'label' }, 'اسم الصنف *'),
          h('input', { className:'input', placeholder: 'مثال: كومبوزيت A2، قفازات S...', value:form.name, onChange:e=>set('name',e.target.value) }),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null,
            h('div', { className:'label' }, 'الفئة'),
            h('select', { className:'select', value:form.category, onChange:e=>set('category',e.target.value) },
              h('option', { value:'' }, '— اختر —'),
              invCategories.map(c => h('option', { key:c, value:c }, c)),
            ),
          ),
          h('div', null,
            h('div', { className:'label' }, 'وحدة القياس'),
            h('select', { className:'select', value:form.unit, onChange:e=>set('unit',e.target.value) },
              units.map(u => h('option', { key:u, value:u }, u)),
            ),
          ),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr 1fr',gap:12} },
          h('div', null, h('div', { className:'label' }, 'الكمية الحالية'), h('input', { className:'input', type:'number', min:0, value:form.stock, onChange:e=>set('stock',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'الحد الأدنى'), h('input', { className:'input', type:'number', min:0, value:form.minStock, onChange:e=>set('minStock',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'السعر (ج.م)'), h('input', { className:'input', type:'number', min:0, value:form.price, onChange:e=>set('price',e.target.value) })),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null, h('div', { className:'label' }, 'عدد وحدات الاستخدام داخل العبوة'), h('input', { className:'input', type:'number', min:0, placeholder:'مثال: 18', value:form.usageUnitsPerPack, onChange:e=>set('usageUnitsPerPack',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'تاريخ الصلاحية (اختياري)'), h('input', { className:'input', type:'date', value:form.expiry, onChange:e=>set('expiry',e.target.value) })),
        ),
      ),
      h('div', { className:'modal-footer' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave },
          saving ? 'جاري الحفظ...' : 'إضافة الصنف'),
      ),
    ),
  );
}

// ==================== Edit Inventory Modal ====================
function EditInventoryModal({ item, onClose, onSaved }) {
  const { toast } = useContext(AppContext);
  const normalizeDateValue = (value) => (/^\d{4}-\d{2}-\d{2}$/.test(String(value || '').trim()) ? String(value).trim() : '');
  const [form, setForm] = useState({
    name: item.name || '',
    category: item.category || '',
    stock: item.stock ?? '',
    minStock: item.minStock ?? '',
    unit: item.unit || 'قطعة',
    price: item.price ?? '',
    usageUnitsPerPack: item.usageUnitsPerPack ?? '',
    expiry: normalizeDateValue(item.expiry),
  });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const invCategories = ['مواد حشو', 'مواد تنظيف', 'أدوات', 'مواد أشعة', 'تركيبات', 'مواد تخدير', 'قفازات ومستلزمات', 'أدوية', 'عام'];
  const units = ['قطعة', 'علبة', 'زجاجة', 'كيس', 'كرتون', 'أمبول', 'لفة', 'كبسولة', 'مل', 'جرام'];

  const handleSave = async () => {
    if (!form.name.trim()) { toast('اسم الصنف مطلوب'); return; }
    setSaving(true);
    try {
      const updated = await DB.updateInventoryItem(item.id, {
        name: form.name.trim(),
        category: form.category.trim() || 'عام',
        stock: +form.stock || 0,
        min_stock: +form.minStock || 0,
        unit: form.unit || 'قطعة',
        price: +form.price || 0,
        usageUnitsPerPack: Math.max(0, Number(form.usageUnitsPerPack) || 0),
        expiry: normalizeDateValue(form.expiry) || null,
      });
      toast('تم تحديث الصنف ✅');
      onSaved(updated, updated.usageUnitsPerPack);
      onClose();
    } catch (e) {
      toast('خطأ: ' + (e.message || 'غير متوقع'));
    } finally {
      setSaving(false);
    }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:500, padding:24, maxHeight:'90vh', overflowY:'auto' } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:20} },
        h('div', { style:{fontWeight:800,fontSize:17} }, 'تعديل صنف'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{padding:'20px 24px', display:'grid', gap:12} },
        h('div', null,
          h('div', { className:'label' }, 'اسم الصنف *'),
          h('input', { className:'input', value:form.name, onChange:e=>set('name',e.target.value) }),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null,
            h('div', { className:'label' }, 'الفئة'),
            h('select', { className:'select', value:form.category, onChange:e=>set('category',e.target.value) },
              h('option', { value:'' }, '— اختر —'),
              invCategories.map(c => h('option', { key:c, value:c }, c)),
            ),
          ),
          h('div', null,
            h('div', { className:'label' }, 'وحدة القياس'),
            h('select', { className:'select', value:form.unit, onChange:e=>set('unit',e.target.value) },
              units.map(u => h('option', { key:u, value:u }, u)),
            ),
          ),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr 1fr',gap:12} },
          h('div', null, h('div', { className:'label' }, 'الكمية الحالية'), h('input', { className:'input', type:'number', min:0, value:form.stock, onChange:e=>set('stock',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'الحد الأدنى'), h('input', { className:'input', type:'number', min:0, value:form.minStock, onChange:e=>set('minStock',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'السعر (ج.م)'), h('input', { className:'input', type:'number', min:0, value:form.price, onChange:e=>set('price',e.target.value) })),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null, h('div', { className:'label' }, 'عدد وحدات الاستخدام داخل العبوة'), h('input', { className:'input', type:'number', min:0, value:form.usageUnitsPerPack, onChange:e=>set('usageUnitsPerPack',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'تاريخ الصلاحية (اختياري)'), h('input', { className:'input', type:'date', value:form.expiry, onChange:e=>set('expiry',e.target.value) })),
        ),
      ),
      h('div', { className:'flex gap-8 jc-sb mt-20' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave }, saving ? 'جاري الحفظ...' : 'حفظ التعديل'),
      ),
    ),
  );
}

// ==================== Bulk Edit Inventory Modal ====================
function BulkEditInventoryModal({ count, onClose, onSaved }) {
  const { toast } = useContext(AppContext);
  const [form, setForm] = useState({ category: '', minStock: '', price: '', expiry: '' });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const invCategories = ['مواد حشو', 'مواد تنظيف', 'أدوات', 'مواد أشعة', 'تركيبات', 'مواد تخدير', 'قفازات ومستلزمات', 'أدوية', 'عام'];

  const handleSave = async () => {
    const payload = {};
    if (form.category.trim()) payload.category = form.category.trim();
    if (String(form.minStock).trim() !== '') payload.min_stock = +form.minStock || 0;
    if (String(form.price).trim() !== '') payload.price = +form.price || 0;
    if (form.expiry) payload.expiry = form.expiry;
    if (!Object.keys(payload).length) {
      toast('املأ حقلًا واحدًا على الأقل للتعديل الجماعي');
      return;
    }
    setSaving(true);
    try {
      await onSaved(payload);
      onClose();
    } catch (e) {
      toast('خطأ: ' + (e.message || 'تعذر التعديل الجماعي'));
    } finally {
      setSaving(false);
    }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:460, padding:24 } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:20} },
        h('div', null,
          h('div', { style:{fontWeight:800,fontSize:17} }, 'تعديل المحدد'),
          h('div', { style:{fontSize:12,color:'var(--text-tertiary)',marginTop:4} }, `سيتم تعديل ${count} صنف. الحقول المعبأة فقط هي التي ستتغير.`),
        ),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{display:'grid',gap:12} },
        h('div', null,
          h('div', { className:'label' }, 'الفئة'),
          h('select', { className:'select', value:form.category, onChange:e=>set('category',e.target.value) },
            h('option', { value:'' }, 'اتركها كما هي'),
            invCategories.map(c => h('option', { key:c, value:c }, c)),
          ),
        ),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null, h('div', { className:'label' }, 'الحد الأدنى'), h('input', { className:'input', type:'number', min:0, placeholder:'اتركه كما هو', value:form.minStock, onChange:e=>set('minStock',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'السعر'), h('input', { className:'input', type:'number', min:0, placeholder:'اتركه كما هو', value:form.price, onChange:e=>set('price',e.target.value) })),
        ),
        h('div', null, h('div', { className:'label' }, 'الصلاحية'), h('input', { className:'input', type:'date', value:form.expiry, onChange:e=>set('expiry',e.target.value) })),
      ),
      h('div', { className:'flex gap-8 jc-sb mt-20' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave }, saving ? 'جاري التعديل...' : 'حفظ التعديل الجماعي'),
      ),
    ),
  );
}

// ==================== BOM Modal ====================
function BomModal({ service, onClose }) {
  const { clinicId, inventory, toast } = useContext(AppContext);
  const allInv = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
  const [usageUnitsMap, setUsageUnitsMap] = useState({});
  const [bom, setBom] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selInvId, setSelInvId] = useState('');
  const [qty, setQty] = useState(1);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    setUsageUnitsMap(loadInventoryUsageUnitsMap(clinicId));
  }, [clinicId]);

  useEffect(() => {
    DB.getBomForService(service.id)
      .then(setBom)
      .catch(console.error)
      .finally(() => setLoading(false));
  }, [service.id]);

  const handleAdd = async () => {
    if (!selInvId) { toast('اختر مادة أولاً'); return; }
    setSaving(true);
    try {
      const item = await DB.addBomItem(clinicId, service.id, selInvId, qty);
      setBom(prev => [...prev, item]);
      setSelInvId(''); setQty(1);
      toast('تم الإضافة ✅');
    } catch(e) { toast('خطأ: ' + (e.message || 'غير متوقع')); }
    finally { setSaving(false); }
  };

  const handleDelete = async (id) => {
    if (!confirm('حذف هذا المكوّن؟')) return;
    try {
      await DB.deleteBomItem(id);
      setBom(prev => prev.filter(b => b.id !== id));
      toast('تم الحذف');
    } catch(e) { toast('خطأ في الحذف'); }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:500, padding:24, maxHeight:'80vh', display:'flex', flexDirection:'column' } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16} },
        h('div', null,
          h('div', { style:{fontWeight:800,fontSize:16} }, 'مكونات الخدمة (BOM)'),
          h('div', { style:{fontSize:13,color:'var(--text-tertiary)',marginTop:2} }, service.name + ' · ' + window.fmtEGP(service.price)),
        ),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{display:'grid',gridTemplateColumns:'1fr 80px auto',gap:8,marginBottom:16,alignItems:'end'} },
        h('div', null,
          h('div', { className:'label' }, 'المادة من المخزون'),
          h('select', { className:'select', value:selInvId, onChange:e=>setSelInvId(e.target.value) },
            h('option', { value:'' }, '— اختر مادة —'),
            allInv.map(i => h('option', { key:i.id, value:i.id }, `${i.name} (${window.fmtNum(i.stock)} ${i.unit})`)),
          ),
        ),
        h('div', null,
          h('div', { className:'label' }, 'الكمية'),
          h('input', { className:'input', type:'number', min:0.1, step:0.1, value:qty, onChange:e=>setQty(+e.target.value) }),
        ),
        h('button', { className:'btn primary', disabled:saving||!selInvId, onClick:handleAdd, style:{marginTop:'auto'} },
          saving ? '...' : h(Icons.Plus, {size:16}),
        ),
      ),
      h('div', { style:{flex:1,overflowY:'auto'} },
        loading ? h('div', { style:{textAlign:'center',padding:24,color:'var(--text-tertiary)'} }, 'جاري التحميل...') :
        bom.length === 0 ? h('div', { style:{textAlign:'center',padding:32,color:'var(--text-tertiary)',border:'2px dashed var(--border)',borderRadius:'var(--radius)'} },
          h('div', null, '📦'),
          h('div', { style:{marginTop:8} }, 'لا توجد مكونات — أضف أول مادة من المخزون'),
        ) :
        h('div', { style:{display:'flex',flexDirection:'column',gap:6} },
          bom.map(b => {
            const invItem = allInv.find(i => i.id === b.inventoryId);
            const unitPrice = invItem ? getInventoryMeasureUnitPrice(invItem, usageUnitsMap) : 0;
            const itemCost = unitPrice * (Number(b.standardQty) || 0);
            return h('div', { key:b.id, style:{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'10px 14px',border:'1px solid var(--border)',borderRadius:'var(--radius)'} },
              h('div', null,
                h('div', { style:{fontWeight:700,fontSize:13} }, b.itemName),
                h('div', { style:{fontSize:11,color:'var(--text-tertiary)',marginTop:2} }, `الكمية المعيارية: ${b.standardQty} ${b.unit}`),
                h('div', { style:{fontSize:11,color:'var(--text-tertiary)',marginTop:2} }, `سعر وحدة القياس: ${window.fmtEGP(unitPrice)} · التكلفة: ${window.fmtEGP(itemCost)}`),
              ),
              h('button', { className:'icon-btn', style:{color:'var(--danger)'}, onClick:()=>handleDelete(b.id) },
                h(Icons.Trash, {size:13}),
              ),
            );
          }),
        ),
      ),
    ),
  );
}

// ==================== Edit Service Modal ====================
function EditServiceModal({ service, onClose, onSaved }) {
  const { toast } = useContext(AppContext);
  const [form, setForm] = useState({ name: service.name, price: service.price, duration: service.duration, category: service.category });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    setSaving(true);
    try {
      const { data, error } = await SB.from('services')
        .update({ name: form.name, price: +form.price, duration: +form.duration, category: form.category })
        .eq('id', service.id).select().single();
      if (error) throw error;
      toast('تم حفظ الخدمة ✅');
      onSaved({ ...service, ...form, price: +form.price, duration: +form.duration });
      onClose();
    } catch(e) { toast('خطأ: ' + (e.message || 'غير متوقع')); }
    finally { setSaving(false); }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:420, padding:24 } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:20} },
        h('div', { style:{fontWeight:800,fontSize:16} }, 'تعديل الخدمة'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{display:'grid',gap:12} },
        h('div', null, h('div', { className:'label' }, 'اسم الخدمة'),
          h('input', { className:'input', value:form.name, onChange:e=>set('name',e.target.value) })),
        h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12} },
          h('div', null, h('div', { className:'label' }, 'السعر (ج.م)'),
            h('input', { className:'input', type:'number', value:form.price, onChange:e=>set('price',e.target.value) })),
          h('div', null, h('div', { className:'label' }, 'المدة (دقيقة)'),
            h('input', { className:'input', type:'number', value:form.duration, onChange:e=>set('duration',e.target.value) })),
        ),
        h('div', null, h('div', { className:'label' }, 'الفئة'),
          h('input', { className:'input', value:form.category, onChange:e=>set('category',e.target.value) })),
      ),
      h('div', { className:'flex gap-8 jc-sb mt-20' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave },
          saving ? 'جاري الحفظ...' : 'حفظ التغييرات'),
      ),
    ),
  );
}

// ═══════════════════════════════════════════════════════
// بيانات المخزون ومكونات الخدمات من Alpha Clinic System
// ═══════════════════════════════════════════════════════
const _INV=[{name:"الفيو جيل",price:10.0,stock:10,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"باند - سادل",price:20.0,stock:20,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"باند - سيكشنال",price:35.0,stock:35,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير -فيشر",price:12.0,stock:12,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"جلاس ايونمر فيلنج - ٢٠ حالة",price:5.0,stock:5,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"صوديوم هيبو كلورايد",price:1.0,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ميتا بيست - ١٧ حالة",price:37.0,stock:37,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ميتا بيكس - ١٠ حالات",price:55.0,stock:55,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"MTA - 0.125 g",price:32.5,stock:32,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ألجينيت -18 حالة",price:27.0,stock:27,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"أمالجم",price:40.0,stock:40,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"اتش - etch - ٢٠ حالة",price:5.0,stock:5,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"اكياس تعقيم",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"اوفر جلافز",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ايدتا جيل - EDTA - ٣٠ حالة",price:3.0,stock:3,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"باند معدن",price:1.5,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بنج موضعى - 100 حالة",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بوست معدن",price:9.0,stock:9,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بوند - One Coat - 100 حالة",price:25.0,stock:25,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بوند cotelene - 100 حالة",price:7.0,stock:7,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بيبر بوينت",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير - TF",price:12.0,stock:12,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير - اندوزى -Endo z",price:40.0,stock:40,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير - جراحى",price:100.0,stock:100,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير - راوند",price:12.0,stock:12,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير - فليم -flame",price:12.0,stock:12,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بير - فوتبول",price:12.0,stock:12,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"بيزو ريمير - Peeso Reamer",price:55.0,stock:55,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"تبات شارم كور",price:15.0,stock:15,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"تبات للهواء والمياة - Air Tip",price:1.0,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"تراى",price:15.0,stock:12,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"تيفلون - ٤٠ حالة",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ثيراكال - ٥٠ حالة",price:20.0,stock:20,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"جاتابيركا تيبر ٤",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"جاتبيركا تيبر 6",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"جاتيبركا تيبر 2",price:1.0,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"جوانتى جلافز",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"حافظ مكان للاطفال - معمل",price:250.0,stock:250,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"حشو مؤقت - 100 حالة",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"خيط جراحى",price:17.0,stock:17,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"خيط فلوص - floss - ١٠٠ مريض",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ديسك فينشنج وبولشينج",price:13.0,stock:13,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"رابر بيس - مقاس - باتى - 30 حالة",price:35.0,stock:35,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"رابر بيس - مقاس - لايت ١٥ حالة",price:35.0,stock:35,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"رابر دام",price:9.0,stock:9,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ريتراكشن كورد - ٤٠ حالة",price:2.5,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"زنك اوكسايد - ٣٥ حالة",price:15.0,stock:15,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ساكشن شفاط",price:1.5,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"سالاين -saline ٢٥ حالة",price:1.0,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"سبريدر - spreader",price:25.0,stock:25,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ستريب - بوليشنج",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ستناليس كراون",price:70.0,stock:70,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ستون - فينشنج وبولشينج",price:25.0,stock:25,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"سرنجات بلاستيك",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"سن بنج",price:2.0,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"سنون ايريجشن",price:6.5,stock:6,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"سيلر - 50 حالة",price:25.0,stock:25,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"شارم كور كمبوزيت - 10 حالات",price:75.0,stock:76,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"شاش - ١٠٠ حالة",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايبر بوست",price:5.0,stock:5,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل روتارى - أوبنر",price:75.0,stock:75,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل روتارى مقاس ١٥",price:75.0,stock:75,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل روتارى مقاس ٢٠",price:75.0,stock:75,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل روتارى مقاس ٢٥",price:75.0,stock:75,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل روتارى مقاس ٣٠",price:75.0,stock:75,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل مانوال مقاس ٢٠",price:40.0,stock:40,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل مانوال مقاس ١٠",price:40.0,stock:40,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل مانوال مقاس ١٥",price:40.0,stock:40,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فايل مانوال مقاس ٨",price:40.0,stock:40,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فرش تلميع وبوليشنغ",price:5.5,stock:5,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فرشة بوند",price:1.0,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"فورماكريزول - ٤٠٠ حالة",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"قطن - ١٠٠ حالة",price:1.0,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"قطن رول",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كبموزيت - Capo - 20 حالة",price:35.0,stock:35,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كبموزيت - Ruby - 10 حالات",price:16.0,stock:16,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كراون - معمل",price:350.0,stock:350,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كربولة بنج",price:20.0,stock:20,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كلوروهيكسدين جيل - ١٥ حالةً",price:6.5,stock:6,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كمبوزيت Ruby - 20 حالات",price:16.0,stock:16,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كمبوزيت Z-Fill - ١٥ حالة",price:50.0,stock:50,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كمبوزيت فلوبال - flowable - ٢٠ حالة",price:15.0,stock:15,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"كوبايات",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"لزق - سيمنت - ٤٠ حالة",price:2.5,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ماسك للوجه",price:1.5,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"مشرط",price:10.0,stock:10,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"مضاد حساسية - desensitizer - ١٠ حالات",price:5.0,stock:5,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"معجون تلميع وبوليشنغ - ٤٠ حالة",price:2.5,stock:2,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"مفرش ألوان",price:1.0,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"مفرش شفاف",price:0.5,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"مناديل",price:1.0,stock:0,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"هيمو ستوب - hemostop - ٣٠ حالة",price:3.0,stock:3,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"واكس - شمع 50 حالة",price:4.0,stock:4,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ورق كربون",price:1.5,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5},{name:"ويدج",price:1.5,stock:1,unit:"قطعة",category:'مستلزمات طبية',minStock:5}];
const _BOM={"كشف":[["جوانتى جلافز",2],["مفرش شفاف",1],["ماسك للوجه",1],["كوبايات",1],["تبات للهواء والمياة - Air Tip",1],["اكياس تعقيم",2],["اوفر جلافز",3],["خيط فلوص - floss - ١٠٠ مريض",1],["قطن - ١٠٠ حالة",1]],"خلع عادي":[["الفيو جيل",1],["اكياس تعقيم",4],["اوفر جلافز",3],["بنج موضعى - 100 حالة",1],["تبات للهواء والمياة - Air Tip",1],["جوانتى جلافز",2],["سرنجات بلاستيك",1],["سن بنج",1],["قطن - ١٠٠ حالة",2],["قطن رول",2],["كربولة بنج",2],["مفرش ألوان",1],["ماسك للوجه",1],["كوبايات",2],["مفرش شفاف",1],["مناديل",2]],"خلع عادي اطفال":[["اكياس تعقيم",4],["اوفر جلافز",3],["بنج موضعى - 100 حالة",1],["تبات للهواء والمياة - Air Tip",1],["جوانتى جلافز",2],["سرنجات بلاستيك",1],["سن بنج",1],["قطن - ١٠٠ حالة",2],["قطن رول",2],["كربولة بنج",1],["مفرش ألوان",1],["ماسك للوجه",1],["كوبايات",1],["مفرش شفاف",1],["مناديل",2]],"خلع جراحى سيباريشن":[["مفرش ألوان",1],["مفرش شفاف",1],["جوانتى جلافز",2],["اوفر جلافز",2],["ماسك للوجه",1],["كوبايات",1],["تبات للهواء والمياة - Air Tip",1],["سن بنج",1],["كربولة بنج",2],["بنج موضعى - 100 حالة",1],["اكياس تعقيم",4],["قطن - ١٠٠ حالة",2],["الفيو جيل",1],["سرنجات بلاستيك",1],["بير - جراحى",1]],"خلع جراحى امباكشن":[["مفرش شفاف",1],["مفرش ألوان",1],["الفيو جيل",1],["اكياس تعقيم",4],["اوفر جلافز",3],["تبات للهواء والمياة - Air Tip",1],["بير - جراحى",1],["بنج موضعى - 100 حالة",1],["جوانتى جلافز",2],["خيط جراحى",1],["سرنجات بلاستيك",1],["قطن - ١٠٠ حالة",2],["شاش - ١٠٠ حالة",1],["سن بنج",1],["كربولة بنج",2],["كوبايات",2],["ماسك للوجه",1],["مناديل",2],["مشرط",1]],"حشو كمبوزيت أمامي":[["مفرش شفاف",2],["مفرش ألوان",1],["جوانتى جلافز",4],["اوفر جلافز",5],["ماسك للوجه",1],["ساكشن شفاط",3],["كوبايات",2],["تبات للهواء والمياة - Air Tip",2],["سن بنج",2],["كربولة بنج",2],["بنج موضعى - 100 حالة",2],["كمبوزيت Z-Fill - ١٥ حالة",1],["بوند - One Coat - 100 حالة",1],["فرشة بوند",2],["اتش - etch - ٢٠ حالة",1],["كمبوزيت فلوبال - flowable - ٢٠ حالة",1],["ديسك فينشنج وبولشينج",1],["حشو مؤقت - 100 حالة",1],["اكياس تعقيم",6],["ورق كربون",1],["بير - TF",1],["قطن - ١٠٠ حالة",2],["قطن رول",2],["رابر دام",1],["ويدج",1],["مناديل",2],["تيفلون - ٤٠ حالة",1],["خيط فلوص - floss - ١٠٠ مريض",1]],"حشو كومبوزيت خلفى":[["مفرش ألوان",1],["مفرش شفاف",2],["جوانتى جلافز",4],["ماسك للوجه",1],["ساكشن شفاط",2],["كوبايات",2],["تبات للهواء والمياة - Air Tip",2],["سن بنج",2],["بنج موضعى - 100 حالة",2],["كربولة بنج",2],["كمبوزيت فلوبال - flowable - ٢٠ حالة",1],["كبموزيت - Capo - 20 حالة",1],["بوند - One Coat - 100 حالة",1],["اتش - etch - ٢٠ حالة",1],["باند - سادل",1],["ستون - فينشنج وبولشينج",1],["حشو مؤقت - 100 حالة",1],["اكياس تعقيم",6],["فرشة بوند",2],["ورق كربون",1],["اوفر جلافز",5],["رابر دام",1],["ويدج",1],["مناديل",1],["قطن - ١٠٠ حالة",2],["قطن رول",2],["تيفلون - ٤٠ حالة",1],["بير - TF",1],["ثيراكال - ٥٠ حالة",1]],"حشو عادى اطفال":[["أمالجم",1],["اكياس تعقيم",3],["اوفر جلافز",3],["باند معدن",1],["بنج موضعى - 100 حالة",1],["بير - راوند",1],["تبات للهواء والمياة - Air Tip",2],["جوانتى جلافز",2],["سن بنج",1],["ساكشن شفاط",2],["كوبايات",1],["كربولة بنج",1],["قطن رول",1],["قطن - ١٠٠ حالة",1],["ماسك للوجه",1],["مفرش ألوان",1],["مفرش شفاف",1],["مناديل",1],["ويدج",1]],"حشو عصب جزئى اطفال":[["مفرش ألوان",1],["مفرش شفاف",2],["مناديل",2],["ويدج",1],["ماسك للوجه",1],["كوبايات",2],["كربولة بنج",1],["قطن رول",2],["قطن - ١٠٠ حالة",2],["فورماكريزول - ٤٠٠ حالة",1],["سن بنج",1],["ساكشن شفاط",3],["جوانتى جلافز",4],["حشو مؤقت - 100 حالة",1],["زنك اوكسايد - ٣٥ حالة",1],["تبات للهواء والمياة - Air Tip",2],["بير - TF",1],["بنج موضعى - 100 حالة",1],["باند معدن",1],["اوفر جلافز",5],["اكياس تعقيم",6],["أمالجم",1]],"حشو عصب كلى اطفال":[["مفرش شفاف",2],["مفرش ألوان",1],["جوانتى جلافز",4],["اوفر جلافز",5],["ماسك للوجه",1],["ساكشن شفاط",3],["كوبايات",3],["تبات للهواء والمياة - Air Tip",2],["باند معدن",1],["بنج موضعى - 100 حالة",2],["كربولة بنج",2],["سن بنج",2],["اكياس تعقيم",6],["حشو مؤقت - 100 حالة",1],["بير - راوند",1],["قطن - ١٠٠ حالة",2],["قطن رول",2],["أمالجم",1],["ويدج",1],["مناديل",2],["فورماكريزول - ٤٠٠ حالة",1],["ميتا بيست - ١٧ حالة",1],["فايل مانوال مقاس ١٠",1],["فايل روتارى مقاس ١٥",1],["سرنجات بلاستيك",1]],"حشو عصب كبار":[["مفرش ألوان",1],["مفرش شفاف",3],["جوانتى جلافز",6],["ماسك للوجه",1],["ساكشن شفاط",4],["كوبايات",4],["تبات للهواء والمياة - Air Tip",3],["سن بنج",3],["كربولة بنج",3],["بنج موضعى - 100 حالة",3],["بوند cotelene - 100 حالة",1],["كمبوزيت فلوبال - flowable - ٢٠ حالة",1],["اتش - etch - ٢٠ حالة",1],["باند - سادل",1],["فايل مانوال مقاس ١٥",1],["فايل روتارى مقاس ٢٥",1],["جاتيبركا تيبر 2",8],["جاتابيركا تيبر ٤",4],["بيبر بوينت",12]]};

// ==================== Variance Analysis Tab ====================
function VarianceAnalysisTab() {
  const { clinicId, inventory, setInventory, invoices, doctors, toast } = useContext(AppContext);

  const currentMonthStr = () => {
    const d = new Date();
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
  };

  const [selectedMonth, setSelectedMonth] = useState(currentMonthStr);
  const [section, setSection] = useState('actual');

  // BOM cache
  const [allBom, setAllBom] = useState([]);
  const [bomLoaded, setBomLoaded] = useState(false);
  const [bomError, setBomError] = useState(null);

  // Section 1: actual consumption
  const [selDoctor, setSelDoctor] = useState('');
  const [actualInputs, setActualInputs] = useState({});
  const [loadedActual, setLoadedActual] = useState([]);
  const [savingActual, setSavingActual] = useState(false);
  const [tablesReady, setTablesReady] = useState(true);

  // Section 2: physical count
  const [physInputs, setPhysInputs] = useState({});
  const [loadedPhys, setLoadedPhys] = useState([]);
  const [savingPhys, setSavingPhys] = useState(false);
  const [applyAsOpeningBalance, setApplyAsOpeningBalance] = useState(true);

  // Report
  const [rptDoctor, setRptDoctor] = useState('');

  const allDoctors = Array.isArray(doctors) ? doctors : [];
  const allInv = Array.isArray(inventory) ? inventory : [];
  const allInvoices = Array.isArray(invoices) ? invoices : [];

  // Load BOM once
  useEffect(() => {
    if (!clinicId) return;
    DB.getAllBom(clinicId)
      .then(bom => { setAllBom(bom); setBomLoaded(true); })
      .catch(e => { setBomError(e.message); setBomLoaded(true); });
  }, [clinicId]);

  // Load actual + physical when month changes
  const loadMonthData = useCallback(async () => {
    if (!clinicId) return;
    const [actual, phys] = await Promise.all([
      DB.getActualConsumption(clinicId, selectedMonth),
      DB.getPhysicalCounts(clinicId, selectedMonth),
    ]);
    // Detect if tables exist (returns [] on error AND on empty)
    setLoadedActual(actual);
    setLoadedPhys(phys);
  }, [clinicId, selectedMonth]);

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

  // Pre-fill actual inputs when doctor selection changes
  useEffect(() => {
    const doctorRecords = loadedActual.filter(r =>
      selDoctor ? r.doctor_id === selDoctor : !r.doctor_id
    );
    const inputs = {};
    doctorRecords.forEach(r => { inputs[r.inventory_id] = String(r.actual_qty || ''); });
    setActualInputs(inputs);
  }, [selDoctor, loadedActual]);

  // Pre-fill physical count inputs
  useEffect(() => {
    const inputs = {};
    loadedPhys.forEach(r => { inputs[r.inventory_id] = String(r.counted_qty || ''); });
    setPhysInputs(inputs);
  }, [loadedPhys]);

  // Theoretical consumption from invoices × BOM
  const theoreticalMap = useMemo(() => {
    if (!bomLoaded || !allBom.length) return {};
    const monthInvoices = allInvoices.filter(inv =>
      (inv.date || '').startsWith(selectedMonth)
    );
    const result = {};
    for (const inv of monthInvoices) {
      for (const item of (inv.items || [])) {
        const qty = Number(item.qty) || 1;
        const bomEntries = allBom.filter(b => b.serviceName === item.name);
        for (const bom of bomEntries) {
          result[bom.inventoryId] = (result[bom.inventoryId] || 0) + bom.standardQty * qty;
        }
      }
    }
    return result;
  }, [allInvoices, allBom, bomLoaded, selectedMonth]);

  // Save actual consumption
  const handleSaveActual = async () => {
    setSavingActual(true);
    try {
      const entries = Object.entries(actualInputs).filter(([, v]) => v !== '' && !Number.isNaN(Number(v)));
      if (!entries.length) { toast('لا توجد بيانات للحفظ'); setSavingActual(false); return; }
      await Promise.all(entries.map(([invId, qty]) =>
        DB.saveActualConsumption(clinicId, selectedMonth, selDoctor || null, invId, Number(qty))
      ));
      await loadMonthData();
      toast('✅ تم حفظ الاستهلاك الفعلي');
    } catch (e) {
      if (String(e.message).includes('relation') || String(e.message).includes('table')) {
        setTablesReady(false);
        toast('❌ الجداول غير موجودة — شغّل SQL أدناه في Supabase أولاً');
      } else {
        toast('❌ ' + (e.message || 'خطأ في الحفظ'));
      }
    } finally {
      setSavingActual(false);
    }
  };

  // Save physical count + optionally set as opening balance
  const handleSavePhys = async () => {
    setSavingPhys(true);
    try {
      const entries = Object.entries(physInputs).filter(([, v]) => v !== '' && !Number.isNaN(Number(v)));
      if (!entries.length) { toast('لا توجد بيانات للحفظ'); setSavingPhys(false); return; }

      // 1. حفظ الجرد في الجدول الشهري
      await Promise.all(entries.map(([invId, qty]) =>
        DB.savePhysicalCount(clinicId, selectedMonth, invId, Number(qty))
      ));

      // 2. تحديث المخزون كرصيد افتتاحي إذا كان الخيار مفعّلاً
      if (applyAsOpeningBalance) {
        const updatedItems = [];
        await Promise.all(entries.map(async ([invId, qty]) => {
          const invItem = allInv.find(x => x.id === invId);
          if (!invItem) return;
          const uup = Number(invItem.usageUnitsPerPack) || 0;
          // وحدات استهلاك → عبوات
          const newStock = uup > 0
            ? Math.round((Number(qty) / uup) * 10000) / 10000
            : Number(qty);
          try {
            const updated = await DB.updateInventoryItem(invId, { stock: newStock });
            if (updated) updatedItems.push(updated);
          } catch(err) {
            console.error('[handleSavePhys] updateInventoryItem failed for', invId, err);
          }
        }));
        // تحديث UI فوراً
        if (setInventory && updatedItems.length > 0) {
          setInventory(prev => (prev || []).map(item => {
            const upd = updatedItems.find(u => u.id === item.id);
            return upd ? { ...item, stock: upd.stock } : item;
          }));
        }
      }

      await loadMonthData();
      toast(applyAsOpeningBalance
        ? `✅ تم حفظ الجرد وتحديث المخزون كرصيد افتتاحي (${entries.length} مادة)`
        : '✅ تم حفظ الجرد الفعلي'
      );
    } catch (e) {
      if (String(e.message).includes('relation') || String(e.message).includes('table')) {
        setTablesReady(false);
        toast('❌ الجداول غير موجودة — شغّل SQL أدناه في Supabase أولاً');
      } else {
        toast('❌ ' + (e.message || 'خطأ في الحفظ'));
      }
    } finally {
      setSavingPhys(false);
    }
  };

  // Report rows
  const reportRows = useMemo(() => {
    return allInv.map(item => {
      const theoretical = Math.round((theoreticalMap[item.id] || 0) * 10) / 10;
      const actualEntries = loadedActual.filter(r =>
        r.inventory_id === item.id && (!rptDoctor || r.doctor_id === rptDoctor)
      );
      const actual = actualEntries.reduce((s, r) => s + (Number(r.actual_qty) || 0), 0);
      const physEntry = loadedPhys.find(r => r.inventory_id === item.id);
      const physical = physEntry ? Number(physEntry.counted_qty) : null;
      const systemUnits = item.usageUnitsPerPack > 0
        ? Math.round(item.stock * item.usageUnitsPerPack * 10) / 10
        : null;
      const var1 = Math.round((actual - theoretical) * 10) / 10;
      const var2 = physical !== null && systemUnits !== null
        ? Math.round((physical - systemUnits) * 10) / 10
        : null;
      return { item, theoretical, actual, physical, systemUnits, var1, var2, hasData: theoretical > 0 || actual > 0 || physical !== null };
    }).filter(r => r.hasData);
  }, [allInv, theoreticalMap, loadedActual, loadedPhys, rptDoctor]);

  const varChip = (val, showZero = false) => {
    if (val === null) return h('span', { style: { color: 'var(--text-tertiary)', fontSize: 11 } }, '—');
    if (!showZero && val === 0) return h('span', { className: 'chip success', style: { fontSize: 11 } }, '✓ 0');
    const positive = val > 0;
    return h('span', {
      className: 'chip ' + (positive ? 'warning' : 'success'),
      style: { fontSize: 11, fontVariantNumeric: 'tabular-nums' },
    }, (positive ? '+' : '') + window.fmtNum(val));
  };

  const SQL_SETUP = `-- شغّل هذا في Supabase SQL Editor (Dashboard > SQL Editor > New Query)
CREATE TABLE IF NOT EXISTS monthly_actual_consumption (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  clinic_id UUID NOT NULL,
  month VARCHAR(7) NOT NULL,
  doctor_id UUID,
  inventory_id UUID NOT NULL,
  actual_qty NUMERIC(10,3) NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(clinic_id, month, doctor_id, inventory_id)
);
CREATE TABLE IF NOT EXISTS monthly_physical_count (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  clinic_id UUID NOT NULL,
  month VARCHAR(7) NOT NULL,
  inventory_id UUID NOT NULL,
  counted_qty NUMERIC(10,3) NOT NULL DEFAULT 0,
  notes TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(clinic_id, month, inventory_id)
);
ALTER TABLE monthly_actual_consumption ENABLE ROW LEVEL SECURITY;
ALTER TABLE monthly_physical_count ENABLE ROW LEVEL SECURITY;
CREATE POLICY "service_role_all_actual" ON monthly_actual_consumption USING (true) WITH CHECK (true);
CREATE POLICY "service_role_all_physical" ON monthly_physical_count USING (true) WITH CHECK (true);`;

  const [showSql, setShowSql] = useState(false);

  const sectionBtns = [
    ['actual', '📝 الاستهلاك الفعلي'],
    ['physical', '🔢 الجرد الفعلي'],
    ['report', '📊 تقرير التباين'],
  ];

  return h('div', { className: 'fade-in' },

    // Month selector + section toggle
    h('div', { className: 'card p-16 mb-12 flex gap-12 ai-c flex-wrap' },
      h('div', null,
        h('div', { className: 'label mb-4' }, 'الشهر'),
        h('input', {
          type: 'month',
          className: 'input',
          style: { width: 160 },
          value: selectedMonth,
          onChange: e => setSelectedMonth(e.target.value),
        }),
      ),
      h('div', { style: { flex: 1 } }),
      h('div', { className: 'tabs' },
        sectionBtns.map(([v, l]) =>
          h('button', { key: v, className: 'tab' + (section === v ? ' active' : ''), onClick: () => setSection(v) }, l)
        ),
      ),
    ),

    // SQL setup notice
    !tablesReady && h('div', { className: 'card p-16 mb-12', style: { background: 'var(--warning-soft)', border: '1px solid var(--warning)', borderRadius: 12 } },
      h('div', { style: { fontWeight: 700, marginBottom: 6 } }, '⚠️ جداول الجرد غير موجودة بعد'),
      h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', marginBottom: 10 } },
        'اضغط "عرض SQL" ثم شغّله مرة واحدة في Supabase SQL Editor لإنشاء الجداول.'
      ),
      h('button', { className: 'btn outline sm', onClick: () => setShowSql(!showSql) }, showSql ? 'إخفاء SQL' : 'عرض SQL'),
      showSql && h('pre', {
        style: {
          marginTop: 10, padding: 12, background: '#1e293b', color: '#e2e8f0',
          borderRadius: 8, fontSize: 11, overflowX: 'auto', whiteSpace: 'pre-wrap', direction: 'ltr',
        },
      }, SQL_SETUP),
    ),

    /* ═══ SECTION 1: Actual Consumption ═══ */
    section === 'actual' && h('div', null,
      h('div', { className: 'card p-16 mb-12 flex gap-12 ai-c' },
        h('div', null,
          h('div', { className: 'label mb-4' }, 'الطبيب'),
          h('select', {
            className: 'input',
            style: { minWidth: 200 },
            value: selDoctor,
            onChange: e => setSelDoctor(e.target.value),
          },
            h('option', { value: '' }, '— كل الأطباء / مشترك —'),
            allDoctors.map(d => h('option', { key: d.id, value: d.id }, d.name)),
          ),
        ),
        h('div', { style: { flex: 1, fontSize: 12, color: 'var(--text-secondary)' } },
          'أدخل إجمالي الاستهلاك الفعلي لهذا الطبيب خلال شهر ',
          h('strong', null, selectedMonth),
          ' (بالوحدات — حالة/قطعة)',
        ),
        h('button', {
          className: 'btn primary',
          disabled: savingActual,
          onClick: handleSaveActual,
        }, savingActual ? '⏳ جاري الحفظ...' : '💾 حفظ الاستهلاك'),
      ),
      h('div', { className: 'card', style: { overflowX: 'auto' } },
        h('table', { className: 'data-table', style: { minWidth: 600, direction: 'rtl' } },
          h('thead', null, h('tr', null,
            h('th', null, 'المادة'),
            h('th', null, 'الفئة'),
            h('th', null, 'الوحدة'),
            h('th', { style: { minWidth: 140 } }, 'الكمية المستهلكة (وحدات)'),
            h('th', null, 'نظري (BOM)'),
          )),
          h('tbody', null,
            allInv.filter(it => it.usageUnitsPerPack > 0 || theoreticalMap[it.id] > 0 || actualInputs[it.id]).map(item =>
              h('tr', { key: item.id },
                h('td', { style: { fontWeight: 600 } }, item.name),
                h('td', null, h('span', { className: 'chip' }, item.category)),
                h('td', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, item.unit),
                h('td', null,
                  h('input', {
                    type: 'number',
                    className: 'input',
                    style: { width: 120, textAlign: 'center' },
                    placeholder: '0',
                    min: 0,
                    step: 0.5,
                    value: actualInputs[item.id] || '',
                    onChange: e => setActualInputs(prev => ({ ...prev, [item.id]: e.target.value })),
                  }),
                ),
                h('td', { style: { color: 'var(--text-tertiary)', fontSize: 12 } },
                  theoreticalMap[item.id] > 0 ? window.fmtNum(theoreticalMap[item.id]) : '—'
                ),
              )
            ),
            allInv.filter(it => it.usageUnitsPerPack > 0 || theoreticalMap[it.id] > 0 || actualInputs[it.id]).length === 0 &&
              h('tr', null, h('td', { colSpan: 5, style: { textAlign: 'center', padding: 32, color: 'var(--text-tertiary)' } },
                'لا توجد مواد لها وحدات قياس أو BOM — أضف usage_units_per_pack من تبويت المخزون'
              )),
          ),
        ),
      ),
    ),

    /* ═══ SECTION 2: Physical Count ═══ */
    section === 'physical' && h('div', null,
      h('div', { className: 'card p-16 mb-12', style: { display: 'flex', flexDirection: 'column', gap: 12 } },
        // Row 1: description
        h('div', { style: { fontSize: 12, color: 'var(--text-secondary)' } },
          'أدخل الكمية الموجودة فعلياً في الدرج/المخزن لشهر ',
          h('strong', null, selectedMonth),
          ' (بالوحدات — حالة/قطعة)',
        ),
        // Row 2: opening balance toggle + save button
        h('div', { style: { display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' } },
          // Checkbox: apply as opening balance
          h('label', {
            style: {
              display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer',
              padding: '8px 14px', borderRadius: 8,
              background: applyAsOpeningBalance ? 'var(--accent-soft)' : 'var(--bg-subtle)',
              border: `1px solid ${applyAsOpeningBalance ? 'var(--accent)' : 'var(--border)'}`,
              transition: 'all .15s',
            },
          },
            h('input', {
              type: 'checkbox',
              checked: applyAsOpeningBalance,
              onChange: e => setApplyAsOpeningBalance(e.target.checked),
              style: { accentColor: 'var(--accent)', width: 15, height: 15, cursor: 'pointer' },
            }),
            h('div', null,
              h('div', { style: { fontSize: 13, fontWeight: 700, color: applyAsOpeningBalance ? 'var(--accent)' : 'var(--text-primary)' } },
                '📦 تحديث المخزون كرصيد افتتاحي',
              ),
              h('div', { style: { fontSize: 11, color: 'var(--text-secondary)', marginTop: 2 } },
                applyAsOpeningBalance
                  ? 'سيتم تحديث stock في المخزون بقيم الجرد المدخلة مباشرةً'
                  : 'الجرد سيُحفظ للتقرير فقط — المخزون لن يتغير',
              ),
            ),
          ),
          h('div', { style: { flex: 1 } }),
          h('button', {
            className: 'btn primary',
            disabled: savingPhys,
            onClick: handleSavePhys,
          }, savingPhys ? '⏳ جاري الحفظ...' : (applyAsOpeningBalance ? '💾 حفظ الجرد + تحديث المخزون' : '💾 حفظ الجرد')),
        ),
        // Info box when opening balance is enabled
        applyAsOpeningBalance && h('div', {
          style: {
            fontSize: 11, padding: '8px 12px', borderRadius: 8,
            background: 'rgba(59,130,246,.08)', borderRight: '3px solid var(--accent)',
            color: 'var(--text-secondary)', lineHeight: 1.7,
          },
        },
          '💡 المعادلة: وحدات الجرد ÷ usage_units_per_pack = عبوات جديدة في المخزون. ',
          'مثال: جرد 50 حالة ÷ 25 حالة/علبة = 2 علبة رصيد.',
        ),
      ),
      h('div', { className: 'card', style: { overflowX: 'auto' } },
        h('table', { className: 'data-table', style: { minWidth: 600, direction: 'rtl' } },
          h('thead', null, h('tr', null,
            h('th', null, 'المادة'),
            h('th', null, 'الفئة'),
            h('th', null, 'مخزون النظام (وحدات)'),
            h('th', { style: { minWidth: 140 } }, 'الجرد الفعلي (وحدات)'),
          )),
          h('tbody', null,
            allInv.map(item => {
              const systemUnits = item.usageUnitsPerPack > 0
                ? Math.round(item.stock * item.usageUnitsPerPack * 10) / 10
                : null;
              return h('tr', { key: item.id },
                h('td', { style: { fontWeight: 600 } }, item.name),
                h('td', null, h('span', { className: 'chip' }, item.category)),
                h('td', { style: { fontWeight: 600, color: 'var(--text-secondary)' } },
                  systemUnits !== null ? window.fmtNum(systemUnits) : window.fmtNum(item.stock) + ' ' + item.unit
                ),
                h('td', null,
                  h('input', {
                    type: 'number',
                    className: 'input',
                    style: { width: 120, textAlign: 'center' },
                    placeholder: '0',
                    min: 0,
                    step: 0.5,
                    value: physInputs[item.id] || '',
                    onChange: e => setPhysInputs(prev => ({ ...prev, [item.id]: e.target.value })),
                  }),
                ),
              );
            }),
          ),
        ),
      ),
    ),

    /* ═══ SECTION 3: Variance Report ═══ */
    section === 'report' && h('div', null,
      h('div', { className: 'card p-12 mb-12 flex gap-12 ai-c' },
        h('span', { style: { fontSize: 12, color: 'var(--text-secondary)' } }, 'فلتر الطبيب:'),
        h('select', {
          className: 'input',
          style: { width: 200 },
          value: rptDoctor,
          onChange: e => setRptDoctor(e.target.value),
        },
          h('option', { value: '' }, '— الكل —'),
          allDoctors.map(d => h('option', { key: d.id, value: d.id }, d.name)),
        ),
        h('div', { style: { flex: 1 } }),
        !bomLoaded && h('span', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, '⏳ تحميل BOM...'),
        bomError && h('span', { style: { fontSize: 12, color: 'var(--warning)' } }, '⚠️ تعذر تحميل BOM — النظري سيظهر 0'),
        h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } },
          h('span', { className: 'chip' }, 'فرق₁ = فعلي − نظري'),
          ' ',
          h('span', { className: 'chip' }, 'فرق₂ = جرد − مخزون النظام'),
        ),
      ),
      reportRows.length === 0
        ? h('div', { className: 'card p-32', style: { textAlign: 'center', color: 'var(--text-tertiary)' } },
          bomLoaded && !allBom.length
            ? 'لا يوجد BOM مضاف — أضف مكونات الخدمات من تبويت "مكونات الخدمات"'
            : 'لا توجد بيانات لهذا الشهر — أضف استهلاك فعلي أو جرد أولاً'
        )
        : h('div', { className: 'card', style: { overflowX: 'auto' } },
          h('table', { className: 'data-table', style: { minWidth: 800, direction: 'rtl' } },
            h('thead', null, h('tr', null,
              h('th', { style: { minWidth: 200 } }, 'المادة'),
              h('th', { title: 'BOM × الفواتير هذا الشهر' }, 'نظري'),
              h('th', { title: 'ما تم إدخاله يدوياً من ورقة الطبيب' }, 'فعلي'),
              h('th', { title: 'الفرق = فعلي - نظري (موجب = استهلاك زيادة عن المعيار)' }, 'فرق الاستهلاك'),
              h('th', { title: 'ما تم جرده فعلياً في الدرج' }, 'جرد الدرج'),
              h('th', { title: 'الكمية في النظام (مخزون × وحدات/علبة)' }, 'مخزون النظام'),
              h('th', { title: 'الفرق = جرد - مخزون (سالب = ضياع/سرقة)' }, 'فرق الجرد'),
            )),
            h('tbody', null,
              reportRows.map(({ item, theoretical, actual, physical, systemUnits, var1, var2 }) =>
                h('tr', { key: item.id },
                  h('td', { style: { fontWeight: 600 } }, item.name),
                  h('td', { style: { fontVariantNumeric: 'tabular-nums' } },
                    theoretical > 0 ? window.fmtNum(theoretical) : h('span', { style: { color: 'var(--text-tertiary)' } }, '—')
                  ),
                  h('td', { style: { fontVariantNumeric: 'tabular-nums', fontWeight: actual > 0 ? 700 : 400 } },
                    actual > 0 ? window.fmtNum(actual) : h('span', { style: { color: 'var(--text-tertiary)' } }, '—')
                  ),
                  h('td', null, varChip(actual > 0 || theoretical > 0 ? var1 : null)),
                  h('td', { style: { fontVariantNumeric: 'tabular-nums' } },
                    physical !== null ? window.fmtNum(physical) : h('span', { style: { color: 'var(--text-tertiary)' } }, '—')
                  ),
                  h('td', { style: { fontVariantNumeric: 'tabular-nums', color: 'var(--text-secondary)' } },
                    systemUnits !== null ? window.fmtNum(systemUnits) : h('span', { style: { color: 'var(--text-tertiary)' } }, '—')
                  ),
                  h('td', null, varChip(var2, true)),
                )
              ),
              h('tr', {
                style: {
                  background: 'var(--bg-subtle)',
                  fontWeight: 800,
                  borderTop: '2px solid var(--border)',
                },
              },
                h('td', null, '📊 الإجمالي'),
                h('td', null, window.fmtNum(reportRows.reduce((s, r) => s + r.theoretical, 0))),
                h('td', null, window.fmtNum(reportRows.reduce((s, r) => s + r.actual, 0))),
                h('td', null, varChip(
                  reportRows.reduce((s, r) => s + r.actual, 0) - reportRows.reduce((s, r) => s + r.theoretical, 0)
                )),
                h('td', null, window.fmtNum(reportRows.filter(r => r.physical !== null).reduce((s, r) => s + r.physical, 0))),
                h('td', null, window.fmtNum(reportRows.filter(r => r.systemUnits !== null).reduce((s, r) => s + r.systemUnits, 0))),
                h('td', null, varChip(
                  reportRows.filter(r => r.var2 !== null).reduce((s, r) => s + r.var2, 0), true
                )),
              ),
            ),
          ),
        ),
    ),
  );
}

// ==================== Inventory ====================
function Inventory() {
  const { toast, inventory, setInventory, services, setServices, clinicId, refreshData } = useContext(AppContext);
  const selectAllRef = useRef(null);
  const [tab, setTab] = useState('stock');
  const [query, setQuery] = useState('');
  const [bomService, setBomService] = useState(null);
  const [editService, setEditService] = useState(null);
  const [editInventoryItem, setEditInventoryItem] = useState(null);
  const [showAddService, setShowAddService] = useState(false);
  const [showAddInv, setShowAddInv] = useState(false);
  const [showBulkEditInv, setShowBulkEditInv] = useState(false);
  const [selectionMode, setSelectionMode] = useState(false);
  const [selectedInventoryIds, setSelectedInventoryIds] = useState([]);
  const [importing, setImporting] = useState(false);
  const [importingInv, setImportingInv] = useState(false);
  const [importingBom, setImportingBom] = useState(false);
  const [deletingInventory, setDeletingInventory] = useState(false);
  const [bomRefreshToken, setBomRefreshToken] = useState(0);
  const usageUnitsKey = `senan-inventory-usage-units:${clinicId || 'default'}`;
  const [usageUnitsMap, setUsageUnitsMap] = useState({});
  const [bomStats, setBomStats] = useState({});
  const allInv  = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
  const allSvcs = (services && services.length) ? services : (window.TREATMENT_TYPES || []);
  const filtered = allInv.filter(i => (i.name||'').includes(query) || (i.category||'').includes(query));
  const visibleInventoryIds = filtered.map(it => it.id);
  const allVisibleSelected = selectionMode && visibleInventoryIds.length > 0 && visibleInventoryIds.every(id => selectedInventoryIds.includes(id));
  const someVisibleSelected = selectionMode && visibleInventoryIds.some(id => selectedInventoryIds.includes(id));

  const handleServiceSaved = (updated) => {
    if (setServices) setServices(prev => prev.map(s => s.id === updated.id ? updated : s));
  };
  const handleNewService = (svc) => {
    if (setServices) setServices(prev => [svc, ...prev]);
  };
  const handleNewInvItem = (item) => {
    if (setInventory) setInventory(prev => [item, ...prev]);
  };
  const handleInventorySaved = (updated) => {
    if (setInventory) setInventory(prev => prev.map(it => it.id === updated.id ? updated : it));
  };
  const extractLegacyPackMeta = (item) => extractLegacyInventoryPackMeta(item);
  const getUsageUnitsPerPack = (item) => getInventoryUsageUnitsPerPack(item, usageUnitsMap);
  const getDisplayInventoryName = (item) => getInventoryDisplayName(item);
  const persistUsageUnitsValue = (itemId, value) => {
    setUsageUnitsMap(prev => {
      const next = { ...prev };
      const numericValue = Math.max(0, Number(value) || 0);
      if (numericValue > 0) next[itemId] = numericValue;
      else delete next[itemId];
      return next;
    });
  };

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(usageUnitsKey);
      setUsageUnitsMap(raw ? JSON.parse(raw) : {});
    } catch (error) {
      console.warn('[Inventory] failed to load usage units map:', error);
      setUsageUnitsMap({});
    }
  }, [usageUnitsKey]);

  useEffect(() => {
    try {
      window.localStorage.setItem(usageUnitsKey, JSON.stringify(usageUnitsMap));
    } catch (error) {
      console.warn('[Inventory] failed to save usage units map:', error);
    }
  }, [usageUnitsKey, usageUnitsMap]);

  useEffect(() => {
    let cancelled = false;
    const loadBomStats = async () => {
      if (!allSvcs.length || !allInv.length) {
        if (!cancelled) setBomStats({});
        return;
      }
      const inventoryPriceMap = {};
      allInv.forEach(item => {
        inventoryPriceMap[item.id] = getInventoryMeasureUnitPrice(item, usageUnitsMap);
      });
      const nextStats = {};
      for (const svc of allSvcs) {
        const bom = await DB.getBomForService(svc.id);
        nextStats[svc.id] = {
          cost: bom.reduce((sum, entry) => sum + ((inventoryPriceMap[entry.inventoryId] || 0) * (Number(entry.standardQty) || 0)), 0),
          itemsCount: bom.length,
        };
      }
      if (!cancelled) setBomStats(nextStats);
    };
    loadBomStats();
    return () => { cancelled = true; };
  }, [clinicId, allSvcs.length, allInv.length, JSON.stringify(usageUnitsMap), bomRefreshToken]);

  const renderLoadingDot = () => h('span', {
    style: {
      width: 14,
      height: 14,
      borderRadius: '50%',
      border: '2px solid var(--border)',
      borderTopColor: 'var(--accent)',
      display: 'inline-block',
      animation: 'spin 0.8s linear infinite',
      flexShrink: 0,
    },
  });

  const handleNewInvItemWithMeta = (item, usageUnitsPerPack = 0) => {
    persistUsageUnitsValue(item.id, usageUnitsPerPack);
    handleNewInvItem(item);
  };

  const handleInventorySavedWithMeta = (updated, usageUnitsPerPack = 0) => {
    persistUsageUnitsValue(updated.id, usageUnitsPerPack);
    handleInventorySaved(updated);
  };

  const toggleInventorySelection = (id) => {
    setSelectedInventoryIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
  };

  const handleSelectAllVisibleInventory = () => {
    const visibleIds = filtered.map(it => it.id);
    const allVisibleSelected = visibleIds.length > 0 && visibleIds.every(id => selectedInventoryIds.includes(id));
    if (allVisibleSelected) {
      setSelectedInventoryIds(prev => prev.filter(id => !visibleIds.includes(id)));
      setSelectionMode(false);
      return;
    }
    setSelectedInventoryIds(Array.from(new Set([...selectedInventoryIds, ...visibleIds])));
  };

  const handleBulkDeleteInventory = async () => {
    if (!selectedInventoryIds.length) {
      toast('اختر أصنافًا أولًا');
      return;
    }
    if (!window.confirm(`حذف ${selectedInventoryIds.length} صنف من المخزون؟`)) return;
    setDeletingInventory(true);
    try {
      for (const id of selectedInventoryIds) {
        await DB.deleteInventoryItem(id);
      }
      if (setInventory) setInventory(prev => prev.filter(it => !selectedInventoryIds.includes(it.id)));
      setSelectedInventoryIds([]);
      setSelectionMode(false);
      toast('تم حذف الأصناف المحددة');
    } catch (e) {
      toast('❌ خطأ: ' + (e.message || 'تعذر حذف بعض الأصناف'));
    } finally {
      setDeletingInventory(false);
    }
  };

  const handleBulkEditInventory = async (payload) => {
    const updatedRows = [];
    for (const id of selectedInventoryIds) {
      const row = await DB.updateInventoryItem(id, payload);
      updatedRows.push(row);
    }
    if (setInventory) {
      setInventory(prev => prev.map(it => updatedRows.find(row => row.id === it.id) || it));
    }
    setSelectedInventoryIds([]);
    setSelectionMode(false);
    toast('تم تعديل الأصناف المحددة ✅');
  };

  useEffect(() => {
    if (tab !== 'stock') {
      setSelectionMode(false);
      setSelectedInventoryIds([]);
    }
  }, [tab]);

  useEffect(() => {
    if (selectAllRef.current) {
      selectAllRef.current.indeterminate = !!(someVisibleSelected && !allVisibleSelected);
    }
  }, [someVisibleSelected, allVisibleSelected, selectionMode]);

  const SHEET_DOC_ID = '12LKRPmpFxpd6VRa0HGTUzqQQtFSEo3pnPA0kk2UfSnU';
  const SHEET_TABS = {
    stock: ['استيراد المخزون', 'استيراد المخزون '],
    services: ['استيراد الخدمات', 'الخدمات والاسعار', 'الخدمات والأسعار'],
    bom: ['استيراد مكونات الخدمات', 'مكونات الخدمة', 'مكونات الخدمات'],
  };
  const SHEET_GIDS = {
    stock: '2031167138',
  };
  const SHEET_BASE_URL = `https://docs.google.com/spreadsheets/d/${SHEET_DOC_ID}/gviz/tq?tqx=out:json&sheet=`;

  const normalizeSheetText = (value) => String(value || '')
    .replace(/[\u200c\u200d]/g, '')
    .replace(/\s+/g, ' ')
    .trim();

  const normalizeHeader = (value) => normalizeSheetText(value)
    .toLowerCase()
    .replace(/[\/_\-–—]+/g, ' ')
    .replace(/\s+/g, ' ')
    .trim();

  const parseGvizResponse = (rawText) => {
    const start = rawText.indexOf('{');
    const end = rawText.lastIndexOf('}');
    if (start < 0 || end < start) throw new Error('صيغة بيانات الشيت غير متوقعة');
    return JSON.parse(rawText.slice(start, end + 1));
  };

  const gvizCellValue = (cell) => {
    if (!cell) return '';
    if (typeof cell.f === 'string' && normalizeSheetText(cell.f)) return String(cell.f);
    if (cell.v == null) return '';
    return String(cell.v);
  };

  const headerIndex = (headers, candidates) => {
    const normalized = headers.map(normalizeHeader);
    for (const candidate of candidates) {
      const idx = normalized.indexOf(normalizeHeader(candidate));
      if (idx >= 0) return idx;
    }
    return -1;
  };

  const pickValue = (row, headers, candidates) => {
    const idx = headerIndex(headers, candidates);
    return idx >= 0 ? normalizeSheetText(row[idx]) : '';
  };

  const fetchSheetRows = async (kind) => {
    const sources = [];
    if (SHEET_GIDS[kind]) {
      sources.push({ gid: SHEET_GIDS[kind] });
    }
    for (const tabName of (SHEET_TABS[kind] || [])) {
      sources.push({ sheet: tabName });
    }

    for (const source of sources) {
      const url = source.gid
        ? `https://docs.google.com/spreadsheets/d/${SHEET_DOC_ID}/gviz/tq?tqx=out:json&gid=${source.gid}`
        : `${SHEET_BASE_URL}${encodeURIComponent(source.sheet)}`;
      const res = await fetch(url);
      if (!res.ok) continue;
      const rawText = await res.text();
      const payload = parseGvizResponse(rawText);
      const table = payload?.table;
      const rows = (table?.rows || [])
        .map(row => (row.c || []).map(gvizCellValue))
        .filter(row => row.some(v => normalizeSheetText(v)));
      if (!rows.length) continue;

      const columnHeaders = (table?.cols || []).map(col => normalizeSheetText(col?.label || ''));
      const firstRow = rows[0] || [];
      const firstRowLooksLikeHeaders = firstRow.some(value => /الخدمة|الخدمات|service|name|اسم|المكون|component|quantity|الكمية|السعر|price|الفئة|category|المخزون|stock|supplier|المورد|expiry|الصلاحية/i.test(String(value || '')));
      const hasColumnHeaders = columnHeaders.some(Boolean);
      const headers = (!hasColumnHeaders || firstRowLooksLikeHeaders) ? firstRow : columnHeaders;
      const dataRows = (!hasColumnHeaders || firstRowLooksLikeHeaders) ? rows.slice(1) : rows;

      if (headers.length && dataRows.length) {
        return { tabName: source.sheet || source.gid, headers, rows: dataRows };
      }
    }
    throw new Error('لم نتمكن من قراءة تبويب الشيت المطلوب');
  };

  const upsertLocalService = async (data) => {
    const inserted = await DB.addService(clinicId, data);
    if (inserted && setServices) setServices(prev => [inserted, ...prev]);
    return inserted;
  };

  const upsertLocalInventory = async (data) => {
    const inserted = await DB.addInventoryItem(clinicId, data);
    if (inserted && setInventory) setInventory(prev => [inserted, ...prev]);
    return inserted;
  };

  // ─── استيراد الخدمات من Google Sheets ───
  const importServicesFromSheets = async () => {
    setImporting(true);
    try {
      const { headers, rows } = await fetchSheetRows('services');
      const sheetSvcs = rows.map(row => {
        const name = pickValue(row, headers, ['الخدمة', 'service', 'name', 'اسم الخدمة', 'اسم الإجراء']);
        const category = pickValue(row, headers, ['الفئة', 'category', 'التصنيف', 'نوع الخدمة']) || 'عام';
        const durationRaw = pickValue(row, headers, ['المدة', 'duration', 'الزمن', 'الوقت']);
        const priceRaw = pickValue(row, headers, ['السعر', 'price', 'تكلفة', 'القيمة']);
        const duration = Math.max(5, parseInt(durationRaw.replace(/[^\d]/g, ''), 10) || 30);
        const price = parseFloat(priceRaw.replace(/[^\d.]/g, '')) || 0;
        return { name, category, duration, price };
      }).filter(s => s.name);

      if (!sheetSvcs.length) {
        throw new Error('تبويب استيراد الخدمات يحتاج عمود "اسم الخدمة" ويفضل معه "المدة" و"السعر"');
      }

      const existingNames = new Set(allSvcs.map(s => normalizeSheetText(s.name)));
      const toAdd = sheetSvcs.filter(s => !existingNames.has(normalizeSheetText(s.name)));

      if (toAdd.length === 0) {
        toast('✅ كل الخدمات موجودة بالفعل من الشيت الإرشادي');
        return;
      }

      let added = 0;
      for (const s of toAdd) {
        try {
          const inserted = await upsertLocalService({
            name: s.name,
            price: s.price,
            duration: s.duration,
            category: s.category,
          });
          if (inserted) added++;
        } catch(e) { console.error('خطأ في إضافة:', s.name, e); }
      }
      if (refreshData) await refreshData();
      toast(`✅ تم استيراد ${added} خدمة جديدة من الشيت الإرشادي`);
    } catch(e) {
      console.error(e);
      toast('❌ خطأ: ' + (e.message || 'فشل الاستيراد'));
    } finally {
      setImporting(false);
    }
  };

  // ─── استيراد المخزون من البيانات المحلية (_INV) ───
  const importInventoryFromSheets = async () => {
    setImportingInv(true);
    try {
      const { headers, rows } = await fetchSheetRows('stock');
      const sheetItems = rows.map(row => {
        const name = pickValue(row, headers, ['الصنف', 'الاسم', 'name', 'item', 'اسم الصنف']);
        const category = pickValue(row, headers, ['الفئة', 'category', 'التصنيف', 'نوع الصنف']) || 'مستلزمات طبية';
        const stockRaw = pickValue(row, headers, ['المخزون', 'stock', 'qty', 'quantity', 'الكمية']);
        const minRaw = pickValue(row, headers, ['الحد الأدنى', 'min stock', 'minimum', 'min', 'الحد الأدني']);
        const unit = pickValue(row, headers, ['الوحدة', 'unit', 'units']) || 'قطعة';
        const priceRaw = pickValue(row, headers, ['السعر', 'price', 'cost', 'التكلفة']);
        const supplier = pickValue(row, headers, ['المورد', 'supplier', 'source']) || '';
        const expiry = pickValue(row, headers, ['الصلاحية', 'expiry', 'expires', 'expiry date']) || '';
        const usageUnitsRaw = pickValue(row, headers, [
          'عدد وحدات الاستخدام داخل العبوة',
          'عدد الحالات داخل العبوة',
          'عدد الوحدات داخل العبوة',
          'تكفي كام حالة',
          'الحالات داخل العبوة',
          'usage units per pack',
          'cases per pack',
        ]);
        const stock = Math.max(0, parseFloat(stockRaw.replace(/[^\d.]/g, '')) || 0);
        const minStock = Math.max(0, parseFloat(minRaw.replace(/[^\d.]/g, '')) || 0);
        const price = Math.max(0, parseFloat(priceRaw.replace(/[^\d.]/g, '')) || 0);
        const usageUnitsPerPack = Math.max(0, parseFloat(String(usageUnitsRaw || '').replace(/[^\d.]/g, '')) || 0);
        return { name, category, stock, minStock, unit, price, supplier, expiry, usageUnitsPerPack };
      }).filter(i => i.name);

      if (!sheetItems.length) {
        const hasServiceHeader = headerIndex(headers, ['اسم الخدمة', 'الخدمة', 'service', 'service name']) >= 0;
        if (hasServiceHeader) {
          throw new Error('تبويب استيراد المخزون يحتوي بيانات خدمات الآن، وليس أصناف مخزون');
        }
        throw new Error('تبويب استيراد المخزون يحتاج عمود "اسم الصنف" على الأقل');
      }

      const existingNames = new Set(allInv.map(i => normalizeSheetText(i.name)));
      const toAdd = sheetItems.filter(i => !existingNames.has(normalizeSheetText(i.name)));
      if (toAdd.length === 0) {
        toast('✅ كل أصناف المخزون موجودة بالفعل من الشيت الإرشادي');
        return;
      }
      let added = 0;
      let failed = 0;
      let firstError = '';
      for (const item of toAdd) {
        try {
          const inserted = await upsertLocalInventory({
            name: item.name,
            price: item.price,
            stock: item.stock,
            min_stock: item.minStock,
            unit: item.unit,
            category: item.category,
            supplier: item.supplier || null,
            expiry: item.expiry || null,
          });
          if (inserted) {
            persistUsageUnitsValue(inserted.id, item.usageUnitsPerPack || 0);
            added++;
          }
        } catch(e) {
          failed++;
          if (!firstError) firstError = e?.message || '';
          console.error('خطأ في إضافة صنف:', item.name, e);
        }
      }
      if (added === 0 && failed > 0) {
        throw new Error(firstError || 'تعذر إضافة أصناف المخزون من الشيت');
      }
      if (refreshData) await refreshData();
      toast(`✅ تم استيراد ${added} صنف جديد من الشيت الإرشادي${failed ? ` · تعذر ${failed}` : ''}`);
    } catch(e) {
      console.error(e);
      toast('❌ خطأ: ' + (e.message || 'فشل الاستيراد'));
    } finally {
      setImportingInv(false);
    }
  };

  // ─── استيراد مكونات الخدمات (BOM) من البيانات المحلية (_BOM) ───
  const importBomFromSheets = async () => {
    setImportingBom(true);
    try {
      // نحتاج قائمة محدّثة من Supabase للخدمات والمخزون
      const currentInv  = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
      const currentSvcs = (services  && services.length)  ? services  : (window.TREATMENT_TYPES || []);

      let totalAdded = 0, skipped = 0;

      for (const [svcName, components] of Object.entries(_BOM)) {
        // إيجاد الخدمة بالاسم (مطابقة جزئية أو كاملة)
        const svc = currentSvcs.find(s => (s.name || '').trim() === svcName.trim());
        if (!svc) { console.warn('لم يُعثر على خدمة:', svcName); skipped++; continue; }

        for (const [itemName, qty] of components) {
          const invItem = currentInv.find(i => (i.name || '').trim() === itemName.trim());
          if (!invItem) { console.warn('لم يُعثر على صنف مخزون:', itemName, '← الخدمة:', svcName); skipped++; continue; }
          try {
            await DB.addBomItem(clinicId, svc.id, invItem.id, qty);
            totalAdded++;
          } catch(e) {
            // تجاهل خطأ upsert conflict (مكوّن موجود مسبقاً)
            if (e && e.code === '23505') { totalAdded++; }
            else { console.error('خطأ BOM:', svcName, itemName, e); skipped++; }
          }
        }
      }
      toast(`✅ تم استيراد ${totalAdded} مكوّن${skipped ? ' · تخطّى ' + skipped : ''}`);
    } catch(e) {
      console.error(e);
      toast('❌ خطأ: ' + (e.message || 'فشل الاستيراد'));
    } finally {
      setImportingBom(false);
    }
  };

  const importBomFromGuidedSheet = async () => {
    setImportingBom(true);
    try {
      const currentInv  = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
      const currentSvcs = (services  && services.length)  ? services  : (window.TREATMENT_TYPES || []);
      if (!currentSvcs.length) throw new Error('استورد الخدمات أولاً قبل مكونات الخدمة');
      if (!currentInv.length) throw new Error('استورد المخزون أو أضف أصنافاً أولاً قبل مكونات الخدمة');
      const { headers, rows } = await fetchSheetRows('bom');
      const sheetRows = rows.map(row => ({
        service: pickValue(row, headers, ['الخدمة', 'service', 'اسم الخدمة', 'الإجراء', 'procedure']),
        item: pickValue(row, headers, ['اسم الصنف', 'المكون', 'item', 'الصنف', 'المادة', 'component']),
        qty: parseFloat(pickValue(row, headers, ['الكمية المعيارية', 'الكمية', 'qty', 'quantity', 'amount']).replace(/[^\d.]/g, '')) || 1,
      })).filter(r => r.service && r.item);

      if (!sheetRows.length) {
        throw new Error('تبويب استيراد مكونات الخدمة يحتاج: اسم الخدمة + اسم الصنف + الكمية المعيارية');
      }

      let totalAdded = 0, skipped = 0;
      for (const row of sheetRows) {
        const svc = currentSvcs.find(s => normalizeSheetText(s.name) === normalizeSheetText(row.service));
        const invItem = currentInv.find(i => normalizeSheetText(i.name) === normalizeSheetText(row.item));
        if (!svc || !invItem) { skipped++; continue; }
        try {
          await DB.addBomItem(clinicId, svc.id, invItem.id, row.qty);
          totalAdded++;
        } catch (e) {
          if (e && e.code === '23505') totalAdded++;
          else { console.error('خطأ BOM:', row.service, row.item, e); skipped++; }
        }
      }
      setBomRefreshToken(prev => prev + 1);
      if (refreshData) await refreshData();
      toast(`✅ تم استيراد ${totalAdded} مكوّن${skipped ? ' · تخطّي ' + skipped : ''}`);
    } catch (e) {
      console.error(e);
      toast('❌ خطأ: ' + (e.message || 'فشل الاستيراد'));
    } finally {
      setImportingBom(false);
    }
  };

  return h('div', { className: 'fade-in' },
    bomService ? h(BomModal, { service: bomService, onClose: () => setBomService(null) }) : null,
    editService ? h(EditServiceModal, { service: editService, onClose: () => setEditService(null), onSaved: handleServiceSaved }) : null,
    editInventoryItem ? h(EditInventoryModal, { item: editInventoryItem, onClose: () => setEditInventoryItem(null), onSaved: handleInventorySavedWithMeta }) : null,
    showBulkEditInv ? h(BulkEditInventoryModal, { count: selectedInventoryIds.length, onClose: () => setShowBulkEditInv(false), onSaved: handleBulkEditInventory }) : null,
    showAddService ? h(AddServiceModal, { onClose: () => setShowAddService(false), onSaved: handleNewService }) : null,
    showAddInv ? h(AddInventoryModal, { onClose: () => setShowAddInv(false), onSaved: handleNewInvItemWithMeta }) : null,

    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'المخزون والخدمات'),
        h('div', { className: 'page-subtitle' }, `${allInv.length} ${'صنف'} · ${allSvcs.length} ${'خدمة'}`),
      ),
      h('div', { className: 'flex gap-8' },
        tab !== 'variance' && h('button', { className: 'btn outline' }, h(Icons.Download, { size: 16 }), 'تصدير'),
        tab === 'stock' ? h(Fragment, null,
          h('button', {
            className: 'btn outline',
            onClick: importInventoryFromSheets,
            disabled: importingInv,
            title: 'استيراد المخزون من الشيت الإرشادي — قابل للتعديل بعد الاستيراد',
          }, importingInv ? renderLoadingDot() : h(Icons.Download, { size: 16 }), importingInv ? 'جاري الاستيراد...' : 'استيراد المخزون'),
          h('button', {
            className: 'btn outline',
            onClick: () => setSelectionMode(true),
          }, 'تحديد'),
          selectionMode && selectedInventoryIds.length > 0 ? h('button', {
            className: 'btn outline',
            onClick: () => setShowBulkEditInv(true),
          }, `تعديل المحدد${selectedInventoryIds.length ? ` (${selectedInventoryIds.length})` : ''}`) : null,
          selectionMode && selectedInventoryIds.length > 0 ? h('button', {
            className: 'btn danger outline',
            disabled: deletingInventory,
            onClick: handleBulkDeleteInventory,
          }, deletingInventory ? renderLoadingDot() : h(Icons.Trash, { size: 14 }), deletingInventory ? 'جاري الحذف...' : `${'حذف المحدد'}${selectedInventoryIds.length ? ` (${selectedInventoryIds.length})` : ''}`) : null,
          h('button', { className: 'btn primary', onClick: () => setShowAddInv(true) }, h(Icons.Plus, { size: 16 }), 'صنف جديد'),
        ) : null,
        /* الخدمات تفضل مدارتها الأساسية في التسعير والربحية، لكن الاستيراد هنا مطلوب قبل ربط المكونات */
        tab === 'bom' ? h(Fragment, null,
          h('button', {
            className: 'btn outline',
            onClick: importServicesFromSheets,
            disabled: importing,
            title: 'استيراد الخدمات من الشيت الإرشادي حتى تظهر في مكونات الخدمة',
          }, importing ? renderLoadingDot() : h(Icons.Download, { size: 16 }), importing ? 'جاري الاستيراد...' : 'استيراد الخدمات'),
          h('button', {
            className: 'btn outline',
            onClick: importBomFromGuidedSheet,
            disabled: importingBom,
            title: 'استيراد مكونات الخدمة من الشيت الإرشادي — قابل للتعديل بعد الاستيراد',
          }, importingBom ? renderLoadingDot() : h(Icons.Download, { size: 16 }), importingBom ? 'جاري الاستيراد...' : 'استيراد مكونات الخدمة'),
        ) : null,
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'card p-12 mb-12', style: { background: 'var(--accent-soft)', border: '1px solid var(--border)', color: 'var(--text-secondary)' } },
        'الاستيراد هنا إرشادي فقط. بعد نزول البيانات تقدر تعدل، تحذف، وتضيف بحرية من نفس الشاشة.'
      ),
      h('div', { className: 'tabs mb-16' },
        [['stock','📦 المخزون'], ['bom','🔬 مكونات الخدمات'], ['variance','📊 الجرد والتحليل']].map(([v,l]) =>
          h('button', { key:v, className:'tab'+(tab===v?' active':''), onClick:()=>setTab(v) }, l)
        ),
      ),

      /* ======= TAB: المخزون ======= */
      tab === 'stock' && h(Fragment, null,
        h('div', { className: 'card p-16 mb-16 flex gap-8 ai-c' },
          h('div', { style: { flex: 1, position: 'relative' } },
            h('input', { className: 'input', placeholder: 'بحث...', value: query, onChange: (e) => setQuery(e.target.value), style: { paddingInlineEnd: 40 } }),
            h('span', { style: { position: 'absolute', insetInlineEnd: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-tertiary)' } }, h(Icons.Search, { size: 16 })),
          ),
          h('button', { className: 'btn outline' }, h(Icons.Filter, { size: 16 }), 'الفئة'),
        ),
        h('div', { className: 'card', style: { overflowX: 'auto', overflowY: 'hidden', direction: 'rtl' } },
          h('table', { className: 'data-table', style: { minWidth: 1180, width: '100%', direction: 'rtl' } },
            h('thead', null, h('tr', null,
              h('th', { style: { minWidth: 220, whiteSpace: 'nowrap' } },
                h('div', { style: { display:'flex', alignItems:'center', justifyContent:'flex-end', gap:10 } },
                  h('span', null, 'الصنف'),
                  selectionMode ? h('input', {
                    ref: selectAllRef,
                    type: 'checkbox',
                    checked: !!allVisibleSelected,
                    onChange: handleSelectAllVisibleInventory,
                    title: allVisibleSelected ? 'إلغاء تحديد الكل' : 'تحديد الكل',
                  }) : null,
                ),
              ),
              ['الفئة', 'المخزون', 'وحدات القياس الفعلية', 'الحد الأدنى', 'السعر', 'سعر وحدة القياس', 'الصلاحية', 'الحالة', '', '', ''].map((t, i) => h('th', { key: i }, t))
            )),
            h('tbody', null,
              filtered.map(it => {
                const stockQty = Number(it.stock) || 0;
                const minQty = Number(it.minStock) || 0;
                const critical = stockQty <= 0;
                const low = !critical && minQty > 0 && stockQty <= minQty;
                const selected = selectedInventoryIds.includes(it.id);
                const usageUnitsPerPack = getUsageUnitsPerPack(it);
                const actualUsageUnits = getInventoryActualUsageUnits(it, usageUnitsMap);
                const measureUnitPrice = getInventoryMeasureUnitPrice(it, usageUnitsMap);
                return h('tr', { key: it.id },
                  h('td', { style: { fontWeight: 600, minWidth: 220 } },
                    h('div', { style: { display:'flex', alignItems:'center', justifyContent:'flex-end', gap:10 } },
                      h('div', { style: { display:'grid', gap:4, justifyItems:'end', textAlign:'right' } },
                        h('span', null, getDisplayInventoryName(it)),
                        usageUnitsPerPack > 0 ? h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)', fontWeight: 500 } }, `العبوة تكفي ${window.fmtNum(usageUnitsPerPack)} حالة`) : null,
                      ),
                      selectionMode ? h('input', {
                        type: 'checkbox',
                        checked: selected,
                        onChange: () => toggleInventorySelection(it.id),
                      }) : null,
                    ),
                  ),
                  h('td', null, h('span', { className: 'chip' }, it.category)),
                  h('td', null,
                    h('div', { className: 'flex ai-c gap-8' },
                      h('span', { style: { fontWeight: 800, color: critical ? 'var(--danger)' : low ? 'var(--warning)' : 'var(--text-primary)' } }, window.fmtNum(stockQty)),
                      h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, it.unit),
                    ),
                  ),
                  h('td', { style: { fontWeight: 700 } }, usageUnitsPerPack > 0 ? window.fmtNum(actualUsageUnits) : '—'),
                  h('td', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, window.fmtNum(minQty) + ' ' + it.unit),
                  h('td', { style: { fontWeight: 600 } }, window.fmtEGP(it.price)),
                  h('td', { style: { fontWeight: 600 } }, usageUnitsPerPack > 0 ? window.fmtEGP(measureUnitPrice) : '—'),
                  h('td', { style: { fontSize: 12, color: 'var(--text-secondary)' } }, it.expiry || '—'),
                  h('td', null, h('span', { className: 'chip ' + (critical ? 'danger' : low ? 'warning' : 'success') },
                    critical ? 'نافد' : low ? 'منخفض' : 'متاح')),
                  h('td', null, h('button', { className: 'btn sm outline', onClick: () => toast('تم طلب الصنف') }, 'طلب')),
                  h('td', null, h('button', {
                    className: 'btn sm outline',
                    onClick: () => setEditInventoryItem({ ...it, usageUnitsPerPack }),
                  }, h(Icons.Edit, { size: 13 }), 'تعديل')),
                  h('td', null, h('button', {
                    className: 'btn sm danger outline',
                    onClick: async () => {
                      if (!window.confirm('حذف الصنف من المخزون؟')) return;
                      try {
                        await DB.deleteInventoryItem(it.id);
                        if (setInventory) setInventory(prev => prev.filter(x => x.id !== it.id));
                        toast('تم حذف الصنف');
                      } catch (e) {
                        toast('❌ خطأ: ' + (e.message || 'تعذر الحذف'));
                      }
                    },
                  }, h(Icons.Trash, { size: 13 }), 'حذف')),
                );
              }),
            ),
          ),
        ),
      ),

      /* ======= TAB: الجرد والتحليل ======= */
      tab === 'variance' && h(VarianceAnalysisTab, null),

      /* ======= TAB: BOM ======= */
      tab === 'bom' && h('div', null,
        h('div', { className: 'grid', style: { gap: 10 } },
          allSvcs.map(svc => h('div', { key: svc.id, className: 'card p-16', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
            h('div', null,
              h('div', { style: { fontWeight: 700, fontSize: 14 } }, svc.name),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, 'إجمالي تكلفة المكونات: ' + window.fmtEGP((bomStats[svc.id] && bomStats[svc.id].cost) || 0) + ' · ' + (svc.duration || 30) + ' دقيقة'),
            ),
            h('div', { className: 'flex gap-8' },
              h('button', { className: 'btn outline', onClick: () => setBomService(svc) },
                h(Icons.Package, { size: 15 }), 'إدارة المكونات'),
              h('button', {
                className: 'btn danger outline',
                onClick: async () => {
                  if (!window.confirm('حذف الخدمة وكل مكوناتها؟')) return;
                  try {
                    await DB.deleteService(svc.id);
                    if (setServices) setServices(prev => prev.filter(x => x.id !== svc.id));
                    toast('تم حذف الخدمة');
                  } catch (e) {
                    toast('❌ خطأ: ' + (e.message || 'تعذر الحذف'));
                  }
                },
              }, h(Icons.Trash, { size: 14 }), 'حذف'),
            ),
          )),
          allSvcs.length === 0 && h('div', { style: { textAlign: 'center', padding: 32, color: 'var(--text-tertiary)', border: '2px dashed var(--border)', borderRadius: 'var(--radius)' } },
            'أضف خدمات أولاً من شاشة التسعير والربحية'),
        ),
      ),
    ),
  );
}

// ==================== Edit Doctor Modal ====================
function EditDoctorModal({ doctor, onClose, onSaved }) {
  const { toast, clinicId } = useContext(AppContext);
  const isNew = !doctor?.id;
  const initialSchedule = normalizeDoctorSchedule(doctor || {});
  const [form, setForm] = useState({
    name: doctor?.name || '',
    specialty: doctor?.specialty || 'أسنان عامة',
    commission_rate: Math.round((doctor?.commissionRate || 0.30) * 100),
    working_days: initialSchedule.days,
    working_from: initialSchedule.from,
    working_to: initialSchedule.to,
  });
  const [saving, setSaving] = useState(false);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const toggleDay = (day) => setForm(prev => {
    const hasDay = (prev.working_days || []).includes(day);
    return {
      ...prev,
      working_days: hasDay
        ? (prev.working_days || []).filter(item => item !== day)
        : [...(prev.working_days || []), day],
    };
  });

  const handleSave = async () => {
    if (!form.name.trim()) { toast('اسم الطبيب مطلوب'); return; }
    const rate = Math.min(Math.max(+form.commission_rate, 0), 100) / 100;
    const schedule = normalizeDoctorSchedule({
      days: form.working_days,
      from: form.working_from,
      to: form.working_to,
    });
    setSaving(true);
    try {
      const payload = {
        name: form.name.trim(),
        specialty: form.specialty.trim() || 'أسنان عامة',
        commission_rate: rate,
        color: doctor?.color || '#0891b2',
        status: doctor?.status || 'متاح',
        working_days: schedule.days,
        working_from: schedule.from,
        working_to: schedule.to,
      };
      const saved = isNew ? await DB.addDoctor(clinicId, payload) : await DB.updateDoctor(doctor.id, payload);
      toast(isNew ? 'تم إضافة الطبيب ✅' : 'تم حفظ بيانات الطبيب ✅');
      onSaved({ ...(doctor || {}), ...saved, commissionRate: rate });
      onClose();
    } catch(e) { toast('خطأ: ' + (e.message || 'غير متوقع')); }
    finally { setSaving(false); }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:300 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:420, padding:24, maxHeight:'90vh', overflowY:'auto' } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:20} },
        h('div', { style:{fontWeight:800,fontSize:16} }, isNew ? 'إضافة طبيب' : 'تعديل بيانات الطبيب'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{display:'grid',gap:12} },
        h('div', null,
          h('div', { className:'label' }, 'الاسم'),
          h('input', { className:'input', value:form.name, onChange:e=>set('name',e.target.value) }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'التخصص'),
          h('input', { className:'input', value:form.specialty, onChange:e=>set('specialty',e.target.value) }),
        ),
        h('div', null,
          h('div', { className:'label' }, 'نسبة العمولة (%)'),
          h('input', { className:'input', type:'number', min:0, max:100, value:form.commission_rate, onChange:e=>set('commission_rate',e.target.value) }),
          h('div', { style:{fontSize:11,color:'var(--text-tertiary)',marginTop:4} },
            `كل 1000 ج.م مدفوعة → عمولة: ${window.fmtEGP(1000 * form.commission_rate / 100)}`),
        ),
        h('div', null,
          h('div', { className:'label' }, 'أيام العمل'),
          h('div', { className:'flex gap-8 wrap', style:{ marginTop:10 } },
            DOCTOR_SCHEDULE_DAY_OPTIONS.map(day => {
              const active = (form.working_days || []).includes(day);
              return h('button', {
                key: day,
                type: 'button',
                className: 'btn sm ' + (active ? 'primary' : 'outline'),
                onClick: () => toggleDay(day),
              }, day);
            }),
          ),
        ),
        h('div', { className:'grid cols-2', style:{ gap:12 } },
          h('div', null,
            h('div', { className:'label' }, 'من الساعة'),
            h('input', { className:'input', type:'time', value:form.working_from, onChange:e=>set('working_from',e.target.value) }),
          ),
          h('div', null,
            h('div', { className:'label' }, 'إلى الساعة'),
            h('input', { className:'input', type:'time', value:form.working_to, onChange:e=>set('working_to',e.target.value) }),
          ),
        ),
        h('div', { className:'card', style:{ padding:14, background:'var(--bg-subtle)' } },
          h('div', { style:{ fontSize:12, color:'var(--text-tertiary)', marginBottom:6 } }, 'ملخص المواعيد'),
          h('div', { style:{ fontWeight:700 } }, formatDoctorScheduleSummary({
            days: form.working_days,
            from: form.working_from,
            to: form.working_to,
          })),
        ),
      ),
      h('div', { className:'flex gap-8 jc-sb mt-20' },
        h('button', { className:'btn outline', onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn primary', disabled:saving, onClick:handleSave },
          saving ? 'جاري الحفظ...' : (isNew ? 'إضافة الطبيب' : 'حفظ')),
      ),
    ),
  );
}

const DOCTOR_SCHEDULE_DAY_OPTIONS = ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'];

function normalizeDoctorSchedule(schedule = {}) {
  const sourceDays = Array.isArray(schedule.days)
    ? schedule.days
    : Array.isArray(schedule.workingDays)
      ? schedule.workingDays
      : [];
  const normalizedDays = sourceDays.filter(day => DOCTOR_SCHEDULE_DAY_OPTIONS.includes(day));
  const fromValue = schedule.from || schedule.workingFrom || '14:00';
  const toValue = schedule.to || schedule.workingTo || '22:00';
  return {
    days: normalizedDays,
    from: String(fromValue).slice(0, 5) || '14:00',
    to: String(toValue).slice(0, 5) || '22:00',
  };
}

function formatDoctorScheduleSummary(schedule) {
  const normalized = normalizeDoctorSchedule(schedule);
  if (!normalized.days.length) return 'لم يتم تحديد أيام العمل بعد';
  const daysLabel = normalized.days.length <= 3
    ? normalized.days.join('، ')
    : `${normalized.days.slice(0, 3).join('، ')} +${normalized.days.length - 3}`;
  return `${daysLabel} · ${normalized.from} - ${normalized.to}`;
}

// ==================== Staff ====================
function Staff() {
  const { doctors, setDoctors, staff, setStaff, toast, clinicId } = useContext(AppContext);
  const [editDoc, setEditDoc] = useState(null);
  const [staffModal, setStaffModal] = useState(null);
  const [importingDocs, setImportingDocs] = useState(false);
  const [savingStaff, setSavingStaff] = useState(false);
  const [deletingStaffId, setDeletingStaffId] = useState(null);
  const [deletingDoctorId, setDeletingDoctorId] = useState(null);
  const [query, setQuery] = useState('');
  const allDoctors = (doctors && doctors.length) ? doctors : (window.DOCTORS || []);
  const allStaff = Array.isArray(staff) ? staff : (window.STAFF || []);
  const filteredStaff = allStaff.filter(s => [s.name, s.role, s.phone, s.shift].join(' ').toLowerCase().includes(query.toLowerCase()));

  const handleDoctorSaved = (updated) => {
    if (setDoctors) setDoctors(prev => (prev || []).some(d => d.id === updated.id)
      ? (prev || []).map(d => d.id === updated.id ? updated : d)
      : [updated, ...(prev || [])]);
  };

  const SHEET_DOCTORS = [
    { name: 'د/ احمد دراج', specialty: 'أسنان عامة', commission_rate: 0.30, color: '#0891b2' },
    { name: 'د/ محمد عمر',  specialty: 'أسنان عامة', commission_rate: 0.30, color: '#7c3aed' },
  ];
  const importDoctorsFromSheets = async () => {
    setImportingDocs(true);
    try {
      const existingNames = new Set(allDoctors.map(d => (d.name || '').trim()));
      const toAdd = SHEET_DOCTORS.filter(d => !existingNames.has(d.name));
      if (toAdd.length === 0) { toast('✅ الأطباء موجودون بالفعل'); return; }
      let added = 0;
      for (const d of toAdd) {
        const { data, error } = await SB.from('doctors')
          .insert({ clinic_id: clinicId, name: d.name, specialty: d.specialty, commission_rate: d.commission_rate, color: d.color, status: 'متاح' })
          .select().single();
        if (!error && data) {
          if (setDoctors) setDoctors(prev => [...prev, {
            ...data,
            commissionRate: data.commission_rate,
            avatar: (data.name || '').slice(0, 2),
          }]);
          added++;
        }
      }
      toast('✅ تم استيراد ' + added + ' طبيب من Google Sheets');
    } catch(e) { toast('❌ خطأ: ' + (e.message || 'فشل')); }
    finally { setImportingDocs(false); }
  };

  const emptyStaffForm = { name: '', role: 'استقبال', phone: '', shift: 'صباحي' };
  const openStaffModal = (member = null) => setStaffModal(member ? {
    ...emptyStaffForm,
    ...member,
    role: member.role || 'استقبال',
  } : { ...emptyStaffForm });
  const saveStaffMember = async () => {
    if (!staffModal?.name?.trim()) { toast('اسم الموظف مطلوب'); return; }
    setSavingStaff(true);
    try {
      const payload = {
        name: staffModal.name.trim(),
        role: staffModal.role || 'موظف',
        phone: staffModal.phone || '',
        shift: staffModal.shift || 'صباحي',
      };
      if (staffModal.id) {
        const updated = await DB.updateStaff(staffModal.id, payload);
        if (setStaff) setStaff(prev => (prev || []).map(s => s.id === updated.id ? updated : s));
        toast('تم تحديث بيانات الموظف ✅');
      } else {
        const inserted = await DB.addStaff(clinicId, payload);
        if (setStaff) setStaff(prev => [inserted, ...(prev || [])]);
        toast('تم إضافة الموظف ✅');
      }
      setStaffModal(null);
    } catch (e) {
      toast('❌ خطأ: ' + (e.message || 'تعذر حفظ الموظف'));
    } finally {
      setSavingStaff(false);
    }
  };

  const deleteStaffMember = async (member) => {
    if (!member?.id || !window.confirm(`حذف ${member.name} من الموظفين؟`)) return;
    setDeletingStaffId(member.id);
    try {
      await DB.deleteStaff(member.id);
      if (setStaff) setStaff(prev => (prev || []).filter(s => s.id !== member.id));
      toast('تم حذف الموظف');
    } catch (e) {
      toast('❌ خطأ: ' + (e.message || 'تعذر حذف الموظف'));
    } finally {
      setDeletingStaffId(null);
    }
  };

  const deleteDoctorMember = async (doctor) => {
    if (!doctor?.id || !window.confirm(`حذف ${doctor.name} من قائمة الأطباء؟`)) return;
    setDeletingDoctorId(doctor.id);
    try {
      await DB.deleteDoctor(doctor.id);
      if (setDoctors) setDoctors(prev => (prev || []).filter(item => item.id !== doctor.id));
      toast('تم حذف الطبيب');
    } catch (error) {
      toast('❌ خطأ: ' + (error.message || 'تعذر حذف الطبيب'));
    } finally {
      setDeletingDoctorId(null);
    }
  };

  const roleCounts = allStaff.reduce((acc, s) => {
    const role = s.role || 'غير محدد';
    acc[role] = (acc[role] || 0) + 1;
    return acc;
  }, {});

  return h('div', { className: 'fade-in' },
    editDoc ? h(EditDoctorModal, { doctor: editDoc, onClose: () => setEditDoc(null), onSaved: handleDoctorSaved }) : null,
    staffModal ? h('div', { className:'modal-backdrop', onClick: () => setStaffModal(null), style: { zIndex: 500 } },
      h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width: 480, padding: 24 } },
        h('div', { className:'modal-header' },
          h('div', { className:'modal-title' }, staffModal.id ? 'تعديل موظف' : 'موظف جديد'),
          h('button', { className:'icon-btn', onClick: () => setStaffModal(null) }, h(Icons.X, { size: 16 })),
        ),
        h('div', { style: { display: 'grid', gap: 12, padding: '16px 0' } },
          h('div', null, h('div', { className:'label' }, 'اسم الموظف'), h('input', { className:'input', value: staffModal.name, onChange: e => setStaffModal(f => ({ ...f, name: e.target.value })) })),
          h('div', { className:'grid cols-2', style: { gap: 12 } },
            h('div', null, h('div', { className:'label' }, 'الدور / الصلاحية'), h('select', { className:'select', value: staffModal.role, onChange: e => setStaffModal(f => ({ ...f, role: e.target.value })) },
              ['استقبال', 'تمريض', 'مساعد طبيب', 'محاسبة', 'مخزون', 'تعقيم', 'إدارة', 'أخرى'].map(role => h('option', { key: role, value: role }, role)),
            )),
            h('div', null, h('div', { className:'label' }, 'الوردية'), h('select', { className:'select', value: staffModal.shift, onChange: e => setStaffModal(f => ({ ...f, shift: e.target.value })) },
              ['صباحي', 'مسائي', 'يوم كامل', 'مرن'].map(shift => h('option', { key: shift, value: shift }, shift)),
            )),
          ),
          h('div', null, h('div', { className:'label' }, 'الهاتف'), h('input', { className:'input', value: staffModal.phone, onChange: e => setStaffModal(f => ({ ...f, phone: e.target.value })) })),
        ),
        h('div', { className:'modal-footer' },
          h('button', { className:'btn outline', onClick: () => setStaffModal(null) }, 'إلغاء'),
          h('button', { className:'btn primary', disabled: savingStaff, onClick: saveStaffMember }, savingStaff ? 'جاري الحفظ...' : 'حفظ'),
        ),
      ),
    ) : null,
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الموظفين'),
        h('div', { className: 'page-subtitle' }, `${allDoctors.length} ${'أطباء'} · ${allStaff.length} ${'موظفين مساعدين'}`),
      ),
      h('div', { className: 'flex gap-8' },
        allDoctors.length === 0 ? h('button', {
          className: 'btn outline',
          onClick: importDoctorsFromSheets,
          disabled: importingDocs,
        }, importingDocs ? 'جاري الاستيراد...' : 'استيراد الأطباء من Sheets') : null,
        h('button', { className: 'btn outline', onClick: () => setEditDoc({}) }, h(Icons.Stethoscope, { size: 16 }), 'طبيب جديد'),
        h('button', { className: 'btn primary', onClick: () => openStaffModal() }, h(Icons.UserPlus, { size: 16 }), 'موظف جديد'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className:'grid cols-4 mb-16' },
        [
          { label: 'الأطباء', value: allDoctors.length, icon: Icons.Stethoscope, color: 'var(--accent)' },
          { label: 'الموظفون', value: allStaff.length, icon: Icons.Users, color: 'var(--info)' },
          { label: 'الاستقبال', value: roleCounts['استقبال'] || 0, icon: Icons.User, color: 'var(--success)' },
          { label: 'المساعدون', value: (roleCounts['تمريض'] || 0) + (roleCounts['مساعد طبيب'] || 0), icon: Icons.Briefcase, color: 'var(--warning)' },
        ].map(card => h('div', { key: card.label, className:'card kpi' },
          h('div', { className:'flex jc-sb ai-c' },
            h('div', null,
              h('div', { className:'label' }, card.label),
              h('div', { className:'value' }, card.value),
            ),
            h('div', { className:'kpi-icon', style: { background: 'var(--bg-subtle)', color: card.color } }, h(card.icon, { size: 20 })),
          ),
        )),
      ),
      h('div', { className: 'mb-16', style: { fontWeight: 800, fontSize: 15 } }, 'الأطباء'),
      h('div', { className: 'grid cols-4 mb-24' },
        allDoctors.map(d => {
          const schedule = normalizeDoctorSchedule(d);
          return h('div', { key: d.id, className: 'card p-20', style: { textAlign: 'center' } },
          h('div', { className: 'avatar lg', style: { background: d.color, margin: '0 auto 12px' } }, d.avatar),
          h('div', { style: { fontWeight: 800, fontSize: 15 } }, d.name),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, d.specialty),
          h('div', { style: { fontSize: 12, color: 'var(--success)', fontWeight: 700, marginTop: 4 } }, `عمولة: ${Math.round((d.commissionRate || 0.30) * 100)}%`),
          h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 8, lineHeight: 1.7, minHeight: 34 } }, formatDoctorScheduleSummary(schedule)),
          h('span', { className: 'chip ' + (d.status === 'مع مريض' ? 'warning' : 'success'), style: { marginTop: 12 } }, d.status || 'متاح'),
          h('div', { className:'grid cols-1', style: { gap: 8, marginTop: 12 } },
            h('button', { className: 'btn sm outline', style: { width: '100%' }, onClick: () => setEditDoc(d) }, h(Icons.Edit, { size: 13 }), 'تعديل البيانات'),
            h('button', {
              className: 'btn sm danger outline',
              style: { width: '100%' },
              disabled: deletingDoctorId === d.id,
              onClick: () => deleteDoctorMember(d),
            }, deletingDoctorId === d.id ? 'جاري الحذف...' : [h(Icons.Trash, { key: 'icon', size: 13 }), 'حذف الطبيب']),
          ),
        );
        }),
      ),
      h('div', { className:'card p-16 mb-16 flex gap-8 ai-c' },
        h('div', { style: { flex: 1, position: 'relative' } },
          h('input', { className:'input', placeholder:'بحث في الموظفين بالاسم أو الدور أو الهاتف...', value: query, onChange: e => setQuery(e.target.value), style: { paddingInlineEnd: 40 } }),
          h('span', { style: { position:'absolute', insetInlineEnd: 12, top:'50%', transform:'translateY(-50%)', color:'var(--text-tertiary)' } }, h(Icons.Search, { size: 16 })),
        ),
        h('button', { className:'btn outline', onClick: () => openStaffModal() }, h(Icons.UserPlus, { size: 15 }), 'إضافة'),
      ),
      h('div', { className: 'card', style: { overflowX: 'auto' } },
        h('table', { className: 'data-table', style: { minWidth: 760 } },
          h('thead', null, h('tr', null, ['الاسم', 'الدور / الصلاحية', 'الهاتف', 'الوردية', 'الإجراءات'].map((t, i) => h('th', { key: i }, t)))),
          h('tbody', null,
            filteredStaff.length ? filteredStaff.map(s => h('tr', { key: s.id },
              h('td', null, h('div', { className: 'flex ai-c gap-12' },
                h('div', { className: 'avatar sm' }, s.avatar || (s.name || '?').slice(0, 2)),
                h('div', { style: { fontWeight: 700 } }, s.name),
              )),
              h('td', null, h('span', { className:'chip' }, s.role || 'موظف')),
              h('td', { style: { direction: 'ltr', textAlign: 'right' } }, s.phone || '—'),
              h('td', null, h('span', { className: 'chip outline' }, s.shift || '—')),
              h('td', null, h('div', { className:'flex gap-8' },
                h('button', { className:'btn sm outline', onClick: () => openStaffModal(s) }, h(Icons.Edit, { size: 13 }), 'تعديل'),
                h('button', { className:'btn sm danger outline', disabled: deletingStaffId === s.id, onClick: () => deleteStaffMember(s) }, deletingStaffId === s.id ? '...' : h(Icons.Trash, { size: 13 }), 'حذف'),
              )),
            )) : h('tr', null, h('td', { colSpan: 5, style: { textAlign:'center', padding: 28, color:'var(--text-tertiary)' } }, query ? 'لا توجد نتائج بحث' : 'لا يوجد موظفون مساعدين بعد')),
          ),
        ),
      ),
    ),
  );
}

// ==================== Reports ====================
// ─────────────────────────────────────────────────────────────
// Simple inline bar-chart (pure SVG, no deps)
// ─────────────────────────────────────────────────────────────
// Horizontal bar chart — click-to-filter + native title tooltips
function SimpleBarChart({ items, valueKey='value', labelKey='name', color='var(--accent)', height=8,
                          onItemClick, activeValue, fmtVal, secondaryKey, secondaryLabel }) {
  if (!items || !items.length) return h('div',{style:{color:'var(--text-tertiary)',fontSize:13,textAlign:'center',padding:'24px 0'}},'لا توجد بيانات');
  const max = Math.max(...items.map(i=>Number(i[valueKey])||0), 1);
  return h('div', {style:{display:'flex',flexDirection:'column',gap:6}},
    items.map((item,i) => {
      const val      = Number(item[valueKey])||0;
      const lbl      = item[labelKey];
      const isActive = activeValue != null && String(lbl) === String(activeValue);
      const isDim    = activeValue != null && !isActive;
      const display  = fmtVal ? fmtVal(val) : (val > 999 ? window.fmtEGP(val) : val);
      const secondary = secondaryKey && item[secondaryKey] != null
        ? ' · ' + (secondaryLabel||'') + item[secondaryKey] : '';
      return h('div', {
        key:i, onClick:()=>onItemClick?.(item),
        title:`${lbl}: ${display}${secondary}`,
        style:{
          cursor: onItemClick ? 'pointer' : 'default',
          opacity: isDim ? 0.28 : 1,
          transition: 'opacity 0.18s',
          borderRadius: 6, padding: '2px 6px',
          background: isActive ? 'var(--accent-soft)' : 'transparent',
          outline: isActive ? '1.5px solid var(--accent)' : 'none',
        }
      },
        h('div',{style:{display:'flex',justifyContent:'space-between',fontSize:12,marginBottom:3,gap:4}},
          h('span',{style:{fontWeight:isActive?800:600,overflow:'hidden',textOverflow:'ellipsis',
            whiteSpace:'nowrap',maxWidth:'65%',color:isActive?color:'var(--text-primary)'}}, lbl),
          h('div',{style:{display:'flex',gap:6,alignItems:'center',flexShrink:0}},
            secondary ? h('span',{style:{fontSize:10,color:'var(--text-tertiary)'}},secondary) : null,
            h('span',{style:{fontWeight:800,color}}, display),
          ),
        ),
        h('div',{style:{background:'var(--bg-subtle)',borderRadius:99,height,overflow:'hidden'}},
          h('div',{style:{
            width:Math.max(3,val/max*100)+'%', height:'100%',
            background:color, borderRadius:99, transition:'width 0.35s', opacity:0.9,
          }}),
        ),
      );
    }),
  );
}

function DonutChart({ items, valueKey='value', labelKey='name', colorKey='color', size=180, thickness=18, centerLabel, centerValue, fmtVal }) {
  const rows = (items || []).filter(item => (Number(item[valueKey]) || 0) > 0);
  if (!rows.length) return h('div',{style:{color:'var(--text-tertiary)',fontSize:13,textAlign:'center',padding:'24px 0'}},'لا توجد بيانات');
  const total = rows.reduce((sum, item) => sum + (Number(item[valueKey]) || 0), 0);
  const radius = (size / 2) - (thickness / 2) - 4;
  const circumference = 2 * Math.PI * radius;
  let offset = 0;

  return h('div', { style:{ display:'grid', gridTemplateColumns:'minmax(160px, 190px) 1fr', gap:18, alignItems:'center' } },
    h('div', { style:{ position:'relative', width:size, height:size, margin:'0 auto' } },
      h('svg', { viewBox:`0 0 ${size} ${size}`, width:size, height:size, style:{ display:'block' } },
        h('circle', {
          cx:size / 2,
          cy:size / 2,
          r:radius,
          fill:'none',
          stroke:'var(--bg-subtle)',
          strokeWidth:thickness,
        }),
        rows.map((item, index) => {
          const value = Number(item[valueKey]) || 0;
          const length = total > 0 ? (value / total) * circumference : 0;
          const dashOffset = -offset;
          offset += length;
          return h('circle', {
            key:item[labelKey] || index,
            cx:size / 2,
            cy:size / 2,
            r:radius,
            fill:'none',
            stroke:item[colorKey] || 'var(--accent)',
            strokeWidth:thickness,
            strokeLinecap:'butt',
            strokeDasharray:`${length} ${Math.max(0, circumference - length)}`,
            strokeDashoffset:dashOffset,
            transform:`rotate(-90 ${size / 2} ${size / 2})`,
          });
        }),
      ),
      h('div', {
        style:{
          position:'absolute',
          inset:0,
          display:'flex',
          flexDirection:'column',
          alignItems:'center',
          justifyContent:'center',
          pointerEvents:'none',
          textAlign:'center',
        }
      },
        h('div', { style:{ fontSize:12, color:'var(--text-tertiary)', marginBottom:4 } }, centerLabel || 'الإجمالي'),
        h('div', { style:{ fontSize:24, fontWeight:900, color:'var(--text-primary)' } }, centerValue),
      ),
    ),
    h('div', { style:{ display:'flex', flexDirection:'column', gap:10 } },
      rows.map((item, index) => {
        const value = Number(item[valueKey]) || 0;
        const percentage = total > 0 ? Math.round((value / total) * 100) : 0;
        const display = fmtVal ? fmtVal(value) : String(value);
        return h('div', {
          key:item[labelKey] || index,
          style:{
            display:'grid',
            gridTemplateColumns:'12px 1fr auto',
            gap:10,
            alignItems:'center',
            padding:'8px 10px',
            border:'1px solid var(--border)',
            borderRadius:12,
            background:'var(--card-bg)',
          }
        },
          h('span', { style:{ width:12, height:12, borderRadius:999, background:item[colorKey] || 'var(--accent)', display:'inline-block' } }),
          h('div', null,
            h('div', { style:{ fontWeight:700, fontSize:13 } }, item[labelKey]),
            h('div', { style:{ fontSize:11, color:'var(--text-tertiary)', marginTop:2 } }, `${percentage}% من الإجمالي`),
          ),
          h('div', { style:{ fontWeight:800, color:'var(--text-primary)', whiteSpace:'nowrap' } }, display),
        );
      }),
    ),
  );
}

// Grouped weekly revenue chart — clickable bars, semantic paid-bar colors, grid lines
function WeeklyRevenueChart({ weeks, onBarClick, activeWeekIdx }) {
  if (!weeks || !weeks.length) return null;
  const maxVal = Math.max(...weeks.map(w=>Math.max(w.revenue||0,w.paid||0)),1);
  const BAR=20, GAP=4, CH=110, TOP=18, LBL=14;
  const colW = BAR*2+GAP+10;
  const W = weeks.length*colW;
  const H = CH+TOP+LBL;
  const REV_COLOR = '#3b82f6';   // blue — إيراد (استحقاق)
  const PAID_COLOR = '#22c55e';  // green — تحصيل
  const fmtLbl = v => v>=1000?(v/1000).toFixed(1).replace('.0','')+'k':String(v);
  return h('svg', {
    viewBox:`0 0 ${W} ${H}`,
    style:{width:'100%',display:'block',overflow:'visible',cursor:onBarClick?'pointer':'default'},
    preserveAspectRatio:'xMidYMid meet',
  },
    // grid lines
    [0.25,0.5,0.75,1].map((f,gi)=>h('line',{key:'g'+gi,
      x1:0,y1:TOP+CH*(1-f),x2:W,y2:TOP+CH*(1-f),
      stroke:'var(--border)',strokeWidth:f===1?0.8:0.4,strokeDasharray:f===1?'none':'3 4'})),
    weeks.map((w,i) => {
      const x=i*colW;
      const revH  = Math.max(3,(w.revenue||0)/maxVal*CH);
      const paidH = Math.max(3,(w.paid||0)/maxVal*CH);
      const isActive = activeWeekIdx===i;
      const isDim    = activeWeekIdx!=null&&!isActive;
      const tip = `أسبوع ${w.label}\nالاستحقاق: ${window.fmtEGP(w.revenue)}\nالتحصيل: ${window.fmtEGP(w.paid)}`;
      return h('g',{key:i,onClick:()=>onBarClick?.(i,w),
        opacity:isDim?0.22:1,style:{transition:'opacity 0.18s'}},
        h('rect',{x:x-2,y:0,width:colW,height:H,fill:'transparent'}),
        h('title',null,tip),
        isActive&&h('rect',{x:x-3,y:1,width:colW+2,height:H-2,rx:5,fill:REV_COLOR,fillOpacity:0.07,stroke:REV_COLOR,strokeWidth:0.8,strokeOpacity:0.3}),
        // Revenue bar (blue)
        h('rect',{x,y:CH+TOP-revH,width:BAR,height:revH,rx:3,fill:REV_COLOR,fillOpacity:isActive?0.75:0.35}),
        // Paid bar (green)
        h('rect',{x:x+BAR+GAP,y:CH+TOP-paidH,width:BAR,height:paidH,rx:3,fill:PAID_COLOR,fillOpacity:isActive?1:0.85}),
        // Revenue label above bar
        w.revenue>0&&h('text',{x:x+BAR/2,y:CH+TOP-revH-3,
          textAnchor:'middle',fontSize:6,fill:REV_COLOR,fontWeight:700,fillOpacity:isActive?1:0.7},
          fmtLbl(w.revenue)),
        // Paid label above bar
        w.paid>0&&h('text',{x:x+BAR+GAP+BAR/2,y:CH+TOP-paidH-3,
          textAnchor:'middle',fontSize:6.5,fill:PAID_COLOR,fontWeight:800},
          fmtLbl(w.paid)),
        // Week label
        h('text',{x:x+BAR,y:CH+TOP+11,textAnchor:'middle',fontSize:7,
          fill:isActive?REV_COLOR:'var(--text-tertiary)',fontWeight:isActive?800:500}, w.label),
      );
    }),
  );
}

// ─────────────────────────────────────────────────────────────
// HoverTooltip — rich animated tooltip on hover
// ─────────────────────────────────────────────────────────────
function HoverTooltip({ children, lines = [], color = 'var(--text-primary)', tag = 'div' }) {
  const [vis, setVis] = useState(false);
  const [coord, setCoord] = useState({ x: 0, y: 0 });
  if (!lines.length) return h(Fragment, null, children);
  const show = (e) => { setCoord({ x: e.clientX, y: e.clientY }); setVis(true); };
  const move = (e) => setCoord({ x: e.clientX, y: e.clientY });
  const hide = () => setVis(false);
  // For table rows use tag='tr' — no wrapping div, handlers go directly on the tag
  const wrapperProps = { onMouseEnter: show, onMouseMove: move, onMouseLeave: hide };
  const wrapper = tag === 'tr'
    ? React.cloneElement(children, wrapperProps)
    : h(tag, { ...wrapperProps, style: { display: 'contents' } }, children);
  return h(Fragment, null,
    wrapper,
    vis && h('div', {
      style: {
        position: 'fixed', left: coord.x + 14, top: coord.y - 10,
        zIndex: 9999, pointerEvents: 'none',
        background: 'var(--bg)', border: '1px solid var(--border)',
        borderRadius: 10, padding: '8px 12px',
        boxShadow: '0 8px 32px rgba(0,0,0,0.18)',
        minWidth: 140, maxWidth: 240,
        animation: 'ttIn 0.12s cubic-bezier(0.34,1.56,0.64,1)',
      }
    },
      h('style', null, `@keyframes ttIn{from{opacity:0;transform:scale(0.88) translateY(4px)}to{opacity:1;transform:scale(1) translateY(0)}}`),
      lines.map((ln, i) => h('div', {
        key: i,
        style: {
          fontSize: i === 0 ? 12 : 11,
          fontWeight: i === 0 ? 700 : 400,
          color: i === 0 ? color : 'var(--text-secondary)',
          marginBottom: i < lines.length - 1 ? 3 : 0,
          lineHeight: 1.4,
        }
      }, ln)),
    ),
  );
}

// ─────────────────────────────────────────────────────────────
// FlexibleRevenueChart — daily/weekly/monthly/yearly, scrollable
// ─────────────────────────────────────────────────────────────
function FlexibleRevenueChart({ invoices, dateFrom, dateTo }) {
  const [frame, setFrame] = useState('weekly');
  const [hovered, setHovered] = useState(null);

  const data = useMemo(() => {
    const from = dateFrom || new Date(Date.now() - 30*24*60*60*1000).toISOString().slice(0,10);
    const to   = dateTo   || new Date().toISOString().slice(0,10);
    const filtered = (invoices||[]).filter(inv => inv.date >= from && inv.date <= to);
    const MONTHS = ['يناير','فبراير','مارس','أبريل','مايو','يونيو','يوليو','أغسطس','سبتمبر','أكتوبر','نوفمبر','ديسمبر'];

    if (frame === 'daily') {
      const buckets = {};
      let d = new Date(from); const end = new Date(to);
      while (d <= end) {
        const ds = d.toISOString().slice(0,10);
        buckets[ds] = 0;
        d.setDate(d.getDate()+1);
      }
      filtered.forEach(inv => { if (buckets[inv.date] !== undefined) buckets[inv.date] += (inv.total||0); });
      return Object.entries(buckets).map(([ds, rev]) => ({
        label: ds.slice(5).replace('-','/'), full: ds, revenue: Math.round(rev),
      }));
    }

    if (frame === 'weekly') {
      const wm = {};
      filtered.forEach(inv => {
        const d = new Date(inv.date); const ws = new Date(d);
        ws.setDate(d.getDate() - d.getDay());
        const key = ws.toISOString().slice(0,10);
        if (!wm[key]) wm[key] = 0; wm[key] += (inv.total||0);
      });
      return Object.entries(wm).sort(([a],[b])=>a<b?-1:1).map(([ws,rev])=>({
        label: ws.slice(5).replace('-','/'), full: ws, revenue: Math.round(rev),
      }));
    }

    if (frame === 'monthly') {
      const mm = {};
      filtered.forEach(inv => {
        const m = inv.date.slice(0,7);
        if (!mm[m]) mm[m] = 0; mm[m] += (inv.total||0);
      });
      return Object.entries(mm).sort(([a],[b])=>a<b?-1:1).map(([m,rev])=>{
        const [yr, mo] = m.split('-');
        return { label: MONTHS[parseInt(mo)-1].slice(0,3)+' '+yr.slice(2), full: m, revenue: Math.round(rev) };
      });
    }

    if (frame === 'yearly') {
      const ym = {};
      filtered.forEach(inv => {
        const y = inv.date.slice(0,4);
        if (!ym[y]) ym[y] = 0; ym[y] += (inv.total||0);
      });
      return Object.entries(ym).sort(([a],[b])=>a<b?-1:1).map(([y,rev])=>({
        label: y, full: y, revenue: Math.round(rev),
      }));
    }
    return [];
  }, [invoices, dateFrom, dateTo, frame]);

  const maxRev = Math.max(...data.map(d=>d.revenue), 1);
  const n = data.length;
  const barW = n <= 8 ? 44 : n <= 20 ? 32 : n <= 40 ? 22 : 16;
  const gap  = n <= 8 ? 14 : n <= 20 ? 10 : 6;
  const colW = barW + gap;
  const chartH = 130;
  const totalW = Math.max(n * colW + gap, 300);
  const fmtLbl = v => v >= 1000 ? (v/1000).toFixed(1).replace('.0','')+'k' : String(v);

  return h('div', null,
    // Frame selector
    h('div', { style: { display: 'flex', gap: 6, marginBottom: 12 } },
      [['daily','يومي'],['weekly','أسبوعي'],['monthly','شهري'],['yearly','سنوي']].map(([val, lbl]) =>
        h('button', {
          key: val, onClick: () => { setFrame(val); setHovered(null); },
          style: {
            padding: '3px 11px', fontSize: 11, fontWeight: frame===val?800:500,
            border: '1px solid '+(frame===val?'var(--accent)':'var(--border)'),
            borderRadius: 20, cursor: 'pointer',
            background: frame===val?'var(--accent-soft)':'transparent',
            color: frame===val?'var(--accent)':'var(--text-tertiary)',
            transition: 'all 0.15s',
          },
        }, lbl)
      ),
    ),
    // Chart
    data.length === 0
      ? h('div', { style: { color:'var(--text-tertiary)', fontSize:13, textAlign:'center', padding:'24px 0' } }, 'لا توجد بيانات في هذه الفترة')
      : h('div', { style: { overflowX:'auto', overflowY:'hidden' } },
          h('div', { style: { minWidth: totalW, position: 'relative' } },
            h('svg', { width: totalW, height: chartH + 20, style: { display:'block', overflow:'visible' } },
              // Grid lines
              [0.25,0.5,0.75,1].map((pct,i) =>
                h('line', { key:i, x1:0, y1:Math.round(chartH*(1-pct)), x2:totalW, y2:Math.round(chartH*(1-pct)),
                  stroke:'var(--border)', strokeWidth:0.5, strokeDasharray:'3 3' })
              ),
              data.map((d, i) => {
                const x = i * colW + gap/2;
                const barH = Math.max(3, (d.revenue / maxRev) * (chartH - 16));
                const y = chartH - barH;
                const isHov = hovered === i;
                return h('g', { key: i,
                  onMouseEnter: () => setHovered(i),
                  onMouseLeave: () => setHovered(null),
                  style: { cursor: 'default' },
                },
                  h('rect', {
                    x, y: 0, width: barW, height: chartH,
                    fill: 'transparent',
                  }),
                  h('rect', {
                    x, y, width: barW, height: barH, rx: 4,
                    fill: 'var(--accent)',
                    opacity: isHov ? 1 : 0.72,
                    style: { transition: 'opacity 0.12s, y 0.25s, height 0.25s' },
                  }),
                  isHov && h('rect', {
                    x: x-2, y: y-2, width: barW+4, height: barH+4, rx: 5,
                    fill: 'none', stroke: 'var(--accent)', strokeWidth: 1.5, opacity: 0.5,
                  }),
                  barH > 18 && h('text', {
                    x: x+barW/2, y: y-4, textAnchor:'middle',
                    fontSize: 8, fill:'var(--accent)', fontWeight:700,
                  }, fmtLbl(d.revenue)),
                  h('text', {
                    x: x+barW/2, y: chartH+13, textAnchor:'middle',
                    fontSize: barW > 28 ? 9 : 7,
                    fill: isHov ? 'var(--accent)' : 'var(--text-tertiary)',
                    fontWeight: isHov ? 700 : 400,
                  }, d.label),
                );
              }),
            ),
            // Tooltip popup
            hovered !== null && data[hovered] && h('div', {
              style: {
                position:'absolute', left: hovered*colW + gap/2 + barW/2,
                top: chartH - Math.max(3,(data[hovered].revenue/maxRev)*(chartH-16)) - 42,
                transform: 'translateX(-50%)',
                background:'var(--bg)', border:'1px solid var(--border)',
                borderRadius:8, padding:'5px 9px',
                boxShadow:'0 4px 16px rgba(0,0,0,0.14)',
                fontSize:11, fontWeight:700, color:'var(--accent)',
                pointerEvents:'none', whiteSpace:'nowrap', zIndex:10,
                animation:'ttIn 0.12s cubic-bezier(0.34,1.56,0.64,1)',
              }
            }, window.fmtEGP(data[hovered].revenue)),
          ),
        ),
  );
}

// ─────────────────────────────────────────────────────────────
// ExpenseDrillDown — clickable expense categories with detail
// ─────────────────────────────────────────────────────────────
function ExpenseDrillDown({ categories, expenses, purchases, loading }) {
  const [expanded, setExpanded] = useState(null);
  if (loading) return h('div',{style:{color:'var(--text-tertiary)',fontSize:13}},'جاري التحميل...');
  if (!categories.length) return h('div',{style:{color:'var(--text-tertiary)',fontSize:13,textAlign:'center',paddingTop:16}},'لا توجد مصروفات في هذه الفترة');

  const total = categories.reduce((s,c)=>s+c.value,0);
  const MAX_COLOR = 'var(--danger)';

  return h('div', { style:{display:'flex',flexDirection:'column',gap:4} },
    categories.map((cat, i) => {
      const isOpen = expanded === cat.name;
      const pct = total > 0 ? cat.value/total*100 : 0;
      const isMaterial = cat.name.includes('ماتريال');

      // Detail rows
      const detailRows = isMaterial
        ? purchases.map(p => ({
            label: p.supplier_name || p.supplier || 'مورد',
            sub: window.fmtDate(p.date),
            amount: Number(p.total)||0,
            items: Array.isArray(p.items) ? p.items : [],
          })).sort((a,b)=>b.amount-a.amount)
        : expenses.filter(e => {
            const cls = classifyAccountingExpenseCategory(e.category);
            if (cat.name.includes('راتب')) return cls==='salaries';
            if (cat.name.includes('إيجار')) return cls==='rent';
            if (cat.name.includes('صيان')) return cls==='maintenance';
            return cls==='other';
          }).map(e => ({
            label: e.description || e.category || 'مصروف',
            sub: window.fmtDate(e.date),
            amount: parseFloat(e.amount)||0,
            items: [],
          })).sort((a,b)=>b.amount-a.amount);

      return h('div', { key:cat.name },
        // Category row (clickable)
        h(HoverTooltip, {
          lines: [cat.name, window.fmtEGP(cat.value), Math.round(pct)+'% من إجمالي المصروفات'],
          color: MAX_COLOR,
        },
          h('div', {
            onClick: () => setExpanded(isOpen ? null : cat.name),
            style: {
              cursor:'pointer', borderRadius:6, padding:'4px 6px',
              background: isOpen ? 'var(--danger-soft)' : 'transparent',
              outline: isOpen ? '1.5px solid var(--danger)' : 'none',
              transition: 'background 0.15s',
            }
          },
            h('div', { style:{display:'flex',justifyContent:'space-between',fontSize:12,marginBottom:3,gap:4} },
              h('span', { style:{fontWeight:isOpen?800:600,color:isOpen?MAX_COLOR:'var(--text-primary)',
                display:'flex',alignItems:'center',gap:4} },
                h('span',{style:{fontSize:9,transition:'transform 0.2s',display:'inline-block',
                  transform:isOpen?'rotate(90deg)':'rotate(0deg)'}},'▶'),
                cat.name,
              ),
              h('div', { style:{display:'flex',gap:8,alignItems:'center',flexShrink:0} },
                h('span',{style:{fontSize:10,color:'var(--text-tertiary)'}},'('+Math.round(pct)+'%)'),
                h('span',{style:{fontWeight:800,color:MAX_COLOR}},window.fmtEGP(cat.value)),
              ),
            ),
            h('div',{style:{background:'var(--bg-subtle)',borderRadius:99,height:8,overflow:'hidden'}},
              h('div',{style:{width:Math.max(3,pct)+'%',height:'100%',
                background:MAX_COLOR,borderRadius:99,transition:'width 0.35s',opacity:0.9}}),
            ),
          ),
        ),

        // Expanded detail
        isOpen && h('div', {
          style:{
            marginTop:4, marginBottom:6, borderRadius:8,
            border:'1px solid var(--border)', overflow:'hidden',
            animation:'ttIn 0.15s ease',
          }
        },
          detailRows.length === 0
            ? h('div',{style:{padding:'12px 16px',fontSize:12,color:'var(--text-tertiary)'}},'لا تفاصيل')
            : h('div',{style:{maxHeight:260,overflowY:'auto'}},
                detailRows.map((row, ri) => h('div', { key:ri,
                  style:{borderBottom:'1px solid var(--border)',padding:'8px 12px',
                    ':last-child':{borderBottom:'none'}}
                },
                  h('div',{style:{display:'flex',justifyContent:'space-between',alignItems:'flex-start'}},
                    h('div',{style:{flex:1,minWidth:0}},
                      h('div',{style:{fontSize:12,fontWeight:600,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}},row.label),
                      h('div',{style:{fontSize:10,color:'var(--text-tertiary)',marginTop:2}},row.sub),
                    ),
                    h('div',{style:{fontWeight:800,fontSize:12,color:MAX_COLOR,flexShrink:0,marginRight:8}},
                      window.fmtEGP(row.amount)),
                  ),
                  // Purchase invoice items
                  row.items.length > 0 && h('div',{style:{marginTop:6,paddingTop:6,borderTop:'1px dashed var(--border)'}},
                    row.items.map((item, ii) => h('div',{key:ii,
                      style:{display:'flex',justifyContent:'space-between',fontSize:10,
                        color:'var(--text-secondary)',padding:'1px 0'}
                    },
                      h('span',null, item.name||item.item_name||'صنف'),
                      h('span',null,
                        (item.quantity||item.qty||1)+' × '+(item.unit||'')+'  ',
                        h('strong',null, window.fmtEGP(item.unit_price||item.price||0)),
                      ),
                    )),
                  ),
                )),
              ),
        ),
      );
    }),
  );
}

// ─────────────────────────────────────────────────────────────
// REPORTS — Full analytics dashboard with cross-filtering
// ─────────────────────────────────────────────────────────────
function Reports() {
  const { doctors, invoices, appointments, patients, services, sessions, inventory, expenses: ctxExpenses, clinicId, clinicName } = useContext(AppContext);

  // ── Tabs & date range ──
  const [tab, setTab]           = useState('financial');
  const [dateOpen, setDateOpen] = useState(false);
  const [activePreset, setActivePreset] = useState('current_month');
  const [dateFrom, setDateFrom] = useState(() => {
    const d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 1).toISOString().split('T')[0];
  });
  const [dateTo, setDateTo] = useState(() => new Date().toISOString().split('T')[0]);

  // ── Cross-filter state ──
  const [activeFilter, setActiveFilter] = useState(null);
  // { type: 'doctor'|'service', value: string, label: string }
  const [activeWeekIdx, setActiveWeekIdx] = useState(null);
  const [expandedDay, setExpandedDay] = useState(null);
  const toggleFilter = (type, value, label) => {
    setActiveFilter(prev => prev && prev.type === type && prev.value === value ? null : { type, value, label });
  };

  // ── Expenses: always fetch directly to avoid context-timing issues ──
  const [loadedExpenses, setLoadedExpenses] = useState([]);
  const [loadedPurchases, setLoadedPurchases] = useState([]);
  const [expLoading, setExpLoading] = useState(false);
  useEffect(() => {
    let cancelled = false;
    if (!clinicId) {
      setLoadedExpenses([]);
      setLoadedPurchases([]);
      setExpLoading(false);
      return () => { cancelled = true; };
    }
    setExpLoading(true);
    (async () => {
      try {
        const [{ data, error }, purchases] = await Promise.all([
          SB.from('expenses').select('*').eq('clinic_id', clinicId).order('date', { ascending: false }),
          DB.getPurchaseInvoices(clinicId).catch(() => []),
        ]);
        if (cancelled) return;
        if (!error) setLoadedExpenses(data || []);
        setLoadedPurchases(Array.isArray(purchases) ? purchases : []);
      } finally {
        if (!cancelled) setExpLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [clinicId]);
  // Prefer fresh fetch; fall back to AppContext if fetch hasn't completed
  const allExpensesRaw = loadedExpenses.length > 0 ? loadedExpenses
                       : (Array.isArray(ctxExpenses) ? ctxExpenses : []);
  const allPurchasesRaw = Array.isArray(loadedPurchases) ? loadedPurchases : [];

  // ── Raw data ──
  const allDoctors  = (doctors   && doctors.length)      ? doctors   : (window.DOCTORS        || []);
  const allInvoices = (invoices  && invoices.length)     ? invoices  : (window.INVOICES        || []);
  const allAppts    = (appointments && appointments.length) ? appointments : (window.APPOINTMENTS || []);
  const allPatients = (patients  && patients.length)     ? patients  : (window.PATIENTS        || []);
  const allInv      = (inventory && inventory.length)    ? inventory : (window.INVENTORY       || []);

  // ── Date-range filter ──
  const fInv  = allInvoices.filter(i => (!dateFrom||i.date>=dateFrom) && (!dateTo||i.date<=dateTo));
  const fAppt = allAppts.filter(a => (!dateFrom||a.date>=dateFrom) && (!dateTo||a.date<=dateTo));
  const fExp  = allExpensesRaw.filter(e => (!dateFrom||e.date>=dateFrom) && (!dateTo||e.date<=dateTo));
  const fPurch = allPurchasesRaw.filter(p => (!dateFrom||p.date>=dateFrom) && (!dateTo||p.date<=dateTo));

  // ── Cross-filter application ──
  const fInvF = useMemo(() => {
    if (!activeFilter) return fInv;
    if (activeFilter.type === 'doctor')  return fInv.filter(inv => {
      const meta = typeof inv.notes === 'object' ? (inv.notes||{}) : {};
      return (meta.doctorName || inv.doctorName) === activeFilter.value;
    });
    if (activeFilter.type === 'service') return fInv.filter(inv =>
      inv.items?.some(item => item.name === activeFilter.value)
    );
    return fInv;
  }, [fInv, activeFilter]);

  const fApptF = useMemo(() => {
    if (!activeFilter) return fAppt;
    if (activeFilter.type === 'doctor')  return fAppt.filter(a => {
      const doc = allDoctors.find(d => String(d.id) === String(a.doctorId || a.doctor_id));
      return (doc?.name || a.doctorName || a.doctor) === activeFilter.value;
    });
    return fAppt;
  }, [fAppt, activeFilter, allDoctors]);

  // ═══ FINANCIAL ═══
  const totalRevenue  = fInvF.reduce((s,i) => s+(i.total||0), 0);
  const totalPaid     = fInvF.reduce((s,i) => s+(i.paid||0),  0);
  const totalDebt     = totalRevenue - totalPaid;
  const collectRate   = totalRevenue > 0 ? totalPaid/totalRevenue*100 : 0;
  const totalExpenses = fExp.reduce((s,e) => s+(parseFloat(e.amount)||0), 0) + fPurch.reduce((s,p) => s + (Number(p.total) || 0), 0);
  const netBalance    = totalPaid - totalExpenses;
  const collectColor  = collectRate>=80 ? 'var(--success)' : collectRate>=60 ? 'var(--warning)' : 'var(--danger)';
  const netColor      = netBalance>=0 ? 'var(--success)' : 'var(--danger)';

  // Operation counts
  const doneAppts    = fApptF.filter(a => a.status==='done').length;
  const activePatients = new Set(fApptF.filter(a=>a.status==='done').map(a=>String(a.patientId||a.patient||'').trim()).filter(Boolean)).size;
  const totalSvcCount  = fInvF.reduce((s,i) => (i.items||[]).reduce((ss,it) => ss+(parseInt(it.qty)||1),s), 0);

  // Doctor revenue
  const doctorRevMap = useMemo(() => {
    const map = {};
    fInvF.forEach(inv => {
      const meta  = typeof inv.notes==='object' ? (inv.notes||{}) : {};
      const dName = meta.doctorName || inv.doctorName || 'غير محدد';
      const doc   = allDoctors.find(d => d.name===dName);
      if (!map[dName]) map[dName]={ name:dName, revenue:0, paid:0, invoices:0, rate:Number(doc?.commissionRate ?? doc?.commission_rate) || 0.30 };
      map[dName].revenue  += (inv.total||0);
      map[dName].paid     += (inv.paid||0);
      map[dName].invoices++;
    });
    return Object.values(map).sort((a,b) => b.paid-a.paid);
  }, [fInvF, allDoctors]);
  const totalCommissions = doctorRevMap.reduce((s,d) => s+d.paid*d.rate, 0);

  // Weekly chart (last 8 weeks)
  const weeklyData = useMemo(() =>
    Array.from({length:8}, (_,i) => {
      const wEnd=new Date(); wEnd.setDate(wEnd.getDate()-i*7);
      const wSt=new Date(wEnd); wSt.setDate(wSt.getDate()-6);
      const ws=wSt.toISOString().split('T')[0];
      const we=wEnd.toISOString().split('T')[0];
      const wInv = fInvF.filter(inv=>inv.date>=ws&&inv.date<=we);
      return {
        label: ws.slice(5).replace('-','/'),
        revenue: Math.round(wInv.reduce((s,inv)=>s+(inv.total||0),0)),
        paid:    Math.round(wInv.reduce((s,inv)=>s+(inv.paid||0),0)),
        ws, we,
      };
    }).reverse()
  , [fInvF]);

  // Service stats
  const serviceStats = useMemo(() => {
    const map = {};
    fInvF.forEach(inv => {
      (inv.items||[]).forEach(item => {
        const key=item.service_id||item.name;
        if (!map[key]) map[key]={name:item.name||'—',revenue:0,count:0};
        const lineTotal=(parseFloat(item.price)||0)*(parseInt(item.qty)||1)-(parseFloat(item.discount)||0);
        map[key].revenue+=lineTotal;
        map[key].count  +=parseInt(item.qty)||1;
      });
    });
    return Object.values(map)
      .map(s=>({...s, avgPrice:s.count>0?Math.round(s.revenue/s.count):0}))
      .sort((a,b)=>b.revenue-a.revenue).slice(0,20);
  }, [fInvF]);

  // Expense by category
  const expByCategory = useMemo(() => {
    const salaries = fExp
      .filter(exp => classifyAccountingExpenseCategory(exp.category) === 'salaries')
      .reduce((sum, exp) => sum + (parseFloat(exp.amount) || 0), 0);
    const rent = fExp
      .filter(exp => classifyAccountingExpenseCategory(exp.category) === 'rent')
      .reduce((sum, exp) => sum + (parseFloat(exp.amount) || 0), 0);
    const maintenance = fExp
      .filter(exp => classifyAccountingExpenseCategory(exp.category) === 'maintenance')
      .reduce((sum, exp) => sum + (parseFloat(exp.amount) || 0), 0);
    const other = fExp
      .filter(exp => classifyAccountingExpenseCategory(exp.category) === 'other')
      .reduce((sum, exp) => sum + (parseFloat(exp.amount) || 0), 0);
    const materials = fPurch.reduce((sum, purchase) => sum + (Number(purchase.total) || 0), 0);
    return [
      { name: 'الماتريال والمستلزمات', value: materials },
      { name: 'الرواتب', value: salaries },
      { name: 'الإيجار والمرافق', value: rent },
      { name: 'الصيانة والمعدات', value: maintenance },
      { name: 'مصاريف أخرى', value: other },
    ].filter(item => item.value > 0).sort((a,b)=>b.value-a.value);
  }, [fExp, fPurch]);

  // Daily breakdown (last 14 days or within date range)
  const dailyBreakdown = useMemo(() => {
    const days=[];
    for (let i=0;i<14;i++) {
      const d=new Date(); d.setDate(d.getDate()-i);
      const ds=d.toISOString().split('T')[0];
      if (dateFrom&&ds<dateFrom) break;
      if (dateTo&&ds>dateTo) continue;
      const dayInv  = fInvF.filter(inv=>inv.date===ds);
      const dayAppt = fApptF.filter(a=>a.date===ds&&a.status==='done');
      const dayPts  = new Set(dayAppt.map(a=>String(a.patientId||a.patient||'').trim()).filter(Boolean)).size;
      // Patient detail rows for Power BI table
      const patientRows = dayInv.map(inv => ({
        name: inv.patient || 'مريض',
        doctor: (typeof inv.notes==='object'?(inv.notes||{}):{})[`doctorName`] || inv.doctorName || '—',
        revenue: inv.total||0,
        paid: inv.paid||0,
        debt: Math.max(0,(inv.total||0)-(inv.paid||0)),
        status: inv.status||'',
      }));
      days.push({
        date:ds,
        label: i===0?'اليوم':i===1?'أمس':ds.slice(5).replace('-','/'),
        revenue: dayInv.reduce((s,inv)=>s+(inv.total||0),0),
        paid:   dayInv.reduce((s,inv)=>s+(inv.paid||0),0),
        invoices: dayInv.length,
        sessions: dayAppt.length,
        patients: dayPts,
        patientRows,
      });
    }
    return days;
  }, [fInvF, fApptF, dateFrom, dateTo]);

  // ═══ PATIENTS ═══
  const newPatients = allPatients.filter(p => {
    const d=(p.created_at||'').slice(0,10);
    return (!dateFrom||d>=dateFrom)&&(!dateTo||d<=dateTo);
  });
  const avgVisits = activePatients>0 ? doneAppts/activePatients : 0;

  const patientVisitMap = useMemo(() => {
    const map={};
    fApptF.filter(a=>a.status==='done').forEach(a=>{
      const key=String(a.patientId||a.patient||'').trim(); if(!key)return;
      if(!map[key]) map[key]={name:a.patient,visits:0,revenue:0,paid:0};
      map[key].visits++;
    });
    fInvF.forEach(inv=>{
      const key=String(inv.patientId||inv.patient||'').trim();
      if(map[key]){ map[key].revenue+=(inv.total||0); map[key].paid+=(inv.paid||0); }
    });
    return Object.values(map).sort((a,b)=>b.visits-a.visits).slice(0,20);
  }, [fApptF, fInvF]);

  const debtors = useMemo(() => {
    const map={};
    fInvF.filter(i=>(i.total||0)>(i.paid||0)).forEach(inv=>{
      const key=String(inv.patientId||inv.patient||'').trim()||inv.patient;
      if(!map[key]) map[key]={name:inv.patient||'—',debt:0};
      map[key].debt+=(inv.total-inv.paid);
    });
    return Object.values(map).sort((a,b)=>b.debt-a.debt).slice(0,12);
  }, [fInvF]);

  const genderCounts = useMemo(()=>{
    const m={ذكر:0,أنثى:0,'غير محدد':0};
    allPatients.forEach(p=>{
      const g=p.gender==='ذكر'||p.gender==='male'?'ذكر':p.gender==='أنثى'||p.gender==='female'?'أنثى':'غير محدد';
      m[g]++;
    });
    return m;
  },[allPatients]);
  const totalGender=Object.values(genderCounts).reduce((s,v)=>s+v,0);

  const ageGroups = useMemo(()=>{
    const g={'0–12':0,'13–25':0,'26–45':0,'46–60':0,'+60':0};
    allPatients.forEach(p=>{
      const age=parseInt(p.age)||0;
      if(age<=12)g['0–12']++;else if(age<=25)g['13–25']++;else if(age<=45)g['26–45']++;else if(age<=60)g['46–60']++;else g['+60']++;
    });
    return g;
  },[allPatients]);
  const totalAge=Object.values(ageGroups).reduce((s,v)=>s+v,0);

  const patientsByDoctor = useMemo(()=>{
    // Build patientId → doctorName from invoices (sorted newest-first by loadClinicData)
    const patDocFromInv = {};
    allInvoices.forEach(inv => {
      const pid = String(inv.patientId||inv.patient_id||'').trim();
      if (!pid || patDocFromInv[pid]) return;
      const meta = typeof inv.notes==='object' ? (inv.notes||{}) : {};
      const dName = (meta.doctorName||inv.doctorName||'').trim();
      if (dName) patDocFromInv[pid] = dName;
    });
    // Fallback: appointments
    allAppts.forEach(a => {
      const pid = String(a.patientId||a.patient_id||'').trim();
      if (!pid || patDocFromInv[pid]) return;
      const dName = (a.doctor||a.doctorName||'').trim();
      if (dName) patDocFromInv[pid] = dName;
    });
    const map={};
    allPatients.forEach(p=>{
      const doc = (
        patDocFromInv[String(p.id||'')] ||
        p.doctor ||
        p.profileData?.medicalRecord?.doctor ||
        ''
      ).trim() || 'غير محدد';
      if(!map[doc]) map[doc]={name:doc,value:0};
      map[doc].value++;
    });
    return Object.values(map).sort((a,b)=>b.value-a.value).slice(0,8);
  },[allPatients, allInvoices, allAppts]);

  const patientsByRegion = useMemo(()=>{
    const map={};
    allPatients.forEach(p=>{
      // location saved in profileData.medicalRecord.location (patient file's منطقة field)
      // patient.location from mapPatient is always '' (no location column in DB)
      const region = (p.profileData?.medicalRecord?.location || p.location || '').trim() || 'غير محدد';
      if(!map[region]) map[region]={name:region,value:0};
      map[region].value++;
    });
    return Object.values(map).sort((a,b)=>b.value-a.value).slice(0,8);
  },[allPatients]);

  // Low stock
  const lowStock = allInv.filter(i=>i.stock<i.minStock);

  // Date preset
  const applyPreset = (preset) => {
    if (!preset||preset==='all'){ setDateFrom(''); setDateTo(''); setActivePreset('all'); setActiveWeekIdx(null); return; }
    const {fromValue,toValue}=window.resolveDateRangePreset(preset);
    setDateFrom(fromValue); setDateTo(toValue); setActivePreset(preset); setDateOpen(false); setActiveWeekIdx(null);
  };

  const { DateRangeFilter } = window.Shell;
  const today = new Date().toISOString().split('T')[0];

  // KPI card
  const KpiCard = ({label,val,color,icon:Icon,soft,sub}) => h('div',{className:'card kpi'},
    h('div',{className:'flex jc-sb ai-c'},
      h('div',null,
        h('div',{className:'label'},label),
        h('div',{className:'value',style:{fontSize:17,color}},val),
        sub&&h('div',{style:{fontSize:10,color:'var(--text-tertiary)',marginTop:2}},sub),
      ),
      h('div',{className:'kpi-icon',style:{background:soft||'var(--bg-subtle)',color}}, h(Icon,{size:18})),
    ),
  );

  // ── Render ──
  return h('div',{className:'fade-in'},
    h('div',{className:'page-header'},
      h('div',null,
        h('div',{className:'page-title'},'📊 '+'التقارير والتحليلات'),
        h('div',{className:'page-subtitle'},'اضغط أي شريط للتصفية الفورية'+(activeFilter?' · 🔍 '+'تصفية نشطة':'')+ ' · '+(clinicName||'سِنان كلينيك')),
      ),
      h('button',{className:'btn outline',onClick:()=>window.print()}, h(Icons.Download,{size:15}),'طباعة'),
    ),

    h('div',{className:'page-content'},

      h(DateRangeFilter,{
        title:'فترة التقرير',subtitle:'اختر فترة جاهزة أو حدّد نطاقاً يدوياً',
        dateFrom,dateTo,open:dateOpen,activePreset,
        onToggle:()=>setDateOpen(d=>!d), onClose:()=>setDateOpen(false),
        onFromChange:v=>{setDateFrom(v);setActivePreset('custom');setActiveWeekIdx(null);},
        onToChange:v=>{setDateTo(v);setActivePreset('custom');setActiveWeekIdx(null);},
        onPresetSelect:applyPreset, onClear:()=>applyPreset('current_month'),
        onApply:()=>setDateOpen(false), buttonWidth:'min(280px,100%)',
      }),

      // Active filter banner
      activeFilter && h('div',{style:{
        display:'flex',alignItems:'center',gap:8,flexWrap:'wrap',
        padding:'8px 14px',borderRadius:'var(--radius)',
        background:'var(--accent-soft)',border:'1px solid var(--accent)',marginBottom:12,fontSize:13,
        animation:'filterBannerIn 0.22s cubic-bezier(0.34,1.56,0.64,1)',
      }},
      h('style',null,`
        @keyframes filterBannerIn {
          from { opacity:0; transform: scaleY(0.8) translateY(-6px); }
          to   { opacity:1; transform: scaleY(1) translateY(0); }
        }
        @keyframes filterBarPulse {
          0%   { outline-offset: 0px; }
          50%  { outline-offset: 3px; }
          100% { outline-offset: 0px; }
        }
      `),
        h('span',{style:{color:'var(--accent)',fontWeight:700}},'🔍 '+'تصفية حسب:'),
        h('span',{style:{fontWeight:800}},activeFilter.label),
        h('span',{style:{fontSize:11,color:'var(--text-tertiary)',background:'var(--bg-subtle)',padding:'2px 6px',borderRadius:4}},
          activeFilter.type==='doctor'?'طبيب':'خدمة'),
        h('button',{
          onClick:()=>setActiveFilter(null),
          className:'btn outline',style:{padding:'2px 10px',fontSize:12,marginRight:'auto'},
        },'مسح ×'),
      ),

      // Tabs
      h('div',{className:'tabs mb-16'},
        [['financial','💰 '+'المالية'],['patients','👥 '+'المرضى'],['services','⚕️ '+'الخدمات'],['daily','📋 '+'يومي']]
        .map(([v,l])=>h('button',{key:v,className:'tab'+(tab===v?' active':''),onClick:()=>setTab(v)},l)),
      ),

      // ══ TAB: FINANCIAL ══
      tab==='financial'&&h('div',null,

        // Main KPIs
        h('div',{className:'grid cols-4 mb-12'},
          [
            {label:'إجمالي الإيرادات', val:window.fmtEGP(totalRevenue),  color:'var(--accent)',  soft:'var(--accent-soft)',  icon:Icons.TrendingUp},
            {label:'إجمالي التحصيل',   val:window.fmtEGP(totalPaid),     color:'var(--success)', soft:'var(--success-soft)', icon:Icons.DollarSign},
            {label:'نسبة التحصيل',     val:window.fmtPercent(collectRate),color:collectColor,     soft:'var(--bg-subtle)',    icon:Icons.BarChart,
              sub:collectRate>=80?'✅ '+'ممتاز':collectRate>=60?'⚠️ '+'مقبول':'🚨 '+'يحتاج تدخل'},
            {label:'إجمالي المديونيات',val:window.fmtEGP(totalDebt),     color:'var(--danger)',  soft:'var(--danger-soft)',  icon:Icons.AlertTriangle},
          ].map((k,i)=>h(KpiCard,{key:i,...k})),
        ),

        // Secondary KPIs
        h('div',{className:'grid cols-3 mb-12'},
          [
            {label:'الرصيد الصافي',    val:expLoading?'...':window.fmtEGP(netBalance),    color:netColor,        icon:Icons.Calculator,
              sub:netBalance>=0?'ربح ✅':'خسارة 🚨'},
            {label:'إجمالي المصروفات', val:expLoading?'...':window.fmtEGP(totalExpenses), color:'var(--danger)',  icon:Icons.TrendingDown},
            {label:'عمولات الأطباء',   val:window.fmtEGP(Math.round(totalCommissions)),   color:'var(--warning)', icon:Icons.Briefcase},
          ].map((k,i)=>h(KpiCard,{key:i,...k})),
        ),

        // Operation KPIs
        h('div',{className:'grid cols-3 mb-16'},
          [
            {label:'مرضى نشطون',   val:activePatients,  color:'var(--info)',    icon:Icons.Users,    sub:'أكملوا زيارة في الفترة'},
            {label:'جلسات مكتملة', val:doneAppts,       color:'var(--accent)',  icon:Icons.Calendar, sub:'مواعيد تم إنجازها'},
            {label:'خدمات مقدمة',  val:totalSvcCount,   color:'var(--success)', icon:Icons.TrendingUp, sub:'وحدات من الفواتير'},
          ].map((k,i)=>h(KpiCard,{key:i,...k})),
        ),

        // Revenue chart (full width, flexible)
        h('div',{className:'card p-20',style:{marginBottom:16}},
          h('div',{style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:2}},
            h('div',null,
              h('div',{style:{fontWeight:800,fontSize:14}},'الإيرادات'),
              h('div',{style:{fontSize:11,color:'var(--text-tertiary)',marginTop:1}},
                'الفترة المحددة أعلاه · '+(dateFrom&&dateTo?window.fmtDate(dateFrom)+' → '+window.fmtDate(dateTo):'كل التواريخ')),
            ),
            h('div',{style:{fontSize:11,color:'var(--text-tertiary)',display:'flex',gap:8,alignItems:'center'}},
              h('span',{style:{background:'var(--accent-soft)',color:'var(--accent)',fontWeight:700,
                padding:'2px 8px',borderRadius:99,fontSize:11}},
                'إجمالي: '+window.fmtEGP(totalRevenue)),
            ),
          ),
          h(FlexibleRevenueChart,{ invoices:fInvF, dateFrom, dateTo }),
        ),

        // Doctors + Expense breakdown
        h('div',{style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16,marginBottom:16}},
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:10}},'الإيرادات حسب الطبيب'+' · '+'انقر للتصفية'),
            doctorRevMap.length===0
              ? h('div',{style:{fontSize:13,color:'var(--text-tertiary)',textAlign:'center',paddingTop:32}},'لا توجد بيانات — اربط الطبيب بالفاتورة')
              : h(SimpleBarChart,{
                  items:doctorRevMap, valueKey:'paid', labelKey:'name', color:'var(--accent)',
                  fmtVal:window.fmtEGP,
                  activeValue:activeFilter?.type==='doctor'?activeFilter.value:null,
                  onItemClick:d=>toggleFilter('doctor',d.name,d.name),
                  secondaryKey:'invoices', secondaryLabel:'',
                }),
          ),
          h('div',{className:'card p-20'},
            h('div',{style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}},
              h('div',{style:{fontWeight:800,fontSize:14}},'توزيع المصروفات'),
              h('div',{style:{fontSize:10,color:'var(--text-tertiary)'}},'انقر فئة لعرض التفاصيل'),
            ),
            h(ExpenseDrillDown,{
              categories:expByCategory,
              expenses:fExp,
              purchases:fPurch,
              loading:expLoading,
            }),
          ),
        ),

        // Top services
        h('div',{className:'card p-20',style:{marginBottom:16}},
          h('div',{style:{fontWeight:800,fontSize:14,marginBottom:10}},'أكثر الخدمات إيراداً'+' · '+'انقر للتصفية'),
          serviceStats.length===0
            ? h('div',{style:{color:'var(--text-tertiary)',fontSize:13,textAlign:'center',paddingTop:16}},'لا توجد فواتير')
            : h('div',{style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16}},
                h(SimpleBarChart,{
                  items:serviceStats.slice(0,8), valueKey:'revenue', labelKey:'name', color:'var(--success)',
                  fmtVal:window.fmtEGP,
                  activeValue:activeFilter?.type==='service'?activeFilter.value:null,
                  onItemClick:s=>toggleFilter('service',s.name,s.name),
                }),
                h('div',{style:{overflowX:'auto'}},
                  h('table',{className:'data-table',style:{fontSize:12}},
                    h('thead',null,h('tr',null,
                      ['الخدمة','الإيراد','التكرار','متوسط السعر'].map((t,i)=>
                        h('th',{key:i,style:{fontWeight:700,fontSize:11}},t)))),
                    h('tbody',null,
                      serviceStats.slice(0,8).map((s,i)=>
                        h(HoverTooltip,{key:i, tag:'tr',
                          lines:[s.name, 'الإيراد: '+window.fmtEGP(s.revenue), 'التكرار: '+s.count+' مرة', 'متوسط: '+window.fmtEGP(s.avgPrice)],
                          color:'var(--success)',
                        },
                          h('tr',{onClick:()=>toggleFilter('service',s.name,s.name),
                            style:{cursor:'pointer',
                              background:activeFilter?.value===s.name?'var(--success-soft)':'transparent'}
                          },
                            h('td',{style:{fontWeight:600,maxWidth:120,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}},s.name),
                            h('td',{style:{color:'var(--success)',fontWeight:700}},window.fmtEGP(s.revenue)),
                            h('td',null,s.count),
                            h('td',{style:{color:'var(--text-tertiary)'}},window.fmtEGP(s.avgPrice)),
                          )
                        )
                      )
                    ),
                  ),
                ),
              ),
        ),
      ),

      // ══ TAB: PATIENTS ══
      tab==='patients'&&h('div',null,

        h('div',{className:'grid cols-4 mb-16'},
          [
            {label:'إجمالي المرضى',      val:allPatients.length,color:'var(--accent)', icon:Icons.Users},
            {label:'مرضى جدد (الفترة)',  val:newPatients.length,color:'var(--success)',icon:Icons.UserPlus},
            {label:'مرضى نشطون',         val:activePatients,    color:'var(--info)',   icon:Icons.User},
            {label:'متوسط الزيارات',     val:avgVisits.toFixed(1)+' جلسة',color:'var(--warning)',icon:Icons.Calendar},
          ].map((k,i)=>h(KpiCard,{key:i,...k})),
        ),

        h('div',{style:{display:'grid',gridTemplateColumns:'2fr 1fr',gap:16,marginBottom:16}},
          h('div',{className:'card',style:{overflow:'hidden'}},
            h('div',{style:{padding:'14px 20px',borderBottom:'1px solid var(--border)',fontWeight:800,fontSize:14}},'أكثر المرضى زيارة'),
            patientVisitMap.length===0
              ? h('div',{style:{padding:32,textAlign:'center',color:'var(--text-tertiary)',fontSize:13}},'لا توجد مواعيد مكتملة في هذه الفترة')
              : h('div',{style:{maxHeight:300,overflowY:'auto'}},
                  h('table',{className:'data-table'},
                    h('thead',null,h('tr',null,['المريض','الإيرادات','التحصيل','الجلسات'].map((t,i)=>h('th',{key:i},t)))),
                    h('tbody',null,
                      patientVisitMap.map((p,i)=>
                        h(HoverTooltip,{key:i, tag:'tr',
                          lines:[p.name,'إيراد: '+window.fmtEGP(p.revenue),'تحصيل: '+window.fmtEGP(p.paid),'زيارات: '+p.visits],
                          color:'var(--accent)',
                        },
                          h('tr',{style:{cursor:'default'}},
                            h('td',{style:{fontWeight:600}},p.name),
                            h('td',null,window.fmtEGP(p.revenue)),
                            h('td',{style:{color:'var(--success)',fontWeight:700}},window.fmtEGP(p.paid)),
                            h('td',null,p.visits),
                          )
                        )
                      ),
                    ),
                  ),
                ),
          ),
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:10}},'المديونيات'),
            debtors.length===0
              ? h('div',{style:{color:'var(--success)',fontSize:13}},'✅ '+'لا توجد مديونيات')
              : h(SimpleBarChart,{items:debtors,valueKey:'debt',labelKey:'name',color:'var(--danger)',fmtVal:window.fmtEGP}),
          ),
        ),

        h('div',{style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16,marginBottom:16}},
          // Patients by doctor (clickable)
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:12}},'المرضى حسب الطبيب'+' · '+'انقر للتصفية'),
            patientsByDoctor.length===0||patientsByDoctor.every(p=>p.name==='غير محدد'||p.name==='Not Set')
              ? h('div',{style:{color:'var(--text-tertiary)',fontSize:13,textAlign:'center',padding:'16px 0'}},'أضف الطبيب المعالج في ملف المريض')
              : h(SimpleBarChart,{
                  items:patientsByDoctor, valueKey:'value', labelKey:'name', color:'var(--accent)',
                  fmtVal:v=>v+' مريض',
                  activeValue:activeFilter?.type==='doctor'?activeFilter.value:null,
                  onItemClick:p=>toggleFilter('doctor',p.name,p.name),
                }),
          ),
          // Regional distribution
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:12}},'التوزيع حسب المنطقة'),
            patientsByRegion.length===0||patientsByRegion.every(p=>p.name==='غير محدد'||p.name==='Not Set')
              ? h('div',{style:{color:'var(--text-tertiary)',fontSize:13,textAlign:'center',padding:'16px 0'}},'أضف العنوان في ملف المريض')
              : h(SimpleBarChart,{
                  items:patientsByRegion, valueKey:'value', labelKey:'name', color:'var(--info)',
                  fmtVal:v=>v+' مريض',
                }),
          ),
        ),

        h('div',{style:{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16}},
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:14}},'توزيع النوع'),
            h(DonutChart,{
              items:Object.entries(genderCounts)
                .filter(([,v])=>v>0)
                .map(([g,v])=>({
                  name:g,
                  value:v,
                  color:g==='ذكر' ? 'var(--info)' : g==='أنثى' ? 'var(--accent)' : 'var(--text-tertiary)',
                })),
              centerLabel:'إجمالي المرضى',
              centerValue:totalGender,
              fmtVal:v => v + ' مريض',
            }),
          ),
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:14}},'الفئات العمرية'),
            h(SimpleBarChart,{
              items:Object.entries(ageGroups).map(([g,v])=>({
                name:g + ' سنة',
                value:v,
                percentage: totalAge>0 ? Math.round(v/totalAge*100) : 0,
              })),
              valueKey:'value',
              labelKey:'name',
              color:'var(--success)',
              fmtVal:v => v + ' مريض',
              secondaryKey:'percentage',
              secondaryLabel:'',
            }),
          ),
        ),
      ),

      // ══ TAB: SERVICES ══
      tab==='services'&&h('div',null,

        h('div',{style:{display:'grid',gridTemplateColumns:'3fr 2fr',gap:16,marginBottom:16}},
          // Service table — clickable rows
          h('div',{className:'card',style:{overflow:'hidden'}},
            h('div',{style:{padding:'14px 20px',borderBottom:'1px solid var(--border)',fontWeight:800,fontSize:14}},
              'أداء الخدمات · انقر للتصفية',
              activeFilter?.type==='service'&&h('span',{style:{fontSize:11,color:'var(--accent)',fontWeight:700,marginRight:6}},'· مفلترة'),
            ),
            serviceStats.length===0
              ? h('div',{style:{padding:40,textAlign:'center',color:'var(--text-tertiary)'}},'لا توجد فواتير في هذه الفترة')
              : h('div',{style:{maxHeight:440,overflowY:'auto'}},
                  h('table',{className:'data-table'},
                    h('thead',null,h('tr',null,
                      ['#','الخدمة','الإيرادات','التكرار','متوسط السعر'].map((t,i)=>h('th',{key:i},t))
                    )),
                    h('tbody',null,
                      serviceStats.map((s,i)=>h('tr',{
                        key:i,
                        onClick:()=>toggleFilter('service',s.name,s.name),
                        title:`اضغط لتصفية: ${s.name}`,
                        style:{
                          cursor:'pointer',
                          background:activeFilter?.type==='service'&&activeFilter.value===s.name?'var(--accent-soft)':undefined,
                        }
                      },
                        h('td',{style:{color:'var(--text-tertiary)',fontWeight:700,fontSize:12}},i+1),
                        h('td',{style:{fontWeight:600,maxWidth:200,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}},s.name),
                        h('td',{style:{fontWeight:800,color:'var(--success)'}},window.fmtEGP(s.revenue)),
                        h('td',null,s.count),
                        h('td',null,window.fmtEGP(s.avgPrice)),
                      )),
                    ),
                  ),
                ),
          ),
          // Service frequency bar chart
          h('div',{className:'card p-20'},
            h('div',{style:{fontWeight:800,fontSize:14,marginBottom:12}},'أكثر الخدمات طلباً · انقر للتصفية'),
            h(SimpleBarChart,{
              items:[...serviceStats].sort((a,b)=>b.count-a.count).slice(0,10),
              valueKey:'count',labelKey:'name',color:'var(--info)',height:7,
              fmtVal:v=>v+' مرة',
              activeValue:activeFilter?.type==='service'?activeFilter.value:null,
              onItemClick:s=>toggleFilter('service',s.name,s.name),
            }),
          ),
        ),

        // Doctor commissions — clickable rows
        h('div',{className:'card',style:{overflow:'hidden',marginBottom:16}},
          h('div',{style:{padding:'14px 20px',borderBottom:'1px solid var(--border)',fontWeight:800,fontSize:14}},'عمولات الأطباء · انقر للتصفية'),
          doctorRevMap.length===0
            ? h('div',{style:{padding:32,textAlign:'center',color:'var(--text-tertiary)',fontSize:13}},'لا توجد بيانات')
            : h('div',null,
                h('table',{className:'data-table'},
                  h('thead',null,h('tr',null,
                    ['الطبيب','إجمالي الاستحقاق','إجمالي التحصيل','نسبة العمولة','العمولة المستحقة']
                    .map((t,i)=>h('th',{key:i},t))
                  )),
                  h('tbody',null,
                    doctorRevMap.map((d,i)=>h('tr',{
                      key:i,
                      onClick:()=>toggleFilter('doctor',d.name,d.name),
                      title:`اضغط لتصفية: ${d.name}`,
                      style:{cursor:'pointer',background:activeFilter?.type==='doctor'&&activeFilter.value===d.name?'var(--accent-soft)':undefined},
                    },
                      h('td',{style:{fontWeight:700}},d.name),
                      h('td',null,window.fmtEGP(d.revenue)),
                      h('td',{style:{color:'var(--success)',fontWeight:700}},window.fmtEGP(d.paid)),
                      h('td',null,Math.round(d.rate*100)+'%'),
                      h('td',{style:{fontWeight:800,color:'var(--accent)',fontSize:15}},window.fmtEGP(Math.round(d.paid*d.rate))),
                    )),
                  ),
                ),
                h('div',{style:{padding:'12px 20px',background:'var(--bg-subtle)',borderTop:'1px solid var(--border)',display:'flex',justifyContent:'space-between'}},
                  h('span',{style:{fontWeight:700}},'إجمالي العمولات:'),
                  h('span',{style:{fontWeight:900,fontSize:16,color:'var(--accent)'}},window.fmtEGP(Math.round(totalCommissions))),
                ),
              ),
        ),
      ),

      // ══ TAB: DAILY ══
      tab==='daily'&&h('div',null,
        (()=>{
          const todayInvoices = allInvoices.filter(i=>i.date===today);
          const todayRevenue  = todayInvoices.reduce((s,i)=>s+(i.paid||0),0);
          const todayAppts    = allAppts.filter(a=>a.date===today);
          const tmrw=new Date(); tmrw.setDate(tmrw.getDate()+1);
          const tomorrowAppts=allAppts.filter(a=>a.date===tmrw.toISOString().split('T')[0]);
          const dailySummary=[
            '📊 ملخص يوم '+today+' — '+(clinicName||'سِنان كلينيك'),
            '💰 إيراد اليوم: '+window.fmtEGP(todayRevenue)+' ('+todayInvoices.length+' فاتورة)',
            '📅 مواعيد اليوم: '+todayAppts.length,
            '📅 مواعيد الغد: '+tomorrowAppts.length,
            lowStock.length>0?'⚠️ مخزون منخفض: '+lowStock.map(i=>i.name).join('، '):'✅ المخزون طبيعي',
          ].join('\n');

          return h(Fragment,null,
            h('div',{className:'grid cols-4 mb-12'},
              [
                {label:'إيراد اليوم',   val:window.fmtEGP(todayRevenue),icon:Icons.DollarSign,  color:'var(--success)'},
                {label:'فواتير اليوم',  val:todayInvoices.length,       icon:Icons.FileText,    color:'var(--accent)'},
                {label:'مواعيد اليوم',  val:todayAppts.length,          icon:Icons.Calendar,    color:'var(--info)'},
                {label:'مخزون منخفض',   val:lowStock.length,            icon:Icons.AlertTriangle,color:lowStock.length>0?'var(--danger)':'var(--success)'},
              ].map((k,i)=>h(KpiCard,{key:i,...k})),
            ),

            // Summary table (last 14 days)
            h('div',{className:'card',style:{overflow:'hidden',marginBottom:16}},
              h('div',{style:{padding:'14px 20px',borderBottom:'1px solid var(--border)',fontWeight:800,fontSize:14}},'ملخص يومي — آخر 14 يوم'),
              dailyBreakdown.length===0
                ? h('div',{style:{padding:32,textAlign:'center',color:'var(--text-tertiary)',fontSize:13}},'لا توجد بيانات في هذه الفترة')
                : h('table',{className:'data-table'},
                    h('thead',null,h('tr',null,
                      ['اليوم','المرضى','الجلسات','الفواتير','الإيراد','التحصيل'].map((t,i)=>h('th',{key:i},t))
                    )),
                    h('tbody',null,
                      dailyBreakdown.map((d,i)=>h('tr',{key:i,
                        style:{background:d.date===today?'var(--accent-soft)':undefined}},
                        h('td',{style:{fontWeight:700,color:d.date===today?'var(--accent)':undefined}},d.label),
                        h('td',null,d.patients||'—'),
                        h('td',null,d.sessions||'—'),
                        h('td',null,d.invoices||'—'),
                        h('td',{style:{color:'var(--info)',fontWeight:600}},d.revenue>0?window.fmtEGP(d.revenue):'—'),
                        h('td',{style:{fontWeight:700,color:'var(--success)'}},d.paid>0?window.fmtEGP(d.paid):'—'),
                      )),
                    ),
                  ),
            ),

            // Power BI-style: patient details per day
            h('div',{className:'card',style:{overflow:'hidden',marginBottom:16}},
                h('div',{style:{padding:'14px 20px',borderBottom:'1px solid var(--border)',display:'flex',justifyContent:'space-between',alignItems:'center'}},
                  h('div',{style:{fontWeight:800,fontSize:14}},'الخدمات والجلسات والمرضى يومياً'),
                  h('div',{style:{fontSize:11,color:'var(--text-tertiary)'}},'انقر يوم لعرض تفاصيل المرضى'),
                ),
                dailyBreakdown.filter(d=>d.invoices>0).length===0
                  ? h('div',{style:{padding:32,textAlign:'center',color:'var(--text-tertiary)',fontSize:13}},'لا توجد فواتير في هذه الفترة')
                  : h('div',null,
                      dailyBreakdown.filter(d=>d.invoices>0).map((d,i)=>{
                        const isOpen = expandedDay===d.date;
                        return h('div',{key:i},
                          // Day header row
                          h('div',{
                            onClick:()=>setExpandedDay(isOpen?null:d.date),
                            style:{
                              display:'grid',gridTemplateColumns:'1fr repeat(5,auto)',gap:'0 20px',
                              padding:'10px 20px',cursor:'pointer',
                              background:d.date===today?'var(--accent-soft)':isOpen?'var(--bg-subtle)':undefined,
                              borderBottom:'1px solid var(--border)',
                              transition:'background 0.15s',
                            },
                          },
                            h('div',{style:{fontWeight:700,fontSize:13,color:d.date===today?'var(--accent)':undefined}},
                              d.label+' '+d.date),
                            h('div',{style:{fontSize:12,color:'var(--text-tertiary)',textAlign:'center'}},d.patients+' مريض'),
                            h('div',{style:{fontSize:12,color:'var(--text-tertiary)',textAlign:'center'}},d.sessions+' جلسة'),
                            h('div',{style:{fontSize:12,color:'var(--text-tertiary)',textAlign:'center'}},d.invoices+' فاتورة'),
                            h('div',{style:{fontSize:12,color:'var(--info)',fontWeight:600,textAlign:'center'}},window.fmtEGP(d.revenue)),
                            h('div',{style:{fontSize:12,color:'var(--success)',fontWeight:700,textAlign:'center'}},window.fmtEGP(d.paid)),
                          ),
                          // Expanded patient rows
                          isOpen&&h('div',{style:{background:'var(--bg-subtle)',borderBottom:'1px solid var(--border)'}},
                            h('table',{className:'data-table',style:{margin:0}},
                              h('thead',null,h('tr',null,
                                ['المريض','الطبيب','الإيراد','التحصيل','المديونية','الحالة'].map((t,ti)=>h('th',{key:ti,style:{fontSize:11,padding:'6px 12px'}},t))
                              )),
                              h('tbody',null,
                                d.patientRows.map((pr,pi)=>h('tr',{key:pi},
                                  h('td',{style:{fontWeight:600,fontSize:12}},pr.name),
                                  h('td',{style:{fontSize:11,color:'var(--text-tertiary)'}},pr.doctor),
                                  h('td',{style:{color:'var(--info)',fontSize:12}},window.fmtEGP(pr.revenue)),
                                  h('td',{style:{color:'var(--success)',fontWeight:700,fontSize:12}},window.fmtEGP(pr.paid)),
                                  h('td',{style:{color:pr.debt>0?'var(--danger)':'var(--success)',fontSize:12}},pr.debt>0?window.fmtEGP(pr.debt):'✓'),
                                  h('td',null,h('span',{className:'chip',style:{fontSize:10}},pr.status||'—')),
                                )),
                              ),
                            ),
                          ),
                        );
                      }),
                    ),
            ),

            h('div',{className:'grid cols-2',style:{gap:16,marginBottom:16}},
              h('div',{className:'card p-20'},
                h('div',{style:{fontWeight:800,fontSize:14,marginBottom:10}},'مواعيد الغد ('+tomorrowAppts.length+')'),
                tomorrowAppts.length===0
                  ? h('div',{style:{color:'var(--text-tertiary)',fontSize:13}},'لا توجد مواعيد')
                  : h('div',{style:{display:'flex',flexDirection:'column',gap:6}},
                      tomorrowAppts.slice(0,8).map((a,i)=>h('div',{key:i,style:{
                        display:'flex',justifyContent:'space-between',padding:'8px 10px',
                        background:'var(--bg-subtle)',borderRadius:'var(--radius)',fontSize:13,
                      }},
                        h('span',{style:{fontWeight:600}},a.patient),
                        h('span',{style:{color:'var(--text-tertiary)'}},a.time+' · '+(a.doctor||'')),
                      )),
                    ),
              ),
              h('div',{className:'card p-20'},
                h('div',{style:{fontWeight:800,fontSize:14,marginBottom:10}},'مخزون منخفض ('+lowStock.length+')'),
                lowStock.length===0
                  ? h('div',{style:{color:'var(--success)',fontSize:13}},'✅ كل الأصناف بمستوى كافٍ')
                  : h('div',{style:{display:'flex',flexDirection:'column',gap:6}},
                      lowStock.slice(0,8).map((it,i)=>h('div',{key:i,style:{
                        display:'flex',justifyContent:'space-between',padding:'8px 10px',
                        background:'var(--danger-soft)',borderRadius:'var(--radius)',fontSize:13,
                      }},
                        h('span',{style:{fontWeight:600,color:'var(--danger)'}},it.name),
                        h('span',{style:{color:'var(--danger)'}},window.fmtNum(it.stock)+'/'+window.fmtNum(it.minStock)+' '+(it.unit||'')),
                      )),
                    ),
              ),
            ),
            h('div',{className:'card p-20'},
              h('div',{style:{fontWeight:800,fontSize:14,marginBottom:10}},'ملخص للواتساب'),
              h('pre',{style:{background:'var(--bg-subtle)',padding:14,borderRadius:'var(--radius)',
                fontSize:13,fontFamily:'inherit',whiteSpace:'pre-wrap',lineHeight:1.8,color:'var(--text-primary)'}},dailySummary),
              h('button',{className:'btn primary',style:{marginTop:10},
                onClick:()=>navigator.clipboard?.writeText(dailySummary)},
                h(Icons.Copy,{size:14}),'نسخ'),
            ),
          );
        })(),
      ),
    ),
  );
}

// ==================== Messages ====================
function Messages() {
  const [active, setActive] = useState('M1');
  const [text, setText] = useState('');
  const [thread, setThread] = useState([
    { id: 1, from: 'them', text: 'صباح الخير، هل أشعة المريض أحمد جاهزة؟', time: '10:22' },
    { id: 2, from: 'me', text: 'صباح النور، نعم تم رفعها منذ قليل على ملفه', time: '10:23' },
    { id: 3, from: 'them', text: 'ممتاز، سأراجعها الآن. شكراً!', time: '10:24' },
  ]);

  const activeThread = (window.MESSAGES || []).find(m => m.id === active) || (window.MESSAGES || [])[0] || {};

  return h('div', { className: 'fade-in', style: { height: '100%' } },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الدردشة الداخلية'),
        h('div', { className: 'page-subtitle' }, 'تواصل سريع بين أعضاء الفريق'),
      ),
    ),
    h('div', { className: 'page-content', style: { height: 'calc(100% - 100px)' } },
      h('div', { className: 'card', style: { display: 'grid', gridTemplateColumns: '300px 1fr', height: 'calc(100vh - 180px)', overflow: 'hidden' } },
        h('div', { style: { borderInlineEnd: '1px solid var(--border)', overflow: 'auto' } },
          h('div', { style: { padding: 12, borderBottom: '1px solid var(--border)' } },
            h('input', { className: 'input', placeholder: 'بحث في المحادثات...', style: { padding: 8, fontSize: 13 } }),
          ),
          window.MESSAGES.map(m => h('div', {
            key: m.id,
            onClick: () => setActive(m.id),
            style: {
              padding: '12px 14px', borderBottom: '1px solid var(--border)', cursor: 'pointer',
              background: active === m.id ? 'var(--accent-soft)' : 'transparent',
              display: 'flex', gap: 10, alignItems: 'center',
            },
          },
            h('div', { style: { position: 'relative' } },
              h('div', { className: 'avatar sm' }, m.avatar),
              m.online ? h('div', { style: { position: 'absolute', bottom: -2, insetInlineEnd: -2, width: 10, height: 10, borderRadius: '50%', background: 'var(--success)', border: '2px solid var(--bg-elevated)' } }) : null,
            ),
            h('div', { style: { flex: 1, minWidth: 0 } },
              h('div', { className: 'flex jc-sb ai-c' },
                h('div', { style: { fontSize: 13, fontWeight: 700, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, m.from),
                h('div', { style: { fontSize: 10, color: 'var(--text-tertiary)' } }, m.time),
              ),
              h('div', { className: 'flex jc-sb ai-c' },
                h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 } }, m.preview),
                m.unread ? h('span', { style: { background: 'var(--accent)', color: '#fff', fontSize: 10, fontWeight: 700, padding: '1px 6px', borderRadius: 999 } }, m.unread) : null,
              ),
            ),
          )),
        ),
        h('div', { style: { display: 'flex', flexDirection: 'column', overflow: 'hidden' } },
          h('div', { style: { padding: 14, borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 12 } },
            h('div', { className: 'avatar sm' }, activeThread.avatar),
            h('div', { style: { flex: 1 } },
              h('div', { style: { fontWeight: 700 } }, activeThread.from),
              h('div', { style: { fontSize: 11, color: activeThread.online ? 'var(--success)' : 'var(--text-tertiary)' } }, activeThread.online ? 'متصل الآن' : 'غير متصل'),
            ),
            h('button', { className: 'icon-btn' }, h(Icons.Phone, { size: 16 })),
            h('button', { className: 'icon-btn' }, h(Icons.MoreHorizontal, { size: 16 })),
          ),
          h('div', { style: { flex: 1, overflowY: 'auto', padding: 20, display: 'flex', flexDirection: 'column', gap: 10 } },
            thread.map(m => h('div', {
              key: m.id,
              style: { display: 'flex', justifyContent: m.from === 'me' ? 'flex-start' : 'flex-end' },
            },
              h('div', {
                style: {
                  maxWidth: '70%', padding: '10px 14px',
                  background: m.from === 'me' ? 'var(--accent)' : 'var(--bg-subtle)',
                  color: m.from === 'me' ? '#fff' : 'var(--text-primary)',
                  borderRadius: m.from === 'me' ? '14px 14px 4px 14px' : '14px 14px 14px 4px',
                  fontSize: 13,
                },
              },
                h('div', null, m.text),
                h('div', { style: { fontSize: 10, opacity: 0.7, marginTop: 4, textAlign: 'end' } }, m.time),
              ),
            )),
          ),
          h('div', { style: { padding: 14, borderTop: '1px solid var(--border)', display: 'flex', gap: 8, alignItems: 'center' } },
            h('button', { className: 'icon-btn' }, h(Icons.Paperclip, { size: 18 })),
            h('input', {
              className: 'input', placeholder: 'اكتب رسالة...', value: text,
              onChange: (e) => setText(e.target.value),
              onKeyDown: (e) => {
                if (e.key === 'Enter' && text.trim()) {
                  setThread([...thread, { id: Date.now(), from: 'me', text, time: 'الآن' }]);
                  setText('');
                }
              },
            }),
            h('button', {
              className: 'btn primary',
              onClick: () => {
                if (!text.trim()) return;
                setThread([...thread, { id: Date.now(), from: 'me', text, time: 'الآن' }]);
                setText('');
              },
            }, h(Icons.Send, { size: 16 })),
          ),
        ),
      ),
    ),
  );
}

// ==================== Settings ====================
function Settings() {
  const { theme, setTheme, density, setDensity, clinicName, setClinicName, clinicTimezone, setClinicTimezone } = useContext(AppContext);
  const [tab, setTab] = useState('general');
  const [roomCount, setRoomCount] = useState(() => parseInt(localStorage.getItem('senan-rooms') || '1', 10));
  const saveRooms = (n) => { const v = Math.max(1, Math.min(10, n)); setRoomCount(v); localStorage.setItem('senan-rooms', String(v)); };
  const [startHour, setStartHour] = useState(() => parseInt(localStorage.getItem('senan-start-hour') || '9', 10));
  const [endHour,   setEndHour]   = useState(() => parseInt(localStorage.getItem('senan-end-hour')   || '17', 10));
  const saveStartHour = (h) => { setStartHour(h); localStorage.setItem('senan-start-hour', String(h)); };
  const saveEndHour   = (h) => { setEndHour(h);   localStorage.setItem('senan-end-hour',   String(h)); };
  const hourLabel = (h) => {
    if (h === 0) return '12:00 ص';
    if (h < 12)  return h + ':00 ص';
    if (h === 12) return '12:00 م';
    return (h - 12) + ':00 م';
  };
  const timezoneOptions = [
    ['local', 'حسب جهاز المستخدم'],
    ['Africa/Cairo', 'مصر - القاهرة'],
    ['Asia/Riyadh', 'السعودية - الرياض'],
    ['Asia/Dubai', 'الإمارات - دبي'],
    ['Asia/Kuwait', 'الكويت'],
    ['Asia/Qatar', 'قطر'],
    ['Asia/Beirut', 'لبنان - بيروت'],
    ['UTC', 'UTC / توقيت عالمي'],
  ];
  const selectedTimezone = clinicTimezone || 'Africa/Cairo';

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الإعدادات'),
        h('div', { className: 'page-subtitle' }, 'إدارة إعدادات العيادة والنظام'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { style: { display: 'grid', gridTemplateColumns: '240px 1fr', gap: 20 } },
        h('div', { className: 'card', style: { padding: 10, height: 'fit-content' } },
          [
            { id: 'general', label: 'عام', icon: Icons.Settings },
            { id: 'clinic', label: 'بيانات العيادة', icon: Icons.Building },
            { id: 'appearance', label: 'المظهر', icon: Icons.Sliders },
            { id: 'notifications', label: 'الإشعارات', icon: Icons.Bell },
            { id: 'billing-s', label: 'الفوترة والضرائب', icon: Icons.CreditCard },
            { id: 'integrations', label: 'التكاملات', icon: Icons.Zap },
            { id: 'security', label: 'الأمان', icon: Icons.Shield },
            { id: 'backup', label: 'النسخ الاحتياطي', icon: Icons.Database },
          ].map(s => h('button', {
            key: s.id,
            className: 'nav-item' + (tab === s.id ? ' active' : ''),
            onClick: () => setTab(s.id),
          },
            h('span', { className: 'icon-box' }, h(s.icon, { size: 16 })),
            h('span', null, s.label),
          )),
        ),
        h('div', { className: 'card p-24' },
          tab === 'general' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'الإعدادات العامة'),
            h('div', { className: 'grid', style: { gap: 16 } },
              h('div', null, h('div', { className: 'label' }, 'اللغة'), h('select', { className: 'select' }, h('option', null, 'العربية'), h('option', null, 'English'))),
              h('div', null,
                h('div', { className: 'label' }, 'المنطقة الزمنية للعيادة'),
                h('select', {
                  className: 'select',
                  value: selectedTimezone,
                  onChange: (e) => setClinicTimezone && setClinicTimezone(e.target.value),
                },
                  timezoneOptions.map(([value, label]) => h('option', { key: value, value }, label)),
                ),
                h('div', { style: { marginTop: 8, fontSize: 12, color: 'var(--text-tertiary)' } },
                  'تؤثر على الساعة، تاريخ اليوم، وعدّادات المواعيد والجلسات.'
                ),
              ),
              h('div', null, h('div', { className: 'label' }, 'العملة'), h('select', { className: 'select' }, h('option', null, 'الجنيه المصري (ج.م)'), h('option', null, 'الريال السعودي'))),
              h('div', null, h('div', { className: 'label' }, 'تنسيق التاريخ'), h('select', { className: 'select' }, h('option', null, 'DD-MM-YYYY'), h('option', null, 'YYYY-MM-DD'))),
            ),
          ),
          tab === 'clinic' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'بيانات العيادة'),
            h('div', { className: 'grid', style: { gap: 16 } },
              h('div', null, h('div', { className: 'label' }, 'اسم العيادة'), h('input', { className: 'input', value: clinicName, onChange: (e) => setClinicName(e.target.value) })),
              h('div', { className: 'grid cols-2', style: { gap: 12 } },
                h('div', null, h('div', { className: 'label' }, 'رقم الهاتف'), h('input', { className: 'input', defaultValue: '+20 2 2345 6789' })),
                h('div', null, h('div', { className: 'label' }, 'البريد الإلكتروني'), h('input', { className: 'input', defaultValue: 'info@senan.clinic' })),
              ),
              h('div', null, h('div', { className: 'label' }, 'العنوان'), h('input', { className: 'input', defaultValue: 'شارع التحرير، وسط البلد، القاهرة' })),
              h('div', null, h('div', { className: 'label' }, 'الرقم الضريبي'), h('input', { className: 'input', defaultValue: '123-456-789' })),
              h('div', null, h('div', { className: 'label' }, 'ساعات العمل'), h('input', { className: 'input', defaultValue: 'السبت - الخميس · 9 صباحاً - 9 مساءً' })),
              h('div', null,
                h('div', { className: 'label' }, 'عدد غرف العيادة'),
                h('div', { className: 'flex ai-c gap-12' },
                  h('button', { className: 'btn outline sm', onClick: () => saveRooms(roomCount - 1) }, '−'),
                  h('span', { style: { fontWeight: 800, fontSize: 20, minWidth: 32, textAlign: 'center' } }, roomCount),
                  h('button', { className: 'btn outline sm', onClick: () => saveRooms(roomCount + 1) }, '+'),
                  h('span', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, 'تنعكس فوراً على جدول المواعيد'),
                ),
              ),
              h('div', null,
                h('div', { className: 'label' }, 'ساعات جدول المواعيد'),
                h('div', { className: 'flex ai-c gap-12', style: { flexWrap: 'wrap' } },
                  h('div', { className: 'flex ai-c gap-8' },
                    h('span', { style: { fontSize: 13, color: 'var(--text-secondary)', minWidth: 40 } }, 'من'),
                    h('select', {
                      className: 'select',
                      style: { width: 120 },
                      value: startHour,
                      onChange: e => saveStartHour(parseInt(e.target.value)),
                    },
                      Array.from({ length: 18 }, (_, i) => i + 6).map(h_ =>
                        h('option', { key: h_, value: h_ }, hourLabel(h_))
                      ),
                    ),
                  ),
                  h('div', { className: 'flex ai-c gap-8' },
                    h('span', { style: { fontSize: 13, color: 'var(--text-secondary)', minWidth: 40 } }, 'إلى'),
                    h('select', {
                      className: 'select',
                      style: { width: 120 },
                      value: endHour,
                      onChange: e => saveEndHour(parseInt(e.target.value)),
                    },
                      Array.from({ length: 18 }, (_, i) => i + 7).map(h_ =>
                        h('option', { key: h_, value: h_, disabled: h_ <= startHour }, hourLabel(h_))
                      ),
                    ),
                  ),
                  h('span', { style: { fontSize: 12, color: 'var(--text-tertiary)' } },
                    `${endHour - startHour} ساعة · تنعكس فوراً على جدول المواعيد`),
                ),
              ),
            ),
            h('button', { className: 'btn primary mt-24' }, 'حفظ التغييرات'),
          ),
          tab === 'appearance' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'المظهر'),
            h('div', { className: 'label' }, 'الثيم'),
            h('div', { className: 'grid cols-3', style: { gap: 10, marginBottom: 20 } },
              [{ id: 'clean', name: 'طبي نظيف', desc: 'أبيض + تركواز هادئ' }, { id: 'luxe', name: 'فاخر داكن', desc: 'أسود + ذهبي' }, { id: 'warm', name: 'دافئ', desc: 'باستيل وأرضي' }].map(t => h('div', {
                key: t.id,
                onClick: () => setTheme(t.id),
                style: {
                  padding: 16, cursor: 'pointer', borderRadius: 'var(--radius)',
                  border: '2px solid ' + (theme === t.id ? 'var(--accent)' : 'var(--border)'),
                  background: theme === t.id ? 'var(--accent-soft)' : 'transparent',
                },
              },
                h('div', { className: 'theme-swatch', 'data-preview': t.id, style: { width: '100%', height: 50, marginBottom: 10, transform: 'none' } }),
                h('div', { style: { fontWeight: 700, fontSize: 14 } }, t.name),
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 2 } }, t.desc),
              )),
            ),
            h('div', { className: 'label' }, 'الكثافة'),
            h('div', { className: 'flex gap-8' },
              ['compact', 'comfortable'].map((d, i) => h('button', {
                key: d,
                className: 'btn ' + (density === d ? 'primary' : 'outline'),
                onClick: () => setDensity(d),
              }, i === 0 ? 'مدمجة' : 'مريحة')),
            ),
          ),
          tab === 'notifications' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'إعدادات الإشعارات'),
            h('div', { className: 'grid', style: { gap: 4 } },
              ['تذكيرات المواعيد (WhatsApp)', 'تذكيرات المواعيد (SMS)', 'تأكيد استلام المدفوعات', 'تنبيهات انخفاض المخزون', 'تنبيهات انتهاء الصلاحية', 'التقرير اليومي للمدير'].map((l, i) => h('label', {
                key: i,
                style: { padding: '14px 0', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', cursor: 'pointer' },
              },
                h('span', { style: { fontSize: 14 } }, l),
                h(Toggle, { defaultChecked: i < 4 }),
              )),
            ),
          ),
          tab === 'billing-s' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'الفوترة والضرائب'),
            h('div', { className: 'grid cols-2', style: { gap: 16 } },
              h('div', null, h('div', { className: 'label' }, 'نسبة الضريبة (%)'), h('input', { className: 'input', defaultValue: '14' })),
              h('div', null, h('div', { className: 'label' }, 'بادئة الفواتير'), h('input', { className: 'input', defaultValue: 'INV-2026-' })),
              h('div', null, h('div', { className: 'label' }, 'شروط الدفع'), h('input', { className: 'input', defaultValue: 'صافي 30 يوم' })),
              h('div', null, h('div', { className: 'label' }, 'العملة الافتراضية'), h('input', { className: 'input', defaultValue: 'ج.م' })),
            ),
          ),
          tab === 'integrations' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'التكاملات'),
            [
              { name: 'WhatsApp Business', desc: 'إرسال التذكيرات والتأكيدات تلقائياً', on: true },
              { name: 'بوابة الدفع Fawry', desc: 'تحصيل المدفوعات أونلاين', on: true },
              { name: 'Google Calendar', desc: 'مزامنة المواعيد مع جوجل', on: false },
              { name: 'نظام التأمين الموحد', desc: 'الربط مع شركات التأمين', on: true },
              { name: 'SMS Gateway', desc: 'إرسال رسائل نصية', on: false },
            ].map((it, i) => h('div', { key: i, style: { padding: 16, border: '1px solid var(--border)', borderRadius: 'var(--radius)', marginBottom: 10, display: 'flex', alignItems: 'center', gap: 12 } },
              h('div', { style: { width: 40, height: 40, borderRadius: 10, background: 'var(--bg-subtle)', display: 'grid', placeItems: 'center' } }, h(Icons.Zap, { size: 18 })),
              h('div', { style: { flex: 1 } },
                h('div', { style: { fontWeight: 700 } }, it.name),
                h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, it.desc),
              ),
              h(Toggle, { defaultChecked: it.on }),
            )),
          ),
          tab === 'security' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'الأمان'),
            h('div', { className: 'grid', style: { gap: 16 } },
              h('div', null, h('div', { className: 'label' }, 'كلمة المرور الحالية'), h('input', { className: 'input', type: 'password', defaultValue: '••••••••' })),
              h('div', null, h('div', { className: 'label' }, 'كلمة المرور الجديدة'), h('input', { className: 'input', type: 'password' })),
              h('label', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)' } },
                h('div', null,
                  h('div', { style: { fontWeight: 700 } }, 'التحقق بخطوتين'),
                  h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, 'أمان إضافي لحسابك'),
                ),
                h(Toggle, { defaultChecked: true }),
              ),
            ),
          ),
          tab === 'backup' && h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'النسخ الاحتياطي'),
            h('div', { style: { padding: 16, background: 'var(--success-soft)', borderRadius: 'var(--radius)', color: 'var(--success)', fontWeight: 600, marginBottom: 16 } },
              h(Icons.Check, { size: 16, style: { display: 'inline-block', verticalAlign: 'text-bottom', marginLeft: 6 } }),
              'آخر نسخة احتياطية: اليوم 03:00 صباحاً',
            ),
            h('div', { className: 'grid cols-2', style: { gap: 12 } },
              h('button', { className: 'btn outline' }, h(Icons.Download, { size: 16 }), 'تصدير جميع البيانات'),
              h('button', { className: 'btn outline' }, h(Icons.Upload, { size: 16 }), 'استعادة من نسخة'),
            ),
          ),
        ),
      ),
    ),
  );
}

function Toggle({ defaultChecked }) {
  const [on, setOn] = useState(!!defaultChecked);
  return h('button', {
    onClick: () => setOn(!on),
    style: {
      width: 42, height: 24, borderRadius: 999, border: 'none',
      background: on ? 'var(--accent)' : 'var(--border-strong)',
      position: 'relative', cursor: 'pointer', transition: 'background 0.2s',
    },
  },
    h('div', {
      style: {
        width: 18, height: 18, borderRadius: '50%', background: '#fff',
        position: 'absolute', top: 3, insetInlineStart: on ? 21 : 3,
        transition: 'all 0.2s', boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
      },
    }),
  );
}

// ==================== Insurance ====================
function Insurance() {
  const providers = [
    { name: 'مصر للتأمين الصحي', patients: 42, claims: 18, approved: 15, pending: 3, amount: 125000, color: 'var(--accent)' },
    { name: 'بوبا العربية', patients: 28, claims: 12, approved: 11, pending: 1, amount: 98000, color: 'var(--info)' },
    { name: 'أكسا للتأمين', patients: 15, claims: 6, approved: 5, pending: 1, amount: 48000, color: 'var(--success)' },
    { name: 'الأهلي للتأمين', patients: 9, claims: 4, approved: 4, pending: 0, amount: 27000, color: 'var(--purple)' },
  ];
  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'التأمين الطبي'),
        h('div', { className: 'page-subtitle' }, '4 شركات تأمين · 40 مطالبة نشطة'),
      ),
      h('button', { className: 'btn primary' }, h(Icons.Plus, { size: 16 }), 'مطالبة جديدة'),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'grid cols-4 mb-24' },
        providers.map((p, i) => h('div', { key: i, className: 'card p-20' },
          h('div', { style: { width: 40, height: 40, borderRadius: 10, background: 'color-mix(in oklab, ' + p.color + ' 15%, var(--bg-elevated))', color: p.color, display: 'grid', placeItems: 'center', marginBottom: 12 } },
            h(Icons.Shield, { size: 20 }),
          ),
          h('div', { style: { fontWeight: 800, fontSize: 14 } }, p.name),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, p.patients + ' مريض'),
          h('div', { style: { fontSize: 20, fontWeight: 800, marginTop: 10 } }, window.fmtEGP(p.amount)),
          h('div', { className: 'flex gap-8 mt-8' },
            h('span', { className: 'chip success', style: { fontSize: 10 } }, p.approved + ' موافقة'),
            p.pending > 0 ? h('span', { className: 'chip warning', style: { fontSize: 10 } }, p.pending + ' معلقة') : null,
          ),
        )),
      ),
      h('div', { className: 'card', style: { overflow: 'hidden' } },
        h('div', { style: { padding: '16px 20px', borderBottom: '1px solid var(--border)', fontWeight: 800 } }, 'المطالبات الأخيرة'),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null, ['رقم المطالبة', 'المريض', 'الشركة', 'التاريخ', 'المبلغ', 'المغطى', 'الحالة'].map((t, i) => h('th', { key: i }, t)))),
          h('tbody', null,
            [
              { id: 'CL-0142', patient: 'أحمد محمد', company: 'مصر للتأمين', date: '2026-04-12', amount: 2500, covered: 2000, status: 'approved' },
              { id: 'CL-0143', patient: 'فاطمة علي', company: 'أكسا', date: '2026-04-15', amount: 1500, covered: 1200, status: 'approved' },
              { id: 'CL-0144', patient: 'محمد عبد الرحمن', company: 'بوبا', date: '2026-04-10', amount: 4500, covered: 3600, status: 'pending' },
              { id: 'CL-0145', patient: 'نورهان إبراهيم', company: 'بوبا', date: '2026-03-28', amount: 500, covered: 0, status: 'rejected' },
            ].map(c => h('tr', { key: c.id },
              h('td', { style: { fontFamily: 'monospace', fontSize: 12, fontWeight: 700 } }, c.id),
              h('td', null, c.patient),
              h('td', null, c.company),
              h('td', { style: { fontSize: 13, color: 'var(--text-secondary)' } }, c.date),
              h('td', { style: { fontWeight: 700 } }, window.fmtEGP(c.amount)),
              h('td', { style: { fontWeight: 700, color: 'var(--success)' } }, window.fmtEGP(c.covered)),
              h('td', null, h('span', { className: 'chip ' + (c.status === 'approved' ? 'success' : c.status === 'pending' ? 'warning' : 'danger') },
                c.status === 'approved' ? 'موافق' : c.status === 'pending' ? 'قيد المراجعة' : 'مرفوض')),
            )),
          ),
        ),
      ),
    ),
  );
}

// ==================== Accounting ====================
const ACCOUNTING_EXPENSE_CATEGORY_OPTIONS = [
  'رواتب',
  'إيجار ومرافق',
  'صيانة ومعدات',
  'تسويق',
  'نقل',
  'اشتراكات',
  'أخرى',
];

function accountingTodayStr() {
  return new Intl.DateTimeFormat('en-CA', { timeZone: 'Africa/Cairo' }).format(new Date());
}

function accountingMonthKey(dateValue) {
  return String(dateValue || '').slice(0, 7);
}

function formatAccountingDate(dateValue) {
  if (!dateValue) return '—';
  const date = new Date(dateValue);
  if (Number.isNaN(date.getTime())) return String(dateValue);
  return window.fmtDate(date);
}

function classifyAccountingExpenseCategory(category) {
  const value = String(category || '').trim();
  if (!value) return 'other';
  if (/راتب|رواتب/u.test(value)) return 'salaries';
  if (/إيجار|ايجار|مرافق|كهرباء|مياه|إنترنت|انترنت/u.test(value)) return 'rent';
  if (/صيانة|معدات/u.test(value)) return 'maintenance';
  return 'other';
}

function openAccountingPrint(title, sections) {
  const body = `
    <div style="font-family:Arial, sans-serif; direction:rtl; padding:24px; max-width:900px; margin:auto">
      <h1 style="margin-bottom:8px">${printableText(title, '')}</h1>
      ${sections.map(section => `
        <div style="margin-bottom:24px">
          <h2 style="font-size:18px; margin:0 0 10px">${printableText(section.title, '')}</h2>
          ${section.rows && section.rows.length ? `
            <table style="width:100%; border-collapse:collapse">
              <thead>
                <tr>
                  ${section.columns.map(col => `<th style="border:1px solid #ddd; padding:8px; text-align:right; background:#f8fafc">${printableText(col, '')}</th>`).join('')}
                </tr>
              </thead>
              <tbody>
                ${section.rows.map(row => `
                  <tr>
                    ${row.map(cell => `<td style="border:1px solid #ddd; padding:8px; text-align:right">${printableText(cell, '')}</td>`).join('')}
                  </tr>
                `).join('')}
              </tbody>
            </table>
          ` : `<p style="color:#64748b">لا توجد بيانات</p>`}
        </div>
      `).join('')}
    </div>
  `;
  return openPrintableWindow({ title, bodyHtml: body, features: 'width=980,height=820' });
}

function AccountingReportModal({ monthLabel, summary, monthlyInvoices, monthlyExpenses, monthlyPurchases, monthlySessions, onClose }) {
  const handlePrint = () => {
    openAccountingPrint('التقرير الشهري - ' + monthLabel, [
      {
        title: 'ملخص الشهر',
        columns: ['المؤشر', 'القيمة'],
        rows: [
          ['الإيرادات', window.fmtEGP(summary.revenue)],
          ['التحصيلات', window.fmtEGP(summary.collections)],
          ['نسبة التحصيل', summary.collectionRate.toFixed(1) + '%'],
          ['المديونيات', window.fmtEGP(summary.receivables)],
          ['المصروفات', window.fmtEGP(summary.expenses)],
          ['الرصيد الحالي', window.fmtEGP(summary.balance)],
          ['متوسط الدفع لكل جلسة', window.fmtEGP(summary.averagePerSession)],
          ['عدد الجلسات', String(summary.sessionCount)],
        ],
      },
      {
        title: 'فواتير الشهر',
        columns: ['التاريخ', 'المريض', 'الطبيب', 'الإجمالي', 'المدفوع'],
        rows: monthlyInvoices.map(inv => [
          formatAccountingDate(inv.date),
          inv.patient || '—',
          inv.doctorName || '—',
          window.fmtEGP(inv.total),
          window.fmtEGP(inv.paid),
        ]),
      },
      {
        title: 'المصروفات العامة',
        columns: ['التاريخ', 'الفئة', 'المستفيد', 'المبلغ'],
        rows: monthlyExpenses.map(exp => [
          formatAccountingDate(exp.date),
          exp.category || 'أخرى',
          exp.recipient || '—',
          window.fmtEGP(Number(exp.amount) || 0),
        ]),
      },
      {
        title: 'مشتريات الماتريال والأدوات',
        columns: ['التاريخ', 'المورد', 'الإجمالي', 'ملاحظات'],
        rows: monthlyPurchases.map(purchase => [
          formatAccountingDate(purchase.date),
          purchase.supplier || '—',
          window.fmtEGP(purchase.total),
          purchase.notes || '—',
        ]),
      },
      {
        title: 'الجلسات',
        columns: ['التاريخ', 'المريض', 'الطبيب', 'المدفوع', 'الشغل المنجز'],
        rows: monthlySessions.map(session => [
          formatAccountingDate(session.date),
          session.patient || '—',
          session.doctor || '—',
          window.fmtEGP(session.paidAmount),
          session.workDone || '—',
        ]),
      },
    ]);
  };

  return h(Fragment, null,
    h('div', { className: 'accounting-backdrop', onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.35)', zIndex: 440 } }),
    h('div', {
      className: 'card accounting-modal',
      style: {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 'min(980px, calc(100vw - 32px))',
        maxHeight: '88vh',
        overflowY: 'auto',
        zIndex: 441,
        padding: 0,
      },
      onClick: (e) => e.stopPropagation(),
    },
      h('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
        h('div', null,
          h('div', { style: { fontSize: 18, fontWeight: 800 } }, 'التقرير الشهري'),
          h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, monthLabel),
        ),
        h('div', { className: 'flex gap-8' },
          h('button', { className: 'btn outline sm', onClick: handlePrint }, h(Icons.Printer, { size: 14 }), 'طباعة / حفظ PDF'),
          h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 16 })),
        ),
      ),
      h('div', { style: { padding: 22 } },
        h('div', { className: 'grid cols-4 mb-16' },
          [
            { label: 'الإيرادات', value: summary.revenue, color: 'var(--accent)' },
            { label: 'التحصيلات', value: summary.collections, color: 'var(--success)' },
            { label: 'المديونيات', value: summary.receivables, color: 'var(--danger)' },
            { label: 'المصروفات', value: summary.expenses, color: 'var(--warning)' },
          ].map((card) => h('div', { key: card.label, className: 'card', style: { padding: 16, background: 'var(--bg-subtle)' } },
            h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 6 } }, card.label),
            h('div', { style: { fontSize: 24, fontWeight: 900, color: card.color } }, window.fmtEGP(card.value)),
          )),
        ),
        h('div', { style: { display: 'grid', gridTemplateColumns: '1.2fr 1fr', gap: 16, marginBottom: 16 } },
          h('div', { className: 'card', style: { padding: 18 } },
            h('div', { style: { fontWeight: 800, marginBottom: 12 } }, 'ملخص الأداء'),
            [
              ['نسبة التحصيل', summary.collectionRate.toFixed(1) + '%'],
              ['الرصيد الحالي', window.fmtEGP(summary.balance)],
              ['متوسط الدفع لكل جلسة', window.fmtEGP(summary.averagePerSession)],
              ['عدد الفواتير', String(monthlyInvoices.length)],
              ['عدد الجلسات', String(summary.sessionCount)],
            ].map(([label, value]) => h('div', {
              key: label,
              style: { display: 'flex', justifyContent: 'space-between', padding: '10px 0', borderBottom: '1px solid var(--border)' },
            },
              h('span', { style: { color: 'var(--text-secondary)' } }, label),
              h('span', { style: { fontWeight: 800 } }, value),
            )),
          ),
          h('div', { className: 'card', style: { padding: 18 } },
            h('div', { style: { fontWeight: 800, marginBottom: 12 } }, 'آخر حركة هذا الشهر'),
            ([
              ...monthlyInvoices.slice(0, 3).map(inv => ({ label: `فاتورة ${inv.patient || '—'}`, date: inv.date, amount: inv.paid, type: 'in' })),
              ...monthlyExpenses.slice(0, 2).map(exp => ({ label: exp.category || 'مصروف', date: exp.date, amount: Number(exp.amount) || 0, type: 'out' })),
              ...monthlyPurchases.slice(0, 2).map(purchase => ({ label: `شراء من ${purchase.supplier || 'مورد'}`, date: purchase.date, amount: purchase.total, type: 'out' })),
            ].sort((a, b) => new Date(b.date || 0) - new Date(a.date || 0)).slice(0, 6)).map((row, idx) => h('div', {
              key: idx,
              style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', borderBottom: idx < 5 ? '1px solid var(--border)' : 'none' },
            },
              h('div', null,
                h('div', { style: { fontWeight: 700, fontSize: 13 } }, row.label),
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, formatAccountingDate(row.date)),
              ),
              h('div', { style: { fontWeight: 800, color: row.type === 'in' ? 'var(--success)' : 'var(--danger)' } },
                (row.type === 'in' ? '+' : '-') + window.fmtEGP(row.amount),
              ),
            )),
          ),
        ),
      ),
    ),
  );
}

function AccountingBreakdownModal({ title, total, rows, type, onClose }) {
  const columnsByType = {
    materials: ['المادة / الصنف', 'المورد', 'التاريخ', 'الكمية', 'سعر الوحدة', 'الإجمالي'],
    salaries: ['الاسم', 'النوع', 'التاريخ', 'المبلغ', 'ملاحظات'],
    generic: ['الوصف', 'الفئة', 'التاريخ', 'المبلغ', 'ملاحظات'],
  };
  const columns = columnsByType[type] || columnsByType.generic;

  return h(Fragment, null,
    h('div', { className: 'accounting-backdrop', onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.35)', zIndex: 442 } }),
    h('div', {
      className: 'card accounting-modal',
      style: {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 'min(980px, calc(100vw - 32px))',
        maxHeight: '88vh',
        overflowY: 'auto',
        zIndex: 443,
        padding: 0,
      },
      onClick: (e) => e.stopPropagation(),
    },
      h('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
        h('div', null,
          h('div', { style: { fontSize: 18, fontWeight: 800 } }, title),
          h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, 'إجمالي ' + window.fmtEGP(total)),
        ),
        h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 16 })),
      ),
      h('div', { style: { padding: 22 } },
        rows.length ? h('table', { className: 'data-table' },
          h('thead', null, h('tr', null, columns.map(col => h('th', { key: col }, col)))),
          h('tbody', null,
            rows.map((row, idx) => h('tr', { key: row.id || idx },
              type === 'materials' ? [
                h('td', { key: 'name' }, row.name || '—'),
                h('td', { key: 'supplier' }, row.supplier || '—'),
                h('td', { key: 'date' }, formatAccountingDate(row.date)),
                h('td', { key: 'qty' }, row.qty || '—'),
                h('td', { key: 'unitPrice' }, window.fmtEGP(row.unitPrice || 0)),
                h('td', { key: 'total', style: { fontWeight: 800 } }, window.fmtEGP(row.total || 0)),
              ] : type === 'salaries' ? [
                h('td', { key: 'recipient' }, row.recipient || '—'),
                h('td', { key: 'source' }, row.source === 'staff' ? 'راتب مسجل على الموظف' : 'مصروف رواتب'),
                h('td', { key: 'date' }, formatAccountingDate(row.date)),
                h('td', { key: 'amount', style: { fontWeight: 800 } }, window.fmtEGP(row.amount || 0)),
                h('td', { key: 'notes' }, row.notes || '—'),
              ] : [
                h('td', { key: 'desc' }, row.description || row.recipient || '—'),
                h('td', { key: 'category' }, row.category || 'أخرى'),
                h('td', { key: 'date' }, formatAccountingDate(row.date)),
                h('td', { key: 'amount', style: { fontWeight: 800 } }, window.fmtEGP(row.amount || 0)),
                h('td', { key: 'notes' }, row.notes || '—'),
              ],
            )),
          ),
        ) : h('div', {
          style: { padding: 40, textAlign: 'center', color: 'var(--text-tertiary)' },
        }, 'لا توجد تفاصيل متاحة حالياً'),
      ),
    ),
  );
}

function AddAccountingExpenseModal({ inventory, onClose, onSaved }) {
  const { clinicId, toast } = useContext(AppContext);
  const today = accountingTodayStr();
  const usageUnitsKey = `senan-inventory-usage-units:${clinicId || 'default'}`;
  const [mode, setMode] = useState('purchase');
  const [saving, setSaving] = useState(false);
  const [usageUnitsMap, setUsageUnitsMap] = useState({});
  const [purchaseForm, setPurchaseForm] = useState({
    supplier: '',
    date: today,
    notes: '',
    items: [{ inventory_id: '', name: '', qty: 1, unit_price: '' }],
  });
  const [expenseForm, setExpenseForm] = useState({
    category: ACCOUNTING_EXPENSE_CATEGORY_OPTIONS[0],
    amount: '',
    recipient: '',
    date: today,
    notes: '',
  });

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(usageUnitsKey);
      setUsageUnitsMap(raw ? JSON.parse(raw) : {});
    } catch (error) {
      console.warn('[Accounting Purchase] failed to load usage units map:', error);
      setUsageUnitsMap({});
    }
  }, [usageUnitsKey]);

  const extractInventoryPackMeta = (invItem) => {
    const cleanName = getInventoryDisplayName(invItem);
    const mappedUsageUnits = getInventoryUsageUnitsPerPack(invItem, usageUnitsMap);
    return {
      cleanName,
      usageUnitsPerPack: mappedUsageUnits,
      unit: invItem?.unit || 'قطعة',
    };
  };

  const getSelectedInventoryMeta = (inventoryId) => {
    const selected = (inventory || []).find(invItem => invItem.id === inventoryId);
    if (!selected) return null;
    return { ...selected, ...extractInventoryPackMeta(selected) };
  };

  const updatePurchaseItem = (index, key, value) => {
    setPurchaseForm(prev => ({
      ...prev,
      items: prev.items.map((item, itemIndex) => {
        if (itemIndex !== index) return item;
        if (key === 'inventory_id') {
          const selected = (inventory || []).find(invItem => invItem.id === value);
          const selectedMeta = selected ? extractInventoryPackMeta(selected) : null;
          return {
            ...item,
            inventory_id: value,
            name: selectedMeta ? selectedMeta.cleanName : item.name,
          };
        }
        return { ...item, [key]: value };
      }),
    }));
  };

  const addPurchaseItem = () => {
    setPurchaseForm(prev => ({
      ...prev,
      items: [...prev.items, { inventory_id: '', name: '', qty: 1, unit_price: '' }],
    }));
  };

  const removePurchaseItem = (index) => {
    setPurchaseForm(prev => ({
      ...prev,
      items: prev.items.filter((_, itemIndex) => itemIndex !== index),
    }));
  };
  const purchaseItemsTotal = purchaseForm.items.reduce((sum, item) => {
    return sum + ((Number(item.qty) || 0) * (Number(item.unit_price) || 0));
  }, 0);
  const handleSave = async () => {
    setSaving(true);
    try {
      if (mode === 'purchase') {
        const rows = purchaseForm.items
          .map(item => ({
            inventory_id: item.inventory_id || null,
            name: String(item.name || '').trim(),
            qty: Number(item.qty) || 0,
            unit_price: Number(item.unit_price) || 0,
          }))
          .filter(item => item.name && item.qty > 0 && item.unit_price >= 0);
        if (!rows.length) {
          toast('أضف صنف شراء واحد على الأقل');
          setSaving(false);
          return;
        }
        const purchase = await DB.addPurchaseInvoice(clinicId, {
          supplier: purchaseForm.supplier.trim() || null,
          date: purchaseForm.date || today,
          notes: purchaseForm.notes.trim() || null,
        }, rows);
        toast('تم تسجيل مشتريات الماتريال ✅');
        onSaved({ type: 'purchase', record: purchase });
      } else {
        const amount = Number(expenseForm.amount) || 0;
        if (amount <= 0) {
          toast('أدخل مبلغ المصروف');
          setSaving(false);
          return;
        }
        const expense = await DB.addExpense(clinicId, {
          category: expenseForm.category || 'أخرى',
          amount,
          recipient: expenseForm.recipient.trim() || null,
          date: expenseForm.date || today,
          notes: expenseForm.notes.trim() || null,
        });
        toast('تم تسجيل المصروف ✅');
        onSaved({ type: 'expense', record: expense });
      }
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر حفظ العملية');
    } finally {
      setSaving(false);
    }
  };

  return h(Fragment, null,
    h('div', { className: 'accounting-backdrop', onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.35)', zIndex: 444 } }),
    h('div', {
      className: 'card accounting-modal',
      style: {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 'min(920px, calc(100vw - 32px))',
        maxHeight: '88vh',
        overflowY: 'auto',
        zIndex: 445,
        padding: 0,
      },
      onClick: (e) => e.stopPropagation(),
    },
      h('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
        h('div', null,
          h('div', { style: { fontSize: 18, fontWeight: 800 } }, 'مصروف جديد'),
          h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, 'سجل شراء ماتريال أو مصروف عام من نفس الشاشة'),
        ),
        h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 16 })),
      ),
      h('div', { style: { padding: 22 } },
        h('div', { className: 'flex gap-8 mb-16' },
          [
            ['purchase', 'مشتريات الماتريال / الأدوات'],
            ['expense', 'مصروف عام'],
          ].map(([value, label]) => h('button', {
            key: value,
            className: 'btn ' + (mode === value ? 'primary' : 'outline'),
            onClick: () => setMode(value),
          }, label)),
        ),
        mode === 'purchase' ? h('div', null,
          h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12, marginBottom: 16 } },
            h('div', null,
              h('div', { className: 'label' }, 'المورد'),
              h('input', {
                className: 'input',
                value: purchaseForm.supplier,
                onChange: (e) => setPurchaseForm(prev => ({ ...prev, supplier: e.target.value })),
                placeholder: 'اسم المورد',
              }),
            ),
            h('div', null,
              h('div', { className: 'label' }, 'التاريخ'),
              h('input', {
                className: 'input',
                type: 'date',
                value: purchaseForm.date,
                onChange: (e) => setPurchaseForm(prev => ({ ...prev, date: e.target.value })),
              }),
            ),
            h('div', { style: { display: 'flex', alignItems: 'flex-end' } },
              h('button', { className: 'btn outline w-full', onClick: addPurchaseItem }, h(Icons.Plus, { size: 14 }), 'إضافة صنف'),
            ),
          ),
          h('div', { className: 'grid', style: { gap: 12 } },
            purchaseForm.items.map((item, index) => {
              const selectedMeta = getSelectedInventoryMeta(item.inventory_id);
              const lineTotal = (Number(item.qty) || 0) * (Number(item.unit_price) || 0);
              return h('div', {
              key: index,
              className: 'card',
              style: { padding: 16, background: 'var(--bg-subtle)' },
            },
              h('div', { style: { display: 'grid', gridTemplateColumns: '1.2fr 1fr 0.6fr 0.6fr 0.7fr auto', gap: 10, alignItems: 'end' } },
                h('div', null,
                  h('div', { className: 'label' }, 'الصنف / المادة'),
                  h('input', {
                    className: 'input',
                    value: item.name,
                    onChange: (e) => updatePurchaseItem(index, 'name', e.target.value),
                    placeholder: 'مثلاً: قفازات، كمامات، بوند',
                  }),
                ),
                h('div', null,
                  h('div', { className: 'label' }, 'من المخزون الحالي'),
                  h('select', {
                    className: 'input',
                    value: item.inventory_id,
                    onChange: (e) => updatePurchaseItem(index, 'inventory_id', e.target.value),
                  },
                    h('option', { value: '' }, 'اختياري'),
                    (inventory || []).map(invItem => {
                      const meta = extractInventoryPackMeta(invItem);
                      return h('option', { key: invItem.id, value: invItem.id }, meta.cleanName);
                    }),
                  ),
                ),
                h('div', null,
                  h('div', { className: 'label' }, selectedMeta ? `الكمية (${selectedMeta.unit})` : 'الكمية'),
                  h('input', {
                    className: 'input',
                    type: 'number',
                    min: '0',
                    value: item.qty,
                    onChange: (e) => updatePurchaseItem(index, 'qty', e.target.value),
                  }),
                ),
                h('div', null,
                  h('div', { className: 'label' }, selectedMeta ? `سعر ${selectedMeta.unit}` : 'سعر الوحدة'),
                  h('input', {
                    className: 'input',
                    type: 'number',
                    min: '0',
                    value: item.unit_price,
                    onChange: (e) => updatePurchaseItem(index, 'unit_price', e.target.value),
                  }),
                ),
                h('div', null,
                  h('div', { className: 'label' }, 'الإجمالي'),
                  h('div', { className: 'input', style: { display: 'flex', alignItems: 'center', fontWeight: 800, background: 'var(--bg-elevated)' } }, window.fmtEGP(lineTotal)),
                ),
                h('button', {
                  className: 'icon-btn',
                  style: { color: 'var(--danger)' },
                  onClick: () => removePurchaseItem(index),
                  disabled: purchaseForm.items.length === 1,
                }, h(Icons.Trash, { size: 14 })),
              ),
              selectedMeta && selectedMeta.usageUnitsPerPack > 0 ? h('div', {
                style: { marginTop: 10, fontSize: 12, color: 'var(--text-tertiary)' },
              }, `هذا الصنف يشتري كوحدة ${selectedMeta.unit}، والعبوة تكفي ${window.fmtNum(selectedMeta.usageUnitsPerPack)} حالة.`) : null,
            );
            }),
          ),
          h('div', {
            style: {
              marginTop: 16,
              padding: 16,
              borderRadius: 'var(--radius-md)',
              background: 'var(--bg-subtle)',
              display: 'flex',
              justifyContent: 'space-between',
              alignItems: 'center',
              fontWeight: 800,
            },
          },
            h('span', { style: { color: 'var(--text-secondary)' } }, 'إجمالي المشتريات'),
            h('span', { style: { fontSize: 18 } }, window.fmtEGP(purchaseItemsTotal)),
          ),
          h('div', { style: { marginTop: 16 } },
            h('div', { className: 'label' }, 'ملاحظات'),
            h('textarea', {
              className: 'textarea',
              rows: 3,
              value: purchaseForm.notes,
              onChange: (e) => setPurchaseForm(prev => ({ ...prev, notes: e.target.value })),
              placeholder: 'أي ملاحظات على الفاتورة أو المشتريات',
            }),
          ),
        ) : h('div', null,
          h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 12, marginBottom: 16 } },
            h('div', null,
              h('div', { className: 'label' }, 'الفئة'),
              h('select', {
                className: 'input',
                value: expenseForm.category,
                onChange: (e) => setExpenseForm(prev => ({ ...prev, category: e.target.value })),
              },
                ACCOUNTING_EXPENSE_CATEGORY_OPTIONS.map(option => h('option', { key: option, value: option }, option)),
              ),
            ),
            h('div', null,
              h('div', { className: 'label' }, 'المبلغ'),
              h('input', {
                className: 'input',
                type: 'number',
                min: '0',
                value: expenseForm.amount,
                onChange: (e) => setExpenseForm(prev => ({ ...prev, amount: e.target.value })),
                placeholder: '0',
              }),
            ),
            h('div', null,
              h('div', { className: 'label' }, 'المستفيد / الجهة'),
              h('input', {
                className: 'input',
                value: expenseForm.recipient,
                onChange: (e) => setExpenseForm(prev => ({ ...prev, recipient: e.target.value })),
                placeholder: 'اسم الشخص أو الجهة',
              }),
            ),
            h('div', null,
              h('div', { className: 'label' }, 'التاريخ'),
              h('input', {
                className: 'input',
                type: 'date',
                value: expenseForm.date,
                onChange: (e) => setExpenseForm(prev => ({ ...prev, date: e.target.value })),
              }),
            ),
          ),
          h('div', null,
            h('div', { className: 'label' }, 'ملاحظات'),
            h('textarea', {
              className: 'textarea',
              rows: 4,
              value: expenseForm.notes,
              onChange: (e) => setExpenseForm(prev => ({ ...prev, notes: e.target.value })),
              placeholder: 'سبب المصروف أو أي تفاصيل إضافية',
            }),
          ),
        ),
      ),
      h('div', { style: { padding: '18px 22px', borderTop: '1px solid var(--border)', display: 'flex', gap: 10, justifyContent: 'flex-end' } },
        h('button', { className: 'btn outline', onClick: onClose }, 'إلغاء'),
        h('button', { className: 'btn primary', onClick: handleSave, disabled: saving },
          saving ? 'جاري الحفظ...' : 'حفظ العملية',
        ),
      ),
    ),
  );
}

function AccountingTransactionsModal({ transactions, onClose, onEdit, onDelete }) {
  const [typeFilter, setTypeFilter] = useState('all');
  const [fromDate, setFromDate] = useState('');
  const [toDate, setToDate] = useState('');
  const [showDateFilter, setShowDateFilter] = useState(false);
  const [activeDatePreset, setActiveDatePreset] = useState('all');
  const selectedRangeLabel = window.getDateRangeLabel
    ? window.getDateRangeLabel(fromDate, toDate)
    : 'كل التواريخ';

  const applyDatePreset = (presetKey) => {
    const { fromValue, toValue } = window.resolveDateRangePreset
      ? window.resolveDateRangePreset(presetKey)
      : { fromValue: '', toValue: '' };
    setFromDate(fromValue || '');
    setToDate(toValue || '');
    setActiveDatePreset(presetKey);
    setShowDateFilter(false);
  };

  const clearDateRange = () => {
    setFromDate('');
    setToDate('');
    setActiveDatePreset('all');
    setShowDateFilter(false);
  };

  const visibleTransactions = useMemo(() => (
    (transactions || []).filter(tx => {
      if (typeFilter !== 'all') {
        if (typeFilter === 'income' && tx.flow !== 'in') return false;
        if (typeFilter === 'session' && tx.kind !== 'session') return false;
        if (typeFilter === 'expense' && tx.kind !== 'expense') return false;
        if (typeFilter === 'purchase' && tx.kind !== 'purchase') return false;
      }
      if (fromDate && (tx.date || '') < fromDate) return false;
      if (toDate && (tx.date || '') > toDate) return false;
      return true;
    })
  ), [transactions, typeFilter, fromDate, toDate]);

  const filteredTotalIn = visibleTransactions.filter(tx => tx.flow === 'in').reduce((sum, tx) => sum + (Number(tx.amount) || 0), 0);
  const filteredTotalOut = visibleTransactions.filter(tx => tx.flow === 'out').reduce((sum, tx) => sum + (Number(tx.amount) || 0), 0);

  return h(Fragment, null,
    h('div', { className: 'accounting-backdrop', onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.35)', zIndex: 446 } }),
    h('div', {
      className: 'card accounting-modal',
      style: {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 'min(1180px, calc(100vw - 24px))',
        maxHeight: '90vh',
        overflowY: 'auto',
        zIndex: 447,
        padding: 0,
      },
      onClick: (e) => e.stopPropagation(),
    },
      h('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 } },
        h('div', null,
          h('div', { style: { fontSize: 18, fontWeight: 800 } }, 'عرض كل المعاملات'),
          h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, 'فلتر بالتاريخ ثم عدّل أو احذف المصروفات والمشتريات'),
        ),
        h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 16 })),
      ),
      h('div', { style: { padding: 22 } },
        h('div', { className: 'grid cols-4 mb-16' },
          [
            { label: 'إجمالي الداخل', value: filteredTotalIn, color: 'var(--success)' },
            { label: 'إجمالي الخارج', value: filteredTotalOut, color: 'var(--danger)' },
            { label: 'عدد البنود', value: visibleTransactions.length, color: 'var(--accent)' },
            { label: 'الفرق', value: filteredTotalIn - filteredTotalOut, color: filteredTotalIn - filteredTotalOut >= 0 ? 'var(--success)' : 'var(--danger)' },
          ].map(card => h('div', { key: card.label, className: 'card', style: { padding: 14, background: 'var(--bg-subtle)' } },
            h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 6 } }, card.label),
            h('div', { style: { fontSize: 20, fontWeight: 900, color: card.color } }, typeof card.value === 'number' ? window.fmtEGP(card.value) : card.value),
          )),
        ),
        h('div', { className: 'card', style: { padding: 16, marginBottom: 16, background: 'var(--bg-subtle)' } },
          h('div', { style: { display: 'grid', gridTemplateColumns: 'minmax(260px, 1.2fr) 1fr auto', gap: 10, alignItems: 'end' } },
            h(Shell.DateRangeFilter, {
              title: 'فلتر التاريخ',
              subtitle: 'اختر فترة جاهزة أو حدد من يوم إلى يوم',
              dateFrom: fromDate,
              dateTo: toDate,
              open: showDateFilter,
              onToggle: () => setShowDateFilter(prev => !prev),
              onClose: () => setShowDateFilter(false),
              onPresetSelect: applyDatePreset,
              activePreset: activeDatePreset,
              onFromChange: (value) => {
                setFromDate(value);
                setActiveDatePreset('custom');
              },
              onToChange: (value) => {
                setToDate(value);
                setActiveDatePreset('custom');
              },
              onClear: clearDateRange,
              onApply: () => setShowDateFilter(false),
              align: 'start',
              buttonWidth: '100%',
              menuWidth: 'min(420px, calc(100vw - 48px))',
            }),
            h('div', null,
              h('div', { className: 'label' }, 'النوع'),
              h('select', { className: 'input', value: typeFilter, onChange: e => setTypeFilter(e.target.value) },
                h('option', { value: 'all' }, 'الكل'),
                h('option', { value: 'income' }, 'تحصيلات'),
                h('option', { value: 'session' }, 'جلسات'),
                h('option', { value: 'expense' }, 'مصروفات'),
                h('option', { value: 'purchase' }, 'مشتريات'),
              ),
            ),
            h('button', {
              className: 'btn outline',
              onClick: () => { clearDateRange(); setTypeFilter('all'); },
            }, 'إعادة ضبط'),
          ),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 10 } }, selectedRangeLabel),
        ),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null, ['التاريخ', 'النوع', 'البيان', 'المبلغ', 'الإجراء'].map((t, i) => h('th', { key: i }, t)))),
          h('tbody', null,
            visibleTransactions.length ? visibleTransactions.map(tx => h('tr', { key: tx.id },
              h('td', null, formatAccountingDate(tx.date)),
              h('td', null,
                h('span', {
                  className: 'chip ' + (tx.flow === 'in' ? 'success' : tx.kind === 'purchase' ? 'accent' : 'danger'),
                }, tx.kind === 'invoice' ? 'فاتورة' : tx.kind === 'session' ? 'جلسة' : tx.kind === 'purchase' ? 'مشتريات' : 'مصروف'),
              ),
              h('td', null,
                h('div', null,
                  h('div', { style: { fontWeight: 700 } }, tx.label),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 2 } }, tx.subLabel || '—'),
                ),
              ),
              h('td', { style: { fontWeight: 800, color: tx.flow === 'in' ? 'var(--success)' : 'var(--danger)' } },
                (tx.flow === 'in' ? '+' : '-') + window.fmtEGP(tx.amount),
              ),
              h('td', null,
                h('div', { className: 'flex gap-4' },
                  tx.editable ? h('button', {
                    className: 'icon-btn',
                    title: 'تعديل',
                    onClick: () => onEdit(tx),
                  }, h(Icons.Edit, { size: 14 })) : h('span', { style: { color: 'var(--text-tertiary)', fontSize: 12 } }, '—'),
                  tx.editable ? h('button', {
                    className: 'icon-btn',
                    title: 'حذف',
                    style: { color: 'var(--danger)' },
                    onClick: () => onDelete(tx),
                  }, h(Icons.Trash, { size: 14 })) : null,
                ),
              ),
            )) : h('tr', null, h('td', { colSpan: 5, style: { textAlign: 'center', padding: 30, color: 'var(--text-tertiary)' } }, 'لا توجد معاملات مطابقة للفلتر')),
          ),
        ),
      ),
    ),
  );
}

function EditAccountingExpenseModal({ expense, onClose, onSaved, onDeleted }) {
  const { toast } = useContext(AppContext);
  const [form, setForm] = useState({
    category: expense.category || 'أخرى',
    amount: String(expense.amount || ''),
    recipient: expense.recipient || '',
    date: expense.date || new Date().toISOString().split('T')[0],
    notes: expense.notes || '',
  });
  const [saving, setSaving] = useState(false);

  const handleSave = async () => {
    const amount = Number(form.amount) || 0;
    if (amount <= 0) { toast('أدخل مبلغ المصروف'); return; }
    setSaving(true);
    try {
      const updated = await DB.updateExpense(expense.id, {
        category: form.category || 'أخرى',
        amount,
        recipient: form.recipient.trim() || null,
        date: form.date || new Date().toISOString().split('T')[0],
        notes: form.notes.trim() || null,
      });
      onSaved(updated);
      toast('تم تعديل المصروف');
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر تعديل المصروف');
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!confirm('حذف هذا المصروف؟')) return;
    setSaving(true);
    try {
      await DB.deleteExpense(expense.id);
      onDeleted(expense.id);
      toast('تم حذف المصروف');
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر حذف المصروف');
    } finally {
      setSaving(false);
    }
  };

  return h(Fragment, null,
    h('div', { className: 'accounting-backdrop', onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.35)', zIndex: 448 } }),
    h('div', {
      className: 'card accounting-modal',
      style: {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 'min(760px, calc(100vw - 24px))',
        zIndex: 449,
        padding: 0,
      },
      onClick: e => e.stopPropagation(),
    },
      h('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
        h('div', null,
          h('div', { style: { fontSize: 18, fontWeight: 800 } }, 'تعديل مصروف'),
          h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, 'يمكنك تعديل الفئة أو المبلغ أو المستفيد'),
        ),
        h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 16 })),
      ),
      h('div', { style: { padding: 22 } },
        h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 12 } },
          h('div', null,
            h('div', { className: 'label' }, 'الفئة'),
            h('select', {
              className: 'input',
              value: form.category,
              onChange: e => setForm(prev => ({ ...prev, category: e.target.value })),
            },
              ACCOUNTING_EXPENSE_CATEGORY_OPTIONS.map(option => h('option', { key: option, value: option }, option)),
            ),
          ),
          h('div', null,
            h('div', { className: 'label' }, 'المبلغ'),
            h('input', {
              className: 'input',
              type: 'number',
              min: '0',
              value: form.amount,
              onChange: e => setForm(prev => ({ ...prev, amount: e.target.value })),
            }),
          ),
          h('div', null,
            h('div', { className: 'label' }, 'المستفيد / الجهة'),
            h('input', {
              className: 'input',
              value: form.recipient,
              onChange: e => setForm(prev => ({ ...prev, recipient: e.target.value })),
            }),
          ),
          h('div', null,
            h('div', { className: 'label' }, 'التاريخ'),
            h('input', {
              className: 'input',
              type: 'date',
              value: form.date,
              onChange: e => setForm(prev => ({ ...prev, date: e.target.value })),
            }),
          ),
        ),
        h('div', { style: { marginTop: 16 } },
          h('div', { className: 'label' }, 'ملاحظات'),
          h('textarea', {
            className: 'textarea',
            rows: 4,
            value: form.notes,
            onChange: e => setForm(prev => ({ ...prev, notes: e.target.value })),
          }),
        ),
      ),
      h('div', { style: { padding: '18px 22px', borderTop: '1px solid var(--border)', display: 'flex', gap: 10, justifyContent: 'space-between' } },
        h('button', { className: 'btn outline', style: { color: 'var(--danger)' }, onClick: handleDelete, disabled: saving }, h(Icons.Trash, { size: 14 }), 'حذف'),
        h('div', { className: 'flex gap-8' },
          h('button', { className: 'btn outline', onClick: onClose }, 'إلغاء'),
          h('button', { className: 'btn primary', onClick: handleSave, disabled: saving }, saving ? 'جاري الحفظ...' : 'حفظ التعديل'),
        ),
      ),
    ),
  );
}

function EditPurchaseInvoiceModal({ purchase, inventory, onClose, onSaved, onDeleted }) {
  const { toast, clinicId } = useContext(AppContext);
  const usageUnitsKey = `senan-inventory-usage-units:${clinicId || 'default'}`;
  const [usageUnitsMap, setUsageUnitsMap] = useState({});
  const [form, setForm] = useState({
    supplier: purchase.supplier || '',
    date: purchase.date || new Date().toISOString().split('T')[0],
    notes: purchase.notes || '',
    items: (purchase.items && purchase.items.length ? purchase.items : [{ inventoryId: '', name: '', qty: 1, unitPrice: 0 }]).map(item => ({
      inventory_id: item.inventoryId || item.inventory_id || '',
      name: item.name || '',
      qty: item.qty || 1,
      unit_price: item.unitPrice || item.unit_price || 0,
    })),
  });
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(usageUnitsKey);
      setUsageUnitsMap(raw ? JSON.parse(raw) : {});
    } catch (error) {
      console.warn('[Edit Purchase] failed to load usage units map:', error);
      setUsageUnitsMap({});
    }
  }, [usageUnitsKey]);

  const extractInventoryPackMeta = (invItem) => {
    const cleanName = getInventoryDisplayName(invItem);
    const mappedUsageUnits = getInventoryUsageUnitsPerPack(invItem, usageUnitsMap);
    return {
      cleanName,
      usageUnitsPerPack: mappedUsageUnits,
      unit: invItem?.unit || 'قطعة',
    };
  };

  const getSelectedInventoryMeta = (inventoryId) => {
    const selected = (inventory || []).find(invItem => invItem.id === inventoryId);
    if (!selected) return null;
    return { ...selected, ...extractInventoryPackMeta(selected) };
  };

  const setItem = (index, key, value) => {
    setForm(prev => ({
      ...prev,
      items: prev.items.map((item, itemIndex) => {
        if (itemIndex !== index) return item;
        if (key === 'inventory_id') {
          const selected = (inventory || []).find(invItem => invItem.id === value);
          const selectedMeta = selected ? extractInventoryPackMeta(selected) : null;
          return { ...item, inventory_id: value, name: selectedMeta ? selectedMeta.cleanName : item.name };
        }
        return { ...item, [key]: value };
      }),
    }));
  };

  const addItem = () => setForm(prev => ({ ...prev, items: [...prev.items, { inventory_id: '', name: '', qty: 1, unit_price: 0 }] }));
  const removeItem = (index) => setForm(prev => ({ ...prev, items: prev.items.filter((_, itemIndex) => itemIndex !== index) }));
  const purchaseItemsTotal = form.items.reduce((sum, item) => {
    return sum + ((Number(item.qty) || 0) * (Number(item.unit_price) || 0));
  }, 0);

  const handleSave = async () => {
    const rows = form.items
      .map(item => ({
        inventory_id: item.inventory_id || null,
        name: String(item.name || '').trim(),
        qty: Number(item.qty) || 0,
        unit_price: Number(item.unit_price) || 0,
      }))
      .filter(item => item.name && item.qty > 0 && item.unit_price >= 0);
    if (!rows.length) {
      toast('أضف صنف شراء واحد على الأقل');
      return;
    }
    setSaving(true);
    try {
      const updated = await DB.updatePurchaseInvoice(purchase.id, {
        supplier: form.supplier.trim() || null,
        date: form.date || new Date().toISOString().split('T')[0],
        notes: form.notes.trim() || null,
      }, rows);
      onSaved(updated);
      toast('تم تعديل فاتورة المشتريات');
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر تعديل الفاتورة');
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!confirm('حذف فاتورة المشتريات؟ سيتم عكس تأثيرها على المخزون.')) return;
    setSaving(true);
    try {
      await DB.deletePurchaseInvoice(purchase.id);
      onDeleted(purchase.id);
      toast('تم حذف فاتورة المشتريات');
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر حذف الفاتورة');
    } finally {
      setSaving(false);
    }
  };

  return h(Fragment, null,
    h('div', { className: 'accounting-backdrop', onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.35)', zIndex: 450 } }),
    h('div', {
      className: 'card accounting-modal',
      style: {
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 'min(980px, calc(100vw - 24px))',
        maxHeight: '90vh',
        overflowY: 'auto',
        zIndex: 451,
        padding: 0,
      },
      onClick: e => e.stopPropagation(),
    },
      h('div', { style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 } },
        h('div', null,
          h('div', { style: { fontSize: 18, fontWeight: 800 } }, 'تعديل فاتورة مشتريات'),
          h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)', marginTop: 4 } }, purchase.supplier || 'فاتورة مشتريات'),
        ),
        h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 16 })),
      ),
      h('div', { style: { padding: 22 } },
        h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12, marginBottom: 16 } },
          h('div', null,
            h('div', { className: 'label' }, 'المورد'),
            h('input', { className: 'input', value: form.supplier, onChange: e => setForm(prev => ({ ...prev, supplier: e.target.value })) }),
          ),
          h('div', null,
            h('div', { className: 'label' }, 'التاريخ'),
            h('input', { className: 'input', type: 'date', value: form.date, onChange: e => setForm(prev => ({ ...prev, date: e.target.value })) }),
          ),
          h('div', { style: { display: 'flex', alignItems: 'flex-end' } },
            h('button', { className: 'btn outline w-full', onClick: addItem }, h(Icons.Plus, { size: 14 }), 'إضافة صنف'),
          ),
        ),
        h('div', { className: 'grid', style: { gap: 12 } },
          form.items.map((item, index) => {
            const selectedMeta = getSelectedInventoryMeta(item.inventory_id);
            const lineTotal = (Number(item.qty) || 0) * (Number(item.unit_price) || 0);
            return h('div', { key: index, className: 'card', style: { padding: 16, background: 'var(--bg-subtle)' } },
            h('div', { style: { display: 'grid', gridTemplateColumns: '1.2fr 1fr 0.6fr 0.6fr 0.7fr auto', gap: 10, alignItems: 'end' } },
              h('div', null,
                h('div', { className: 'label' }, 'الصنف / المادة'),
                h('input', { className: 'input', value: item.name, onChange: e => setItem(index, 'name', e.target.value) }),
              ),
              h('div', null,
                h('div', { className: 'label' }, 'من المخزون الحالي'),
                h('select', { className: 'input', value: item.inventory_id, onChange: e => setItem(index, 'inventory_id', e.target.value) },
                  h('option', { value: '' }, 'اختياري'),
                  (inventory || []).map(invItem => {
                    const meta = extractInventoryPackMeta(invItem);
                    return h('option', { key: invItem.id, value: invItem.id }, meta.cleanName);
                  }),
                ),
              ),
              h('div', null,
                h('div', { className: 'label' }, selectedMeta ? `الكمية (${selectedMeta.unit})` : 'الكمية'),
                h('input', { className: 'input', type: 'number', min: '0', value: item.qty, onChange: e => setItem(index, 'qty', e.target.value) }),
              ),
              h('div', null,
                h('div', { className: 'label' }, selectedMeta ? `سعر ${selectedMeta.unit}` : 'سعر الوحدة'),
                h('input', { className: 'input', type: 'number', min: '0', value: item.unit_price, onChange: e => setItem(index, 'unit_price', e.target.value) }),
              ),
              h('div', null,
                h('div', { className: 'label' }, 'الإجمالي'),
                h('div', { className: 'input', style: { display: 'flex', alignItems: 'center', fontWeight: 800, background: 'var(--bg-elevated)' } }, window.fmtEGP(lineTotal)),
              ),
              h('button', {
                className: 'icon-btn',
                style: { color: 'var(--danger)' },
                onClick: () => removeItem(index),
                disabled: form.items.length === 1,
              }, h(Icons.Trash, { size: 14 })),
            ),
            selectedMeta && selectedMeta.usageUnitsPerPack > 0 ? h('div', {
              style: { marginTop: 10, fontSize: 12, color: 'var(--text-tertiary)' },
            }, `هذا الصنف يشتري كوحدة ${selectedMeta.unit}، والعبوة تكفي ${window.fmtNum(selectedMeta.usageUnitsPerPack)} حالة.`) : null,
          );
          }),
        ),
        h('div', {
          style: {
            marginTop: 16,
            padding: 16,
            borderRadius: 'var(--radius-md)',
            background: 'var(--bg-subtle)',
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            fontWeight: 800,
          },
        },
          h('span', { style: { color: 'var(--text-secondary)' } }, 'إجمالي المشتريات'),
          h('span', { style: { fontSize: 18 } }, window.fmtEGP(purchaseItemsTotal)),
        ),
        h('div', { style: { marginTop: 16 } },
          h('div', { className: 'label' }, 'ملاحظات'),
          h('textarea', { className: 'textarea', rows: 4, value: form.notes, onChange: e => setForm(prev => ({ ...prev, notes: e.target.value })) }),
        ),
      ),
      h('div', { style: { padding: '18px 22px', borderTop: '1px solid var(--border)', display: 'flex', gap: 10, justifyContent: 'space-between' } },
        h('button', { className: 'btn outline', style: { color: 'var(--danger)' }, onClick: handleDelete, disabled: saving }, h(Icons.Trash, { size: 14 }), 'حذف'),
        h('div', { className: 'flex gap-8' },
          h('button', { className: 'btn outline', onClick: onClose }, 'إلغاء'),
          h('button', { className: 'btn primary', onClick: handleSave, disabled: saving }, saving ? 'جاري الحفظ...' : 'حفظ التعديل'),
        ),
      ),
    ),
  );
}

function Accounting() {
  const { invoices, expenses, inventory, staff, clinicId, toast, setExpenses, refreshData } = useContext(AppContext);
  const [purchaseInvoices, setPurchaseInvoices] = useState([]);
  const [sessions, setSessions] = useState([]);
  const [loadingExtras, setLoadingExtras] = useState(false);
  const [detailModal, setDetailModal] = useState(null);
  const [showExpenseModal, setShowExpenseModal] = useState(false);
  const [showReportModal, setShowReportModal] = useState(false);
  const [showTransactionsModal, setShowTransactionsModal] = useState(false);
  const [editingTransaction, setEditingTransaction] = useState(null);

  const allInvoices = (invoices && invoices.length) ? invoices : (window.INVOICES || []);
  const allExpenses = (expenses && expenses.length) ? expenses : [];
  const allInventory = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
  const todayStr = accountingTodayStr();
  const currentMonth = accountingMonthKey(todayStr);
  const monthLabel = window.fmtMonthYear(new Date(todayStr));

  const loadAccountingExtras = useCallback(async () => {
    if (!clinicId) return;
    setLoadingExtras(true);
    try {
      const [purchaseRows, sessionRows] = await Promise.all([
        DB.getPurchaseInvoices(clinicId),
        DB.getClinicSessions(clinicId),
      ]);
      setPurchaseInvoices(purchaseRows || []);
      setSessions(sessionRows || []);
    } catch (error) {
      console.error('[Accounting] failed to load extras:', error);
      setPurchaseInvoices([]);
      setSessions([]);
      toast('تعذر تحميل تفاصيل المحاسبة');
    } finally {
      setLoadingExtras(false);
    }
  }, [clinicId, toast]);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      if (cancelled) return;
      await loadAccountingExtras();
    })();
    return () => { cancelled = true; };
  }, [loadAccountingExtras]);

  useEffect(() => {
    const onRefresh = () => loadAccountingExtras();
    window.addEventListener('senan:accounting-refresh', onRefresh);
    return () => window.removeEventListener('senan:accounting-refresh', onRefresh);
  }, [loadAccountingExtras]);

  const metrics = useMemo(() => {
    const revenue = allInvoices.reduce((sum, inv) => sum + (Number(inv.total) || 0), 0);
    const collections = allInvoices.reduce((sum, inv) => sum + (Number(inv.paid) || 0), 0);
    const receivables = Math.max(0, revenue - collections);
    const expensesOnly = allExpenses.reduce((sum, exp) => sum + (Number(exp.amount) || 0), 0);
    const materialsExpenses = purchaseInvoices.reduce((sum, purchase) => sum + (Number(purchase.total) || 0), 0);
    const totalExpenses = expensesOnly + materialsExpenses;
    const sessionCount = sessions.length;
    return {
      revenue,
      collections,
      collectionRate: revenue > 0 ? (collections / revenue) * 100 : 0,
      receivables,
      expenses: totalExpenses,
      materialsExpenses,
      expensesOnly,
      balance: collections - totalExpenses,
      averagePerSession: sessionCount > 0 ? collections / sessionCount : 0,
      sessionCount,
    };
  }, [allExpenses, allInvoices, purchaseInvoices, sessions]);

  const salaryEntries = useMemo(() => {
    const expenseRows = allExpenses
      .filter(exp => classifyAccountingExpenseCategory(exp.category) === 'salaries')
      .map(exp => ({
        id: exp.id,
        recipient: exp.recipient || 'موظف غير محدد',
        amount: Number(exp.amount) || 0,
        date: exp.date || exp.created_at || '',
        notes: exp.notes || '',
        source: 'expense',
      }));
    const existingRecipients = new Set(expenseRows.map(row => `${row.recipient}|${row.amount}`));
    const fallbackStaffRows = (staff || [])
      .map(member => {
        const amount = Number(member.salary || member.base_salary || member.monthly_salary || 0) || 0;
        if (!amount) return null;
        const key = `${member.name || ''}|${amount}`;
        if (existingRecipients.has(key)) return null;
        return {
          id: member.id,
          recipient: member.name || 'موظف',
          amount,
          date: todayStr,
          notes: member.role || '',
          source: 'staff',
        };
      })
      .filter(Boolean);
    return [...expenseRows, ...fallbackStaffRows];
  }, [allExpenses, staff, todayStr]);

  const materialEntries = useMemo(() => (
    purchaseInvoices.flatMap(purchase => {
      if (!Array.isArray(purchase.items) || !purchase.items.length) {
        return [{
          id: purchase.id,
          name: purchase.notes || 'فاتورة مشتريات',
          supplier: purchase.supplier || '—',
          date: purchase.date,
          qty: 1,
          unitPrice: Number(purchase.total) || 0,
          total: Number(purchase.total) || 0,
        }];
      }
      return purchase.items.map(item => ({
        id: item.id,
        name: item.name || 'صنف غير محدد',
        supplier: purchase.supplier || '—',
        date: purchase.date,
        qty: item.qty || 0,
        unitPrice: item.unitPrice || 0,
        total: item.total || 0,
      }));
    })
  ), [purchaseInvoices]);

  const otherExpenseGroups = useMemo(() => {
    const groups = {
      rent: allExpenses.filter(exp => classifyAccountingExpenseCategory(exp.category) === 'rent'),
      maintenance: allExpenses.filter(exp => classifyAccountingExpenseCategory(exp.category) === 'maintenance'),
      other: allExpenses.filter(exp => classifyAccountingExpenseCategory(exp.category) === 'other'),
    };
    return groups;
  }, [allExpenses]);

  const expenseDistribution = useMemo(() => {
    const rows = [
      {
        key: 'materials',
        label: 'الماتريال والمستلزمات',
        color: 'var(--info)',
        total: metrics.materialsExpenses,
        rows: materialEntries,
        type: 'materials',
      },
      {
        key: 'salaries',
        label: 'الرواتب',
        color: 'var(--accent)',
        total: salaryEntries.reduce((sum, row) => sum + (row.amount || 0), 0),
        rows: salaryEntries,
        type: 'salaries',
      },
      {
        key: 'rent',
        label: 'الإيجار والمرافق',
        color: 'var(--warning)',
        total: otherExpenseGroups.rent.reduce((sum, row) => sum + (Number(row.amount) || 0), 0),
        rows: otherExpenseGroups.rent.map(row => ({
          id: row.id,
          description: row.recipient || row.notes || 'مصروف مرافق',
          category: row.category,
          date: row.date || row.created_at || '',
          amount: Number(row.amount) || 0,
          notes: row.notes || '',
        })),
        type: 'generic',
      },
      {
        key: 'maintenance',
        label: 'الصيانة والمعدات',
        color: 'var(--success)',
        total: otherExpenseGroups.maintenance.reduce((sum, row) => sum + (Number(row.amount) || 0), 0),
        rows: otherExpenseGroups.maintenance.map(row => ({
          id: row.id,
          description: row.recipient || row.notes || 'صيانة أو معدات',
          category: row.category,
          date: row.date || row.created_at || '',
          amount: Number(row.amount) || 0,
          notes: row.notes || '',
        })),
        type: 'generic',
      },
      {
        key: 'other',
        label: 'مصاريف أخرى',
        color: 'var(--purple)',
        total: otherExpenseGroups.other.reduce((sum, row) => sum + (Number(row.amount) || 0), 0),
        rows: otherExpenseGroups.other.map(row => ({
          id: row.id,
          description: row.recipient || row.notes || 'مصروف عام',
          category: row.category,
          date: row.date || row.created_at || '',
          amount: Number(row.amount) || 0,
          notes: row.notes || '',
        })),
        type: 'generic',
      },
    ];
    return rows.filter(row => row.total > 0 || row.rows.length > 0);
  }, [materialEntries, metrics.materialsExpenses, otherExpenseGroups, salaryEntries]);

  const allTransactions = useMemo(() => (
    [
      ...allInvoices
        .map(inv => ({
          id: 'invoice-' + inv.id,
          kind: 'invoice',
          flow: 'in',
          label: `فاتورة ${inv.patient || '—'}`,
          subLabel: (() => {
            const total = Number(inv.total) || 0;
            const paid = Number(inv.paid) || 0;
            const remaining = Math.max(0, total - paid);
            return paid > 0
              ? `إجمالي: ${window.fmtEGP(total)} · مدفوع: ${window.fmtEGP(paid)} · متبقي: ${window.fmtEGP(remaining)}`
              : `إجمالي الفاتورة: ${window.fmtEGP(total)}`;
          })(),
          amount: Number(inv.total) || 0,
          date: inv.date || inv.created_at || '',
          created_at: inv.created_at || '',
          editable: false,
        })),
      ...sessions
        .filter(session => (Number(session.paidAmount) || 0) > 0)
        .map(session => ({
          id: 'session-' + session.id,
          kind: 'session',
          flow: 'in',
          label: `جلسة ${session.patient || '—'}`,
          subLabel: [
            session.doctor || '',
            session.workDone || '',
            session.invoiceId ? `فاتورة ${session.invoiceId}` : '',
          ].filter(Boolean).join(' · ') || '—',
          amount: Number(session.paidAmount) || 0,
          date: session.date || session.created_at || '',
          created_at: session.created_at || '',
          editable: false,
        })),
      ...allExpenses.map(exp => ({
        id: 'expense-' + exp.id,
        kind: 'expense',
        flow: 'out',
        label: exp.category || 'مصروف عام',
        subLabel: exp.recipient || exp.notes || '—',
        amount: Number(exp.amount) || 0,
        date: exp.date || exp.created_at || '',
        created_at: exp.created_at || '',
        editable: true,
        record: exp,
      })),
      ...purchaseInvoices.map(purchase => ({
        id: 'purchase-' + purchase.id,
        kind: 'purchase',
        flow: 'out',
        label: `شراء ${purchase.supplier || 'مورد'}`,
        subLabel: `${(purchase.items || []).length} أصناف`,
        amount: Number(purchase.total) || 0,
        date: purchase.date || purchase.created_at || '',
        created_at: purchase.created_at || '',
        editable: true,
        record: purchase,
      })),
    ]
      .filter(item => item.amount > 0)
      .sort((a, b) => {
        const aTime = new Date(a.created_at || a.date || 0).getTime();
        const bTime = new Date(b.created_at || b.date || 0).getTime();
        if (bTime !== aTime) return bTime - aTime;
        return new Date(b.date || 0).getTime() - new Date(a.date || 0).getTime();
      })
  ), [allExpenses, allInvoices, purchaseInvoices, sessions]);

  const latestTransactions = useMemo(() => allTransactions.slice(0, 8), [allTransactions]);

  const monthlyData = useMemo(() => {
    const monthlyInvoices = allInvoices.filter(inv => accountingMonthKey(inv.date || inv.created_at) === currentMonth);
    const monthlyExpenses = allExpenses.filter(exp => accountingMonthKey(exp.date || exp.created_at) === currentMonth);
    const monthlyPurchases = purchaseInvoices.filter(purchase => accountingMonthKey(purchase.date || purchase.created_at) === currentMonth);
    const monthlySessions = sessions.filter(session => accountingMonthKey(session.date || session.created_at) === currentMonth);
    const monthlyRevenue = monthlyInvoices.reduce((sum, inv) => sum + (Number(inv.total) || 0), 0);
    const monthlyCollections = monthlyInvoices.reduce((sum, inv) => sum + (Number(inv.paid) || 0), 0);
    const monthlyExpensesTotal = monthlyExpenses.reduce((sum, exp) => sum + (Number(exp.amount) || 0), 0)
      + monthlyPurchases.reduce((sum, purchase) => sum + (Number(purchase.total) || 0), 0);
    return {
      monthlyInvoices,
      monthlyExpenses,
      monthlyPurchases,
      monthlySessions,
      summary: {
        revenue: monthlyRevenue,
        collections: monthlyCollections,
        collectionRate: monthlyRevenue > 0 ? (monthlyCollections / monthlyRevenue) * 100 : 0,
        receivables: Math.max(0, monthlyRevenue - monthlyCollections),
        expenses: monthlyExpensesTotal,
        balance: monthlyCollections - monthlyExpensesTotal,
        averagePerSession: monthlySessions.length ? monthlyCollections / monthlySessions.length : 0,
        sessionCount: monthlySessions.length,
      },
    };
  }, [allExpenses, allInvoices, currentMonth, purchaseInvoices, sessions]);

  const handleAccountingSaved = ({ type, record }) => {
    if (type === 'expense') {
      setExpenses(prev => [record, ...(prev || [])]);
      return;
    }
    if (type === 'purchase') {
      setPurchaseInvoices(prev => [record, ...(prev || [])]);
      refreshData && refreshData();
      loadAccountingExtras();
    }
  };

  const handleExpenseUpdated = (updated) => {
    setExpenses(prev => (prev || []).map(exp => exp.id === updated.id ? updated : exp));
  };

  const handleExpenseDeleted = (id) => {
    setExpenses(prev => (prev || []).filter(exp => exp.id !== id));
  };

  const handlePurchaseUpdated = (updated) => {
    setPurchaseInvoices(prev => (prev || []).map(item => item.id === updated.id ? updated : item));
    refreshData && refreshData();
    loadAccountingExtras();
  };

  const handlePurchaseDeleted = (id) => {
    setPurchaseInvoices(prev => (prev || []).filter(item => item.id !== id));
    refreshData && refreshData();
    loadAccountingExtras();
  };

  const openTransactionEditor = (tx) => {
    if (!tx || !tx.editable) return;
    setEditingTransaction(tx);
    setShowTransactionsModal(false);
  };

  const deleteTransaction = async (tx) => {
    if (!tx || !tx.editable) return;
    if (!confirm(tx.kind === 'purchase' ? 'حذف فاتورة المشتريات؟' : 'حذف هذا المصروف؟')) return;
    try {
      if (tx.kind === 'purchase') {
        await DB.deletePurchaseInvoice(tx.record.id);
        handlePurchaseDeleted(tx.record.id);
      } else if (tx.kind === 'expense') {
        await DB.deleteExpense(tx.record.id);
        handleExpenseDeleted(tx.record.id);
      }
      toast('تم الحذف بنجاح');
    } catch (error) {
      console.error(error);
      toast('تعذر الحذف');
    }
  };

  return h('div', { className: 'fade-in' },
    showTransactionsModal ? h(AccountingTransactionsModal, {
      transactions: allTransactions,
      onClose: () => setShowTransactionsModal(false),
      onEdit: openTransactionEditor,
      onDelete: deleteTransaction,
    }) : null,
    editingTransaction && editingTransaction.kind === 'expense' ? h(EditAccountingExpenseModal, {
      expense: editingTransaction.record,
      onClose: () => setEditingTransaction(null),
      onSaved: handleExpenseUpdated,
      onDeleted: handleExpenseDeleted,
    }) : null,
    editingTransaction && editingTransaction.kind === 'purchase' ? h(EditPurchaseInvoiceModal, {
      purchase: editingTransaction.record,
      inventory: allInventory,
      onClose: () => setEditingTransaction(null),
      onSaved: handlePurchaseUpdated,
      onDeleted: handlePurchaseDeleted,
    }) : null,
    detailModal ? h(AccountingBreakdownModal, {
      title: detailModal.label,
      total: detailModal.total,
      rows: detailModal.rows,
      type: detailModal.type,
      onClose: () => setDetailModal(null),
    }) : null,
    showExpenseModal ? h(AddAccountingExpenseModal, {
      inventory: allInventory,
      onClose: () => setShowExpenseModal(false),
      onSaved: handleAccountingSaved,
    }) : null,
    showReportModal ? h(AccountingReportModal, {
      monthLabel,
      summary: monthlyData.summary,
      monthlyInvoices: monthlyData.monthlyInvoices,
      monthlyExpenses: monthlyData.monthlyExpenses,
      monthlyPurchases: monthlyData.monthlyPurchases,
      monthlySessions: monthlyData.monthlySessions,
      onClose: () => setShowReportModal(false),
    }) : null,
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'المحاسبة'),
        h('div', { className: 'page-subtitle' }, 'الإيرادات، التحصيلات، المديونيات، والمصروفات الفعلية'),
      ),
      h('div', { className: 'flex gap-8' },
        h('button', { className: 'btn outline', onClick: () => setShowReportModal(true) }, h(Icons.Download, { size: 16 }), 'تقرير شهري'),
        h('button', { className: 'btn primary', onClick: () => setShowExpenseModal(true) }, h(Icons.Plus, { size: 16 }), 'مصروف جديد'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'grid cols-4 mb-16' },
        [
          { label: 'الإيرادات', value: metrics.revenue, hint: `${allInvoices.length} ${'فاتورة'}`, color: 'var(--accent)' },
          { label: 'التحصيلات', value: metrics.collections, hint: 'إجمالي المدفوع من الفواتير', color: 'var(--success)' },
          { label: 'نسبة التحصيل', value: metrics.collectionRate.toFixed(1) + '%', hint: 'المدفوع ÷ إجمالي الفواتير', color: 'var(--info)' },
          { label: 'المديونيات', value: metrics.receivables, hint: 'المبالغ المتبقية على المرضى', color: 'var(--danger)' },
          { label: 'المصروفات', value: metrics.expenses, hint: 'تشمل المشتريات والمصاريف العامة', color: 'var(--warning)' },
          { label: 'الرصيد الحالي', value: metrics.balance, hint: 'التحصيلات - المصروفات', color: metrics.balance >= 0 ? 'var(--success)' : 'var(--danger)' },
          { label: 'متوسط الدفع لكل جلسة', value: metrics.averagePerSession, hint: `${metrics.sessionCount} ${'جلسة مسجلة'}`, color: 'var(--purple)' },
        ].map((card) => h('div', { key: card.label, className: 'card kpi' },
          h('div', { className: 'label' }, card.label),
          h('div', { className: 'value', style: { color: card.color } }, typeof card.value === 'string' ? card.value : window.fmtEGP(card.value)),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 6 } }, card.hint),
        )),
      ),
    h('div', { style: { display: 'grid', gridTemplateColumns: '1.2fr 1fr', gap: 20 } },
        h('div', { className: 'card p-20' },
          h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 } },
            h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'توزيع المصروفات'),
            loadingExtras ? h('span', { className: 'chip' }, 'جاري تحميل التفاصيل...') : h('span', { className: 'chip accent' }, 'اضغط على أي بند للتفاصيل'),
          ),
          expenseDistribution.length ? expenseDistribution.map((entry) => {
            const pct = metrics.expenses > 0 ? Math.round((entry.total / metrics.expenses) * 100) : 0;
            return h('button', {
              key: entry.key,
              className: 'btn ghost w-full',
              style: {
                justifyContent: 'space-between',
                alignItems: 'stretch',
                textAlign: 'right',
                padding: 0,
                marginBottom: 10,
                border: '1px solid var(--border)',
                background: 'var(--bg-subtle)',
              },
              onClick: () => setDetailModal(entry),
            },
              h('div', { style: { padding: 14, width: '100%' } },
                h('div', { className: 'flex jc-sb ai-c mb-8' },
                  h('div', null,
                    h('div', { style: { fontSize: 14, fontWeight: 800 } }, entry.label),
                    h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, `${entry.rows.length} ${'بند مسجل'}`),
                  ),
                  h('div', { style: { display: 'flex', alignItems: 'center', gap: 10 } },
                    h('span', { style: { fontSize: 13, fontWeight: 800 } }, window.fmtEGP(entry.total)),
                    h(Icons.ChevronLeft, { size: 16 }),
                  ),
                ),
                h('div', { className: 'progress' },
                  h('div', { className: 'progress-bar', style: { width: pct + '%', background: entry.color } }),
                ),
              ),
            );
          }) : h('div', { style: { padding: 32, textAlign: 'center', color: 'var(--text-tertiary)' } }, 'لا توجد مصروفات مسجلة بعد'),
        ),
        h('div', { className: 'card p-20' },
          h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 } },
            h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'آخر المعاملات'),
            h('button', { className: 'btn outline sm', onClick: () => setShowTransactionsModal(true) }, 'عرض الكل'),
          ),
          latestTransactions.length ? latestTransactions.map((item, index) => h('div', {
            key: item.id,
            style: { display: 'flex', alignItems: 'center', gap: 12, padding: '10px 0', borderBottom: index < latestTransactions.length - 1 ? '1px solid var(--border)' : 'none' },
          },
            h('div', {
              style: {
                width: 34,
                height: 34,
                borderRadius: 10,
                display: 'grid',
                placeItems: 'center',
                background: item.type === 'in' ? 'var(--success-soft)' : 'var(--danger-soft)',
                color: item.type === 'in' ? 'var(--success)' : 'var(--danger)',
                flexShrink: 0,
              },
            }, h(item.type === 'in' ? Icons.TrendingUp : Icons.TrendingDown, { size: 16 })),
            h('div', { style: { flex: 1, minWidth: 0 } },
              h('div', { style: { fontSize: 13, fontWeight: 700 } }, item.label),
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, formatAccountingDate(item.date)),
            ),
            h('div', {
              style: {
                fontSize: 14,
                fontWeight: 800,
                color: item.type === 'in' ? 'var(--success)' : 'var(--danger)',
                whiteSpace: 'nowrap',
              },
            }, (item.type === 'in' ? '+' : '-') + window.fmtEGP(item.amount)),
            item.editable ? h('div', { className: 'flex gap-4' },
              h('button', { className: 'icon-btn', title: 'تعديل', onClick: () => { setEditingTransaction(item); } }, h(Icons.Edit, { size: 14 })),
              h('button', {
                className: 'icon-btn',
                title: 'حذف',
                style: { color: 'var(--danger)' },
                onClick: () => deleteTransaction(item),
              }, h(Icons.Trash, { size: 14 })),
            ) : null,
          )) : h('div', { style: { padding: 32, textAlign: 'center', color: 'var(--text-tertiary)' } }, 'لا توجد معاملات حتى الآن'),
        ),
      ),
    ),
  );
}

// ==================== Prescriptions (all) ====================
function GlobalNewRxModal({ onClose, onSaved, patients }) {
  const { toast, clinicId, setPrescriptions } = useContext(AppContext);
  const today = new Date().toISOString().split('T')[0];
  const [patientName, setPatientName] = useState('');
  const [meds, setMeds] = useState([{ name: '', dose: '', duration: '7 أيام' }]);
  const [notes, setNotes] = useState('');
  const addMed = () => setMeds(m => [...m, { name: '', dose: '', duration: '7 أيام' }]);
  const removeMed = (i) => setMeds(m => m.filter((_, j) => j !== i));
  const upd = (i, k, v) => setMeds(m => m.map((med, j) => j === i ? { ...med, [k]: v } : med));

  const handlePrint = () => {
    const c = `<div style="font-family:Arial;direction:rtl;padding:24px;max-width:600px;margin:auto"><h2 style="text-align:center">وصفة طبية</h2><p><strong>المريض:</strong> ${printableText(patientName, '')}</p><p><strong>التاريخ:</strong> ${printableText(today, '')}</p><hr/>${meds.map((m, i) => `<p>${i + 1}. <strong>${printableText(m.name)}</strong> — ${printableText(m.dose)}</p><p style="margin:4px 0 10px;color:#4b5563">المدة: ${printableText(m.duration)}</p>`).join('')}${String(notes || '').trim() ? `<hr/><p><strong>ملاحظات:</strong> ${printableMultiline(notes)}</p>` : ''}<br/><p style="text-align:left;margin-top:40px">توقيع الطبيب: ___________</p></div>`;
    if (!openPrintableWindow({ title: 'وصفة طبية', bodyHtml: c, features: 'width=760,height=840' })) {
      toast('تعذر فتح نافذة الطباعة');
    }
  };
  const handleSave = async () => {
    const normalizedName = String(patientName || '').trim().toLowerCase();
    const selectedPatient = (patients || []).find(p => String(p?.name || '').trim().toLowerCase() === normalizedName);
    if (!meds[0].name.trim()) { toast('أضف دواء واحداً على الأقل'); return; }
    if (!selectedPatient?.id) { toast('اختر مريضاً من القائمة أولاً'); return; }
    try {
      const savedRx = await DB.addPrescription(clinicId, { patientId: selectedPatient.id, date: today, notes }, meds);
      setPrescriptions(prev => [savedRx, ...(prev || [])]);
      toast('تم حفظ الوصفة ✅');
      if (onSaved) onSaved(savedRx);
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر حفظ الوصفة');
    }
  };

  return h('div', { className:'modal-backdrop', onClick: onClose, style: { zIndex:500 } },
    h('div', { className:'gm-box', onClick: e => e.stopPropagation(), style: { width:520, padding:28, maxHeight:'90vh', overflowY:'auto' } },
      h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:20} },
        h('div', { style:{fontWeight:800,fontSize:16} }, '📋 وصفة طبية جديدة'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:16})),
      ),
      h('div', { style:{marginBottom:14} },
        h('div', { className:'label' }, 'المريض'),
        h('input', { className:'input', list:'rx-patients', placeholder:'ابحث أو اكتب اسم المريض', value:patientName, onChange:e=>setPatientName(e.target.value) }),
        h('datalist', { id:'rx-patients' }, (patients||[]).map(p => h('option', { key:p.id, value:p.name }))),
      ),
      h('div', { style:{marginBottom:16} },
        h('div', { style:{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10} },
          h('div', { className:'label' }, 'الأدوية'),
          h('button', { className:'btn outline sm', onClick:addMed }, h(Icons.Plus,{size:12}), 'إضافة دواء'),
        ),
        meds.map((m,i) => h('div', { key:i, style:{border:'1px solid var(--border)',borderRadius:'var(--radius)',padding:12,marginBottom:8} },
          h('div', { style:{display:'grid',gridTemplateColumns:'1fr 1fr 1fr auto',gap:8} },
            h('input', { className:'input', placeholder:'اسم الدواء', value:m.name, onChange:e=>upd(i,'name',e.target.value) }),
            h('input', { className:'input', placeholder:'الجرعة', value:m.dose, onChange:e=>upd(i,'dose',e.target.value) }),
            h('select', { className:'input', value:m.duration, onChange:e=>upd(i,'duration',e.target.value) },
              ['3 أيام','5 أيام','7 أيام','10 أيام','14 أيام','شهر'].map(d => h('option',{key:d,value:d},d)),
            ),
            meds.length > 1 ? h('button', { className:'icon-btn', style:{color:'var(--danger)'}, onClick:()=>removeMed(i) }, h(Icons.X,{size:14})) : h('div'),
          ),
        )),
      ),
      h('div', { style:{marginBottom:20} },
        h('div', { className:'label' }, 'ملاحظات'),
        h('textarea', { className:'textarea', rows:2, placeholder:'تعليمات...', value:notes, onChange:e=>setNotes(e.target.value) }),
      ),
      h('div', { style:{display:'flex',gap:8} },
        h('button', { className:'btn outline', style:{flex:1}, onClick:onClose }, 'إلغاء'),
        h('button', { className:'btn outline', style:{flex:1}, onClick:handlePrint }, h(Icons.Printer,{size:14}), 'طباعة'),
        h('button', { className:'btn primary', style:{flex:1}, onClick:handleSave }, h(Icons.Check,{size:14}), 'حفظ'),
      ),
    ),
  );
}

function Prescriptions() {
  const { patients, prescriptions, toast } = useContext(AppContext);
  const allPatients = (patients && patients.length) ? patients : (window.PATIENTS || []);
  const [showNew, setShowNew] = useState(false);
  const rxList = Array.isArray(prescriptions) ? prescriptions : [];
  const getPatientPhone = (name) => String(allPatients.find(p => String(p.name || '').trim().toLowerCase() === String(name || '').trim().toLowerCase())?.phone || '').trim();

  const printRx = (r) => {
    const c = `<div style="font-family:Arial;direction:rtl;padding:24px;max-width:600px;margin:auto"><h2 style="text-align:center">وصفة طبية</h2><p><strong>المريض:</strong> ${printableText(r.patient, '')}</p><p><strong>التاريخ:</strong> ${printableText(r.date, '')}</p><hr/>${(r.meds || []).map((m, i) => `<p>${i + 1}. <strong>${printableText(m.name)}</strong> — ${printableText(m.dose)}</p><p style="margin:4px 0 10px;color:#4b5563">المدة: ${printableText(m.duration)}</p>`).join('')}<br/><p style="text-align:left;margin-top:40px">توقيع الطبيب: ___________</p></div>`;
    if (!openPrintableWindow({ title: `وصفة طبية - ${r.patient || ''}`, bodyHtml: c, features: 'width=760,height=840' })) {
      toast('تعذر فتح نافذة الطباعة');
    }
  };

  return h('div', { className: 'fade-in' },
    showNew ? h(GlobalNewRxModal, { patients: allPatients, onClose: () => setShowNew(false), onSaved: () => setShowNew(false) }) : null,
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الوصفات الطبية'),
        h('div', { className: 'page-subtitle' }, rxList.length + ' وصفة مسجلة'),
      ),
      h('button', { className: 'btn primary', onClick: () => setShowNew(true) }, h(Icons.Plus, { size: 16 }), 'وصفة جديدة'),
    ),
    h('div', { className: 'page-content' },
      rxList.length === 0 ? h('div', { className: 'card empty-state', style:{padding:60} },
        h('div', { className:'empty-state-icon' }, h(Icons.Pill,{size:32})),
        h('div', null, 'لا توجد وصفات مسجلة'),
        h('button', { className:'btn primary mt-16', onClick:()=>setShowNew(true) }, h(Icons.Plus,{size:14}), 'وصفة جديدة'),
      ) :
      h('div', { className: 'grid', style: { gap: 12 } },
        rxList.map(r => h('div', { key: r.id, className: 'card p-20' },
          h('div', { className: 'flex jc-sb ai-c mb-12' },
            h('div', null,
              h('div', { style: { fontWeight: 800, fontSize: 15 } }, r.patient),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, `${r.id} · ${r.date} · ${r.doctor || '—'}`),
            ),
            h('div', { className: 'flex gap-4' },
              h('button', { className: 'btn outline sm', onClick: () => printRx(r) }, h(Icons.Printer, { size: 14 }), 'طباعة'),
              h('button', { className: 'btn outline sm', onClick: () => toast('تم الإرسال للصيدلية ✅') }, h(Icons.Send, { size: 14 }), 'إرسال للصيدلية'),
              h('button', {
                className: 'btn outline sm',
                onClick: () => {
                  const phone = getPatientPhone(r.patient);
                  const url = buildWhatsAppUrl(phone, `مرحبًا، هذه وصفة ${r.patient} بتاريخ ${r.date}.`);
                  if (!url) { toast('رقم الهاتف غير متاح'); return; }
                  window.open(url, '_blank', 'noopener');
                },
              }, h(Icons.MessageCircle, { size: 14 }), 'واتساب'),
            ),
          ),
          h('div', { className: 'grid cols-2', style: { gap: 8 } },
            r.meds.map((m, i) => h('div', { key: i, style: { padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)' } },
              h('div', { className: 'flex ai-c gap-8 mb-4' },
                h('div', { style: { color: 'var(--accent)' } }, h(Icons.Pill, { size: 16 })),
                h('div', { style: { fontWeight: 700, fontSize: 14 } }, m.name),
              ),
              h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', marginTop: 6 } }, m.dose),
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 2 } }, 'المدة: ' + m.duration),
            )),
          ),
        )),
      ),
    ),
  );
}

// ==================== Xrays (all) ====================
function XrayLightbox({ img, onClose }) {
  const sourceUrl = img?.dataUrl || '';
  return h('div', {
    onClick: onClose,
    style: { position:'fixed',inset:0,background:'rgba(0,0,0,0.9)',zIndex:1000,display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',cursor:'zoom-out' },
  },
    h('div', { style:{position:'absolute',top:16,insetInlineEnd:16} },
      h('button', { className:'icon-btn', style:{background:'rgba(255,255,255,0.15)',color:'#fff',width:40,height:40}, onClick:onClose }, h(Icons.X,{size:20})),
    ),
    h('div', { onClick:e=>e.stopPropagation(), style:{background:img.dataUrl ? 'transparent' : 'repeating-linear-gradient(45deg,#1a1a2e,#1a1a2e 12px,#2a2a3e 12px,#2a2a3e 24px)',width:640,height:480,borderRadius:12,overflow:'hidden',display:'grid',placeItems:'center',position:'relative'} },
      img.dataUrl
        ? h('img', { src:img.dataUrl, style:{width:'100%',height:'100%',objectFit:'contain'} })
        : h('div', { style:{textAlign:'center',color:'#fff',opacity:0.5} }, h(Icons.Image,{size:64}), h('div',{style:{fontFamily:'monospace',fontSize:14,marginTop:12}}, (img.type||'').toUpperCase())),
      h('div', { style:{position:'absolute',bottom:0,left:0,right:0,padding:'14px 20px',background:'rgba(0,0,0,0.6)'} },
        h('div', { style:{fontWeight:800,fontSize:15,color:'#fff'} }, img.label),
        h('div', { style:{fontSize:12,color:'rgba(255,255,255,0.7)',marginTop:4} }, `${img.patient} · ${img.date}`),
      ),
    ),
    h('div', { style:{marginTop:16,display:'flex',gap:8}, onClick:e=>e.stopPropagation() },
      h('button', { className:'btn outline', style:{color:'#fff',borderColor:'rgba(255,255,255,0.3)'}, onClick:()=>window.print() }, h(Icons.Printer,{size:14}), 'طباعة'),
      h('button', {
        className:'btn outline',
        style:{color:'#fff',borderColor:'rgba(255,255,255,0.3)'},
        onClick:()=> {
          if (!window.downloadFromUrl || !window.downloadFromUrl(sourceUrl, `${String(img?.label || 'xray').replace(/[\\/:*?"<>|]/g, '_')}.png`)) {
            window.print();
          }
        },
      }, h(Icons.Download,{size:14}), 'تحميل'),
    ),
  );
}

function Xrays() {
  const { toast, patients } = useContext(AppContext);
  const fileRef = React.useRef(null);
  const [lightbox, setLightbox] = useState(null);
  const allPatients = (patients && patients.length) ? patients : (window.PATIENTS || []);
  const [imgs, setImgs] = useState(() => loadGlobalXrays());
  useEffect(() => {
    setImgs(loadGlobalXrays());
  }, []);
  const [filterType, setFilterType] = useState('');
  const [search, setSearch] = useState('');

  const filtered = imgs.filter(im =>
    (!filterType || im.type === filterType) &&
    (!search || im.patient.includes(search) || im.label.includes(search))
  );

  const handleUpload = async (e) => {
    const file = e.target.files[0]; if (!file) return;
    const isImg = file.type.startsWith('image/');
    try {
      const dataUrl = await fileToStoredDataUrl(file);
      const newImg = { id:Date.now(), patient:'', date:new Date().toISOString().split('T')[0], type:isImg ? 'ديجيتال' : 'مستند', label:file.name.replace(/\.[^.]+$/,''), dataUrl };
      setImgs(prev => {
        const next = [newImg, ...prev];
        saveGlobalXrays(next);
        return next;
      });
      toast('تم رفع الصورة ✅');
      e.target.value = '';
    } catch (error) {
      console.error(error);
      toast('تعذر رفع الصورة');
    }
  };

  const handleDelete = (id, e) => {
    e.stopPropagation();
    if (!confirm('حذف هذه الصورة؟')) return;
    setImgs(prev => {
      const next = prev.filter(im => im.id !== id);
      saveGlobalXrays(next);
      return next;
    });
    if (lightbox?.id === id) setLightbox(null);
    toast('تم الحذف');
  };

  return h('div', { className: 'fade-in' },
    lightbox ? h(XrayLightbox, { img:lightbox, onClose:()=>setLightbox(null) }) : null,
    h('input', { ref:fileRef, type:'file', accept:'image/*,.pdf', style:{display:'none'}, onChange:handleUpload }),
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'الأشعة والصور'),
        h('div', { className: 'page-subtitle' }, `${filtered.length} صورة · تصفح وإدارة الأشعة`),
      ),
      h('div', { className:'flex gap-8' },
        h('input', { className:'input', placeholder:'بحث بالمريض أو الوصف...', value:search, onChange:e=>setSearch(e.target.value), style:{width:200} }),
        h('div', { style:{display:'flex',gap:4,padding:3,background:'var(--bg-subtle)',borderRadius:'var(--radius)'} },
          ['الكل','بانوراما','ديجيتال'].map(t => h('button', {
            key:t, className:'btn sm',
            style:{background:filterType===(t==='الكل'?'':t)?'var(--bg-elevated)':'transparent', boxShadow:filterType===(t==='الكل'?'':t)?'var(--shadow-sm)':'none'},
            onClick:()=>setFilterType(t==='الكل'?'':t),
          }, t)),
        ),
        h('button', { className:'btn primary', onClick:()=>fileRef.current.click() }, h(Icons.Upload,{size:16}), 'رفع صورة'),
      ),
    ),
    h('div', { className: 'page-content' },
      filtered.length === 0 ? h('div', { className:'card empty-state', style:{padding:60} },
        h('div', { className:'empty-state-icon' }, h(Icons.Image,{size:32})),
        h('div', null, 'لا توجد صور'),
        h('button', { className:'btn primary mt-16', onClick:()=>fileRef.current.click() }, h(Icons.Upload,{size:14}), 'رفع أول صورة'),
      ) :
      h('div', { className: 'grid cols-4', style:{gap:12} },
        filtered.map(im => h('div', { key:im.id, className:'card', style:{overflow:'hidden',cursor:'pointer',position:'relative'} },
          h('div', {
            onClick: ()=>setLightbox(im),
            style:{aspectRatio:'4/3', background:im.dataUrl ? `url(${im.dataUrl}) center/cover` : 'repeating-linear-gradient(45deg,#2a2a3a,#2a2a3a 10px,#3a3a4a 10px,#3a3a4a 20px)', display:'grid', placeItems:'center', color:'#fff', position:'relative'},
          },
            !im.dataUrl ? h('div', { style:{textAlign:'center',opacity:0.55} }, h(Icons.Image,{size:36}), h('div',{style:{fontFamily:'monospace',fontSize:10,marginTop:6}},im.type.toUpperCase())) : null,
            h('span', { className:'chip', style:{position:'absolute',top:8,insetInlineEnd:8,background:'rgba(0,0,0,0.55)',color:'#fff',border:'none',fontSize:10} }, im.type),
            h('div', { style:{position:'absolute',inset:0,background:'rgba(0,0,0,0)',transition:'background 0.2s',display:'grid',placeItems:'center'},
              onMouseEnter:e=>e.currentTarget.style.background='rgba(0,0,0,0.3)',
              onMouseLeave:e=>e.currentTarget.style.background='rgba(0,0,0,0)',
            }),
          ),
          h('div', { style:{padding:'10px 12px',display:'flex',justifyContent:'space-between',alignItems:'center'} },
            h('div', null,
              h('div', { style:{fontWeight:700,fontSize:13} }, im.label),
              h('div', { style:{fontSize:12,color:'var(--text-secondary)',marginTop:2} }, im.patient),
              h('div', { style:{fontSize:11,color:'var(--text-tertiary)',marginTop:1} }, im.date),
            ),
            h('button', { className:'icon-btn', style:{color:'var(--danger)',width:28,height:28}, onClick:e=>handleDelete(im.id,e) }, h(Icons.Trash,{size:13})),
          ),
        )),
      ),
    ),
  );
}

// ==================== Patient Portal ====================
function PatientPortal() {
  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'بوابة المريض'),
        h('div', { className: 'page-subtitle' }, 'معاينة — هكذا يرى المريض بياناته على الموبايل'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { style: { display: 'grid', gridTemplateColumns: '360px 1fr', gap: 24 } },
        // Phone preview
        h('div', { style: { display: 'flex', justifyContent: 'center' } },
          h('div', {
            style: {
              width: 340, height: 680, background: '#0b1020', borderRadius: 40, padding: 10,
              boxShadow: 'var(--shadow-lg)', position: 'relative',
            },
          },
            h('div', {
              style: {
                width: '100%', height: '100%', background: 'var(--bg)', borderRadius: 30,
                overflow: 'hidden', display: 'flex', flexDirection: 'column', direction: 'rtl',
              },
            },
              h('div', { style: { padding: '12px 20px 8px', background: 'linear-gradient(135deg, var(--accent), var(--info))', color: '#fff' } },
                h('div', { style: { fontSize: 11, opacity: 0.9 } }, 'مساء الخير'),
                h('div', { style: { fontSize: 18, fontWeight: 800, marginTop: 2 } }, 'أحمد محمد 👋'),
                h('div', {
                  style: {
                    marginTop: 12, padding: 12, background: 'rgba(255,255,255,0.15)',
                    borderRadius: 12, fontSize: 12,
                  },
                },
                  h('div', { style: { opacity: 0.9 } }, 'موعدك القادم'),
                  h('div', { style: { fontSize: 15, fontWeight: 800, marginTop: 4 } }, '22 أبريل · 14:30'),
                  h('div', { style: { opacity: 0.9, marginTop: 2 } }, 'متابعة حشو عصب — د. سارة'),
                ),
              ),
              h('div', { style: { padding: 16, overflow: 'auto', flex: 1 } },
                h('div', { style: { fontWeight: 800, fontSize: 13, marginBottom: 10 } }, 'الخدمات'),
                h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8, marginBottom: 16 } },
                  [
                    { icon: Icons.Calendar, label: 'حجز' },
                    { icon: Icons.File, label: 'ملفي' },
                    { icon: Icons.CreditCard, label: 'فواتير' },
                    { icon: Icons.Image, label: 'أشعة' },
                  ].map((s, i) => h('div', {
                    key: i,
                    style: { background: 'var(--bg-elevated)', borderRadius: 10, padding: 8, textAlign: 'center', border: '1px solid var(--border)' },
                  },
                    h('div', { style: { color: 'var(--accent)', display: 'flex', justifyContent: 'center' } }, h(s.icon, { size: 18 })),
                    h('div', { style: { fontSize: 10, marginTop: 4, fontWeight: 600 } }, s.label),
                  )),
                ),
                h('div', { style: { fontWeight: 800, fontSize: 13, marginBottom: 10 } }, 'خطة العلاج الحالية'),
                h('div', { style: { background: 'var(--bg-elevated)', padding: 12, borderRadius: 10, border: '1px solid var(--border)', marginBottom: 12 } },
                  h('div', { style: { fontSize: 13, fontWeight: 700 } }, 'علاج شامل للفك السفلي'),
                  h('div', { className: 'flex jc-sb ai-c mt-8', style: { fontSize: 10, color: 'var(--text-tertiary)' } },
                    h('span', null, '60% مكتمل'),
                    h('span', null, '4 من 6 جلسات'),
                  ),
                  h('div', { className: 'progress mt-8' }, h('div', { className: 'progress-bar', style: { width: '60%' } })),
                ),
                h('div', { style: { fontWeight: 800, fontSize: 13, marginBottom: 10 } }, 'آخر الوصفات'),
                h('div', { style: { background: 'var(--bg-elevated)', padding: 12, borderRadius: 10, border: '1px solid var(--border)' } },
                  h('div', { style: { fontSize: 12, fontWeight: 700 } }, 'أموكسيسيلين 500mg'),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 2 } }, 'كبسولة كل 8 ساعات · 7 أيام'),
                ),
              ),
            ),
          ),
        ),
        // Features list
        h('div', null,
          h('div', { style: { fontWeight: 800, fontSize: 16, marginBottom: 16 } }, 'ما يستطيع المريض فعله'),
          h('div', { className: 'grid cols-2', style: { gap: 12 } },
            [
              { icon: Icons.Calendar, title: 'حجز وإدارة المواعيد', desc: 'حجز، تأجيل، أو إلغاء المواعيد أونلاين' },
              { icon: Icons.File, title: 'عرض الملف الطبي', desc: 'تاريخ العلاج، الأشعة، والملاحظات' },
              { icon: Icons.CreditCard, title: 'الفواتير والدفع', desc: 'سداد الفواتير عبر بوابة الدفع' },
              { icon: Icons.Pill, title: 'الوصفات الطبية', desc: 'عرض الوصفات وطلب إعادة صرفها' },
              { icon: Icons.Bell, title: 'التذكيرات', desc: 'تنبيهات قبل الموعد بيوم' },
              { icon: Icons.MessageCircle, title: 'التواصل مع العيادة', desc: 'رسائل مباشرة مع الاستقبال' },
            ].map((f, i) => h('div', { key: i, className: 'card p-16' },
              h('div', { style: { width: 40, height: 40, borderRadius: 10, background: 'var(--accent-soft)', color: 'var(--accent)', display: 'grid', placeItems: 'center', marginBottom: 10 } }, h(f.icon, { size: 18 })),
              h('div', { style: { fontWeight: 700, fontSize: 14, marginBottom: 2 } }, f.title),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, f.desc),
            )),
          ),
        ),
      ),
    ),
  );
}

// ==================== Pricing & Profitability ====================
function Pricing() {
  const { services, inventory, clinicId } = useContext(AppContext);
  const allSvcs = (services && services.length) ? services : (window.TREATMENT_TYPES || []);
  const allInv  = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);

  // Fixed costs state (persisted in memory — in real app these go to a settings table)
  const [fixedCosts, setFixedCosts] = useState({
    rent: 5000,
    salaries: 20000,
    utilities: 2000,
    depreciation: 3000,
    other: 1000,
  });
  const [sessionsPerMonth, setSessionsPerMonth] = useState(120);
  const [bomCosts, setBomCosts] = useState({});
  const [loadingBom, setLoadingBom] = useState(false);
  const [bomLoaded, setBomLoaded] = useState(false);
  const [pricingUsageUnitsMap, setPricingUsageUnitsMap] = useState({});

  useEffect(() => {
    setPricingUsageUnitsMap(loadInventoryUsageUnitsMap(clinicId));
  }, [clinicId, allInv.length]);

  const totalFixedCost = Object.values(fixedCosts).reduce((s, v) => s + (+v || 0), 0);
  const fixedCostPerSession = sessionsPerMonth > 0 ? totalFixedCost / sessionsPerMonth : 0;

  // Load BOM data to calculate material cost per service
  const loadBomCosts = async () => {
    if (bomLoaded || !allSvcs.length) return;
    setLoadingBom(true);
    const costs = {};
    for (const svc of allSvcs) {
      try {
        const bom = await DB.getBomForService(svc.id);
        costs[svc.id] = bom.reduce((sum, b) => {
          const item = allInv.find(i => i.id === b.inventoryId);
          return sum + (item ? getInventoryMeasureUnitPrice(item, pricingUsageUnitsMap) * b.standardQty : 0);
        }, 0);
      } catch(e) { costs[svc.id] = 0; }
    }
    setBomCosts(costs);
    setBomLoaded(true);
    setLoadingBom(false);
  };

  useEffect(() => { loadBomCosts(); }, [allSvcs.length, allInv.length, clinicId, JSON.stringify(pricingUsageUnitsMap)]);

  const fixedLabels = [
    ['rent', '🏠 الإيجار الشهري'],
    ['salaries', '👥 رواتب ثابتة (غير الأطباء)'],
    ['utilities', '💡 كهرباء / مياه / إنترنت'],
    ['depreciation', '🔧 استهلاك الأجهزة (شهري)'],
    ['other', '📦 مصاريف أخرى ثابتة'],
  ];

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, '📊 التسعير والربحية'),
        h('div', { className: 'page-subtitle' }, 'احسب ربحك الحقيقي من كل خدمة بعد الخصم والتكاليف الثابتة'),
      ),
    ),
    h('div', { className: 'page-content' },

      /* ===== قسم 1: التكاليف الثابتة ===== */
      h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20, marginBottom: 20 } },
        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 14 } }, '🏗️ التكاليف الثابتة الشهرية'),
          h('div', { style: { display: 'grid', gap: 10 } },
            fixedLabels.map(([k, label]) => h('div', { key: k, style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12 } },
              h('span', { style: { fontSize: 13, flex: 1 } }, label),
              h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
                h('input', {
                  className: 'input', type: 'number', min: 0,
                  style: { width: 110, padding: '5px 8px', fontSize: 13, textAlign: 'left' },
                  value: fixedCosts[k],
                  onChange: e => setFixedCosts(prev => ({ ...prev, [k]: +e.target.value })),
                }),
                h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'ج.م'),
              ),
            )),
          ),
          h('div', { style: { marginTop: 14, padding: '10px 14px', background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', display: 'flex', justifyContent: 'space-between' } },
            h('span', { style: { fontWeight: 700 } }, 'إجمالي التكاليف الثابتة'),
            h('span', { style: { fontWeight: 800, fontSize: 16, color: 'var(--danger)' } }, window.fmtEGP(totalFixedCost)),
          ),
        ),

        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 14 } }, '⚙️ معادلة التوزيع'),
          h('div', { style: { fontSize: 13, color: 'var(--text-secondary)', marginBottom: 12 } },
            'التكلفة الثابتة لكل جلسة = إجمالي التكاليف ÷ عدد جلسات الشهر'),
          h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 } },
            h('div', { className: 'label', style: { whiteSpace: 'nowrap' } }, 'جلسات الشهر التقديرية:'),
            h('input', { className: 'input', type: 'number', min: 1, value: sessionsPerMonth,
              style: { width: 90 }, onChange: e => setSessionsPerMonth(+e.target.value) }),
          ),
          h('div', { className: 'grid cols-2', style: { gap: 12 } },
            [
              { label: 'إجمالي ثابت/شهر', val: window.fmtEGP(totalFixedCost), color: 'var(--danger)' },
              { label: 'ثابت/جلسة', val: window.fmtEGP(Math.round(fixedCostPerSession)), color: 'var(--warning)' },
            ].map((k, i) => h('div', { key: i, style: { padding: 14, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', textAlign: 'center' } },
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginBottom: 4 } }, k.label),
              h('div', { style: { fontSize: 18, fontWeight: 800, color: k.color } }, k.val),
            )),
          ),
          h('div', { style: { marginTop: 16, padding: '12px 14px', background: 'var(--accent-soft)', borderRadius: 'var(--radius)', fontSize: 12, color: 'var(--accent)', fontWeight: 600 } },
            '💡 عشان تضيف استهلاك جهاز: سعر الجهاز ÷ عمره بالشهور. مثلاً: يونيت 120,000 ج.م ÷ 120 شهر = 1,000 ج.م/شهر'),
        ),
      ),

      /* ===== قسم 2: ربحية كل خدمة ===== */
      h('div', { className: 'card', style: { overflow: 'hidden' } },
        h('div', { style: { padding: '14px 20px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
          h('div', { style: { fontWeight: 800, fontSize: 15 } }, '💰 تحليل ربحية الخدمات'),
          loadingBom ? h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, 'جاري تحميل بيانات المواد...') : null,
        ),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null,
            ['الخدمة', 'سعر البيع', 'تكلفة المواد', 'تكلفة ثابتة/جلسة', 'تكلفة إجمالية', 'هامش الربح', 'نسبة الربح', 'التقييم'].map((t, i) =>
              h('th', { key: i }, t))
          )),
          h('tbody', null,
            allSvcs.length === 0 ?
              h('tr', null, h('td', { colSpan: 8, style: { textAlign: 'center', padding: 32, color: 'var(--text-tertiary)' } }, 'أضف خدمات أولاً من المخزون والخدمات')) :
            allSvcs.map(svc => {
              const materialCost = bomCosts[svc.id] || 0;
              const totalCost    = materialCost + fixedCostPerSession;
              const profit       = svc.price - totalCost;
              const margin       = svc.price > 0 ? (profit / svc.price) * 100 : 0;
              const rating       = margin >= 60 ? '🟢 ممتاز' : margin >= 40 ? '🟡 جيد' : margin >= 20 ? '🟠 مقبول' : '🔴 خسارة';
              return h('tr', { key: svc.id },
                h('td', { style: { fontWeight: 700 } }, svc.name),
                h('td', { style: { fontWeight: 800, color: 'var(--accent)' } }, window.fmtEGP(svc.price)),
                h('td', { style: { color: 'var(--danger)' } }, window.fmtEGP(Math.round(materialCost))),
                h('td', { style: { color: 'var(--warning)' } }, window.fmtEGP(Math.round(fixedCostPerSession))),
                h('td', { style: { fontWeight: 700, color: 'var(--danger)' } }, window.fmtEGP(Math.round(totalCost))),
                h('td', { style: { fontWeight: 800, color: profit >= 0 ? 'var(--success)' : 'var(--danger)' } }, window.fmtEGP(Math.round(profit))),
                h('td', null,
                  h('div', { className: 'flex ai-c gap-8' },
                    h('div', { className: 'progress', style: { flex: 1, height: 6 } },
                      h('div', { className: 'progress-bar', style: { width: Math.max(0, margin) + '%', background: margin >= 60 ? 'var(--success)' : margin >= 40 ? 'var(--accent)' : margin >= 20 ? 'var(--warning)' : 'var(--danger)' } }),
                    ),
                    h('span', { style: { fontSize: 12, fontWeight: 700, minWidth: 35 } }, Math.round(margin) + '%'),
                  ),
                ),
                h('td', null, h('span', { style: { fontSize: 12 } }, rating)),
              );
            }),
          ),
        ),
      ),
    ),
  );
}

function PricingV2() {
  const { services, inventory, clinicId } = useContext(AppContext);
  const allSvcs = (services && services.length) ? services : (window.TREATMENT_TYPES || []);
  const allInv = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
  const pricingModelKey = `senan-pricing-model:${clinicId || 'default'}`;
  const doctorCommissionKey = `senan-pricing-commissions:${clinicId || 'default'}`;
  const defaultCostModel = {
    workingHoursPerDay: 5,
    workingDaysPerWeek: 5,
    weeksPerMonth: 4,
    establishmentCostFiveYears: 600000,
    runningFixedMonthly: 10000,
    salariesMonthly: 10000,
    otherFixedMonthly: 0,
  };
  const [costModel, setCostModel] = useState(defaultCostModel);
  const [doctorCommissionMap, setDoctorCommissionMap] = useState({});
  const [bomStats, setBomStats] = useState({});
  const [loadingBom, setLoadingBom] = useState(false);
  const [pricingUsageUnitsMap, setPricingUsageUnitsMap] = useState({});

  useEffect(() => {
    setPricingUsageUnitsMap(loadInventoryUsageUnitsMap(clinicId));
  }, [clinicId, allInv.length]);

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(pricingModelKey);
      if (!raw) {
        setCostModel(defaultCostModel);
        return;
      }
      const parsed = JSON.parse(raw);
      setCostModel(prev => ({ ...prev, ...parsed }));
    } catch (error) {
      console.warn('[Pricing] failed to load cost model:', error);
      setCostModel(defaultCostModel);
    }
  }, [pricingModelKey]);

  useEffect(() => {
    try {
      window.localStorage.setItem(pricingModelKey, JSON.stringify(costModel));
    } catch (error) {
      console.warn('[Pricing] failed to save cost model:', error);
    }
  }, [pricingModelKey, costModel]);

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(doctorCommissionKey);
      setDoctorCommissionMap(raw ? JSON.parse(raw) : {});
    } catch (error) {
      console.warn('[Pricing] failed to load doctor commissions:', error);
      setDoctorCommissionMap({});
    }
  }, [doctorCommissionKey]);

  useEffect(() => {
    try {
      window.localStorage.setItem(doctorCommissionKey, JSON.stringify(doctorCommissionMap));
    } catch (error) {
      console.warn('[Pricing] failed to save doctor commissions:', error);
    }
  }, [doctorCommissionKey, doctorCommissionMap]);

  const updateCostModel = (key, value) => {
    const numericValue = Math.max(0, Number(value) || 0);
    setCostModel(prev => ({ ...prev, [key]: numericValue }));
  };

  const updateDoctorCommission = (serviceId, value) => {
    const numericValue = Math.max(0, Number(value) || 0);
    setDoctorCommissionMap(prev => ({ ...prev, [serviceId]: numericValue }));
  };

  const serviceSnapshot = allSvcs
    .map(svc => `${svc.id}:${Number(svc.price) || 0}:${Number(svc.duration) || 0}`)
    .join('|');
  const inventorySnapshot = allInv
    .map(item => `${item.id}:${Number(item.price) || 0}`)
    .join('|');

  useEffect(() => {
    let cancelled = false;

    const loadBomStats = async () => {
      if (!allSvcs.length) {
        setBomStats({});
        setLoadingBom(false);
        return;
      }

      setLoadingBom(true);
      const inventoryPriceMap = {};
      allInv.forEach(item => {
        inventoryPriceMap[item.id] = getInventoryMeasureUnitPrice(item, pricingUsageUnitsMap);
      });
      const nextStats = {};

      await Promise.all(allSvcs.map(async (svc) => {
        try {
          const bom = await DB.getBomForService(svc.id);
          nextStats[svc.id] = {
            cost: bom.reduce((sum, entry) => sum + ((inventoryPriceMap[entry.inventoryId] || 0) * (Number(entry.standardQty) || 0)), 0),
            itemsCount: bom.length,
          };
        } catch (error) {
          nextStats[svc.id] = { cost: 0, itemsCount: 0 };
        }
      }));

      if (!cancelled) {
        setBomStats(nextStats);
        setLoadingBom(false);
      }
    };

    loadBomStats();
    return () => { cancelled = true; };
  }, [clinicId, serviceSnapshot, inventorySnapshot, JSON.stringify(pricingUsageUnitsMap)]);

  const workingHoursPerMonth = Math.max(
    0,
    (Number(costModel.workingHoursPerDay) || 0)
      * (Number(costModel.workingDaysPerWeek) || 0)
      * (Number(costModel.weeksPerMonth) || 0)
  );
  const establishmentDepreciationPerYear = (Number(costModel.establishmentCostFiveYears) || 0) / 5;
  const establishmentDepreciationPerMonth = (Number(costModel.establishmentCostFiveYears) || 0) / 60;
  const establishmentDepreciationPerHour = workingHoursPerMonth > 0 ? establishmentDepreciationPerMonth / workingHoursPerMonth : 0;
  const runningFixedPerHour = workingHoursPerMonth > 0 ? (Number(costModel.runningFixedMonthly) || 0) / workingHoursPerMonth : 0;
  const salariesPerHour = workingHoursPerMonth > 0 ? (Number(costModel.salariesMonthly) || 0) / workingHoursPerMonth : 0;
  const otherFixedPerHour = workingHoursPerMonth > 0 ? (Number(costModel.otherFixedMonthly) || 0) / workingHoursPerMonth : 0;
  const totalFixedMonthly = establishmentDepreciationPerMonth
    + (Number(costModel.runningFixedMonthly) || 0)
    + (Number(costModel.salariesMonthly) || 0)
    + (Number(costModel.otherFixedMonthly) || 0);
  const totalFixedPerHour = workingHoursPerMonth > 0 ? totalFixedMonthly / workingHoursPerMonth : 0;

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, '📊 التسعير والربحية'),
        h('div', { className: 'page-subtitle' }, 'احسب تكلفة الساعة الحقيقية أولًا، ثم راقب ربحية كل خدمة مع المواد والزمن وعمولة الطبيب'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20, marginBottom: 20 } },
        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 8 } }, '⏱️ ساعات التشغيل'),
          h('div', { style: { fontSize: 13, color: 'var(--text-secondary)', marginBottom: 14 } },
            'ابدأ بعدد ساعات الشغل الفعلية في الشهر، لأننا سنقسم عليها كل التكلفة الثابتة بدل فكرة تكلفة الجلسة الموحدة.'
          ),
          h('div', { style: { display: 'grid', gap: 12 } },
            [
              ['workingHoursPerDay', 'ساعات العمل يوميًا', 'عدد الساعات الفعلية داخل اليوم'],
              ['workingDaysPerWeek', 'أيام العمل أسبوعيًا', 'عدد أيام الشغل في الأسبوع'],
              ['weeksPerMonth', 'أسابيع العمل شهريًا', 'اكتب 4 أو 4.3 حسب طريقتك'],
            ].map(([key, label, hint]) => h('div', {
              key,
              style: { display: 'grid', gridTemplateColumns: '1.3fr auto', gap: 12, alignItems: 'center' },
            },
              h('div', null,
                h('div', { style: { fontSize: 14, fontWeight: 700 } }, label),
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, hint),
              ),
              h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
                h('input', {
                  className: 'input',
                  type: 'number',
                  min: 0,
                  style: { width: 110, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  value: costModel[key],
                  onChange: e => updateCostModel(key, e.target.value),
                }),
                h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, key === 'workingHoursPerDay' ? 'ساعة' : key === 'workingDaysPerWeek' ? 'يوم' : 'أسبوع'),
              ),
            )),
          ),
          h('div', { className: 'grid cols-2', style: { gap: 12, marginTop: 18 } },
            [
              { label: 'ساعات العمل/شهر', value: `${workingHoursPerMonth.toFixed(0)} ساعة`, color: 'var(--accent)' },
              { label: 'إجمالي ثابت/ساعة', value: window.fmtEGP(totalFixedPerHour), color: 'var(--warning)' },
            ].map((item) => h('div', {
              key: item.label,
              style: { padding: 14, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', textAlign: 'center' },
            },
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginBottom: 4 } }, item.label),
              h('div', { style: { fontSize: 20, fontWeight: 900, color: item.color } }, item.value),
            )),
          ),
        ),
        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 8 } }, '🏗️ التكلفة الثابتة الحقيقية'),
          h('div', { style: { fontSize: 13, color: 'var(--text-secondary)', marginBottom: 14 } },
            'بنفس منطق ملف الإكسل: استهلاك الأجهزة + التشغيل الثابت + الرواتب الثابتة + أي بند إضافي، ثم نقسمهم على ساعات العمل الشهرية.'
          ),
          h('div', { style: { display: 'grid', gap: 12 } },
            h('div', { style: { display: 'grid', gridTemplateColumns: '1.3fr auto', gap: 12, alignItems: 'center' } },
              h('div', null,
                h('div', { style: { fontSize: 14, fontWeight: 700 } }, 'تكلفة التأسيس والتجهيز لخمس سنوات'),
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, 'اجمع فيها الأجهزة والكراسي والوحدات وكل أصل ثابت تريد استهلاكه'),
              ),
              h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
                h('input', {
                  className: 'input',
                  type: 'number',
                  min: 0,
                  style: { width: 130, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  value: costModel.establishmentCostFiveYears,
                  onChange: e => updateCostModel('establishmentCostFiveYears', e.target.value),
                }),
                h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'ج.م'),
              ),
            ),
            [
              ['runningFixedMonthly', 'التشغيل الثابت الشهري', 'إيجار، كهرباء، مياه، إنترنت، تسويق...'],
              ['salariesMonthly', 'الرواتب الثابتة', 'رواتب الفريق الثابتة بعيدًا عن عمولات الأطباء'],
              ['otherFixedMonthly', 'مصروفات ثابتة إضافية', 'أي بند شهري ثابت آخر'],
            ].map(([key, label, hint]) => h('div', {
              key,
              style: { display: 'grid', gridTemplateColumns: '1.3fr auto', gap: 12, alignItems: 'center' },
            },
              h('div', null,
                h('div', { style: { fontSize: 14, fontWeight: 700 } }, label),
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, hint),
              ),
              h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
                h('input', {
                  className: 'input',
                  type: 'number',
                  min: 0,
                  style: { width: 130, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  value: costModel[key],
                  onChange: e => updateCostModel(key, e.target.value),
                }),
                h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'ج.م'),
              ),
            )),
          ),
          h('div', { className: 'grid cols-2', style: { gap: 12, marginTop: 16 } },
            [
              { label: 'إهلاك الأجهزة/سنة', val: window.fmtEGP(establishmentDepreciationPerYear), color: 'var(--accent)' },
              { label: 'إهلاك الأجهزة/شهر', val: window.fmtEGP(establishmentDepreciationPerMonth), color: 'var(--accent)' },
              { label: 'إهلاك الأجهزة/ساعة', val: window.fmtEGP(establishmentDepreciationPerHour), color: 'var(--warning)' },
              { label: 'التشغيل الثابت/ساعة', val: window.fmtEGP(runningFixedPerHour), color: 'var(--warning)' },
              { label: 'الرواتب الثابتة/ساعة', val: window.fmtEGP(salariesPerHour), color: 'var(--warning)' },
              { label: 'الإضافي الثابت/ساعة', val: window.fmtEGP(otherFixedPerHour), color: 'var(--warning)' },
              { label: 'إجمالي ثابت/شهر', val: window.fmtEGP(totalFixedMonthly), color: 'var(--danger)' },
              { label: 'إجمالي ثابت/ساعة', val: window.fmtEGP(totalFixedPerHour), color: 'var(--danger)' },
            ].map((item, index) => h('div', {
              key: item.label + index,
              style: { padding: 14, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', textAlign: 'center' },
            },
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginBottom: 4 } }, item.label),
              h('div', { style: { fontSize: 18, fontWeight: 800, color: item.color } }, item.val),
            )),
          ),
          h('div', {
            style: {
              marginTop: 16,
              padding: '14px 16px',
              background: 'var(--accent-soft)',
              borderRadius: 'var(--radius)',
              fontSize: 12,
              color: 'var(--accent)',
              fontWeight: 600,
              display: 'grid',
              gap: 8,
            },
          },
            h('div', null, `• في الإعداد الحالي: ${window.fmtEGP(costModel.establishmentCostFiveYears)} ÷ 60 شهر = ${window.fmtEGP(establishmentDepreciationPerMonth)} شهريًا، ثم ÷ ${workingHoursPerMonth.toFixed(0) || '0'} ساعة = ${window.fmtEGP(establishmentDepreciationPerHour)} للساعة.`),
            h('div', null, '• لو عندك أكثر من جهاز، اجمعهم كلهم داخل بند التأسيس والتجهيز لخمس سنوات.'),
            h('div', null, '• الخدمة التي تستغرق 90 دقيقة ستتحمل 1.5 ساعة من التكلفة الثابتة تلقائيًا في الجدول التالي.'),
          ),
        ),
      ),
      h('div', { className: 'card', style: { overflow: 'hidden' } },
        h('div', { style: { padding: '14px 20px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
          h('div', { style: { fontWeight: 800, fontSize: 15 } }, '💰 تحليل ربحية الخدمات'),
          loadingBom ? h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, 'جاري تحميل تكاليف المواد من BOM والمخزون...') : null,
        ),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null,
            ['الخدمة', 'سعر البيع', 'تكلفة المواد', 'تكلفة الساعة', 'عمولة الطبيب', 'تكلفة إجمالية', 'هامش الربح', 'نسبة الربح', 'التقييم'].map((t, i) =>
              h('th', { key: i }, t))
          )),
          h('tbody', null,
            allSvcs.length === 0 ?
              h('tr', null, h('td', { colSpan: 9, style: { textAlign: 'center', padding: 32, color: 'var(--text-tertiary)' } }, 'أضف خدمات أولًا من المخزون والخدمات')) :
            allSvcs.map(svc => {
              const durationMinutes = Number(svc.duration) || 30;
              const durationHours = durationMinutes / 60;
              const materialStats = bomStats[svc.id] || { cost: 0, itemsCount: 0 };
              const materialCost = Number(materialStats.cost) || 0;
              const doctorCommission = Number(doctorCommissionMap[svc.id]) || 0;
              const loadedFixedCost = totalFixedPerHour * durationHours;
              const totalCost = materialCost + loadedFixedCost + doctorCommission;
              const profit = (Number(svc.price) || 0) - totalCost;
              const margin = (Number(svc.price) || 0) > 0 ? (profit / Number(svc.price)) * 100 : 0;
              const rating = profit < 0
                ? '🔴 خاسرة'
                : margin >= 55
                  ? '🟢 ممتازة'
                  : margin >= 35
                    ? '🟡 جيدة'
                    : margin >= 15
                      ? '🟠 تحتاج تحسين'
                      : '🔴 ضعيفة';
              return h('tr', { key: svc.id },
                h('td', null,
                  h('div', { style: { fontWeight: 700 } }, svc.name),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, `${durationMinutes} دقيقة`),
                ),
                h('td', { style: { fontWeight: 800, color: 'var(--accent)' } }, window.fmtEGP(Number(svc.price) || 0)),
                h('td', { style: { color: 'var(--danger)' } },
                  h('div', { style: { fontWeight: 700 } }, window.fmtEGP(Math.round(materialCost))),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, materialStats.itemsCount ? `${materialStats.itemsCount} مادة مرتبطة` : 'لا توجد مواد مرتبطة'),
                ),
                h('td', { style: { color: 'var(--warning)' } },
                  h('div', { style: { fontWeight: 700 } }, `${window.fmtEGP(Math.round(totalFixedPerHour))} / ساعة`),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, `تحميل الخدمة: ${window.fmtEGP(Math.round(loadedFixedCost))}`),
                ),
                h('td', null,
                  h('input', {
                    className: 'input',
                    type: 'number',
                    min: 0,
                    value: doctorCommission,
                    onChange: e => updateDoctorCommission(svc.id, e.target.value),
                    style: { width: 96, padding: '6px 8px', fontSize: 13, textAlign: 'left' },
                  }),
                ),
                h('td', { style: { fontWeight: 700, color: 'var(--danger)' } }, window.fmtEGP(Math.round(totalCost))),
                h('td', { style: { fontWeight: 800, color: profit >= 0 ? 'var(--success)' : 'var(--danger)' } }, window.fmtEGP(Math.round(profit))),
                h('td', null,
                  h('div', { className: 'flex ai-c gap-8' },
                    h('div', { className: 'progress', style: { flex: 1, height: 6 } },
                      h('div', { className: 'progress-bar', style: { width: Math.max(0, Math.min(100, margin)) + '%', background: margin >= 55 ? 'var(--success)' : margin >= 35 ? 'var(--accent)' : margin >= 15 ? 'var(--warning)' : 'var(--danger)' } }),
                    ),
                    h('span', { style: { fontSize: 12, fontWeight: 700, minWidth: 35 } }, Math.round(margin) + '%'),
                  ),
                ),
                h('td', null, h('span', { style: { fontSize: 12 } }, rating)),
              );
            }),
          ),
        ),
      ),
    ),
  );
}

function PricingV3() {
  const { services, inventory, clinicId, setServices, toast } = useContext(AppContext);
  const allSvcs = (services && services.length) ? services : (window.TREATMENT_TYPES || []);
  const allInv = (inventory && inventory.length) ? inventory : (window.INVENTORY || []);
  const pricingModelKey = `senan-pricing-model:${clinicId || 'default'}`;
  const doctorCommissionKey = `senan-pricing-commissions:${clinicId || 'default'}`;
  const defaultCostModel = {
    workingHoursPerDay: 5,
    workingDaysPerWeek: 5,
    weeksPerMonth: 4,
    equipmentInvestmentTotal: 600000,
    equipmentLifespanYears: 8,
    extraEquipmentGroups: [],
    runningFixedMonthly: 10000,
    salariesMonthly: 10000,
    otherFixedMonthly: 0,
  };
  const [costModel, setCostModel] = useState(defaultCostModel);
  const [doctorCommissionMap, setDoctorCommissionMap] = useState({});
  const [bomStats, setBomStats] = useState({});
  const [loadingBom, setLoadingBom] = useState(false);
  const [pricingUsageUnitsMap, setPricingUsageUnitsMap] = useState({});
  const [priceDrafts, setPriceDrafts] = useState({});
  const [durationDrafts, setDurationDrafts] = useState({});
  const [showExtraEquipment, setShowExtraEquipment] = useState(false);
  const [showPricingGuidance, setShowPricingGuidance] = useState(false);
  // Services management (moved from Inventory)
  const [showAddServiceP, setShowAddServiceP] = useState(false);
  const [editServiceP, setEditServiceP] = useState(null);

  useEffect(() => {
    setPricingUsageUnitsMap(loadInventoryUsageUnitsMap(clinicId));
  }, [clinicId, allInv.length]);

  const normalizeMoneyValue = (value) => {
    const number = Number(value) || 0;
    if (Math.abs(number) >= 100) return Math.round(number);
    return Math.round(number * 10) / 10;
  };
  const fmtMoney = (value) => {
    const roundedValue = normalizeMoneyValue(value);
    return `${new Intl.NumberFormat('en-US', {
      minimumFractionDigits: Number.isInteger(roundedValue) ? 0 : 1,
      maximumFractionDigits: 1,
    }).format(roundedValue)} ج.م`;
  };
  const fmtNumber = (value) => {
    const roundedValue = normalizeMoneyValue(value);
    return new Intl.NumberFormat('en-US', {
      minimumFractionDigits: Number.isInteger(roundedValue) ? 0 : 1,
      maximumFractionDigits: 1,
    }).format(roundedValue);
  };
  const fmtPercent = value => `${new Intl.NumberFormat('en-US', {
    minimumFractionDigits: 0,
    maximumFractionDigits: 1,
  }).format(Math.max(0, Number(value) || 0))}%`;
  const hintBadgeStyle = {
    width: 18,
    height: 18,
    borderRadius: 999,
    display: 'inline-grid',
    placeItems: 'center',
    background: 'var(--bg-subtle)',
    color: 'var(--text-secondary)',
    fontSize: 11,
    fontWeight: 900,
    cursor: 'help',
    border: '1px solid var(--border)',
  };
  const renderHintBadge = (hint) => h('span', {
    title: hint,
    'aria-label': hint,
    style: hintBadgeStyle,
  }, 'i');
  const renderFieldLabel = (label, hint) => h('div', {
    style: { display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 14, fontWeight: 700 },
  },
    h('span', null, label),
    renderHintBadge(hint),
  );
  const normalizeCommissionEntry = (entry) => {
    if (typeof entry === 'number') {
      return { mode: 'amount', value: Math.max(0, entry || 0) };
    }
    if (entry && typeof entry === 'object') {
      return {
        mode: entry.mode === 'percent' ? 'percent' : 'amount',
        value: Math.max(0, Number(entry.value) || 0),
      };
    }
    return { mode: 'amount', value: 0 };
  };

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(pricingModelKey);
      if (!raw) {
        setCostModel(defaultCostModel);
        return;
      }
      const parsed = JSON.parse(raw);
      const migrated = {
        ...defaultCostModel,
        ...parsed,
      };
      if (parsed.establishmentCostFiveYears != null && parsed.equipmentInvestmentTotal == null) {
        migrated.equipmentInvestmentTotal = Math.max(0, Number(parsed.establishmentCostFiveYears) || 0);
      }
      if (parsed.equipmentLifespanYears == null) {
        migrated.equipmentLifespanYears = defaultCostModel.equipmentLifespanYears;
      }
      migrated.extraEquipmentGroups = Array.isArray(parsed.extraEquipmentGroups)
        ? parsed.extraEquipmentGroups.map(group => ({
            name: String(group.name || ''),
            cost: Math.max(0, Number(group.cost) || 0),
            lifespanYears: Math.max(1, Number(group.lifespanYears) || 1),
          }))
        : [];
      setCostModel(migrated);
    } catch (error) {
      console.warn('[Pricing] failed to load cost model:', error);
      setCostModel(defaultCostModel);
    }
  }, [pricingModelKey]);

  useEffect(() => {
    try {
      window.localStorage.setItem(pricingModelKey, JSON.stringify(costModel));
    } catch (error) {
      console.warn('[Pricing] failed to save cost model:', error);
    }
  }, [pricingModelKey, costModel]);

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(doctorCommissionKey);
      if (!raw) {
        setDoctorCommissionMap({});
        return;
      }
      const parsed = JSON.parse(raw);
      const migrated = {};
      Object.entries(parsed || {}).forEach(([serviceId, entry]) => {
        migrated[serviceId] = normalizeCommissionEntry(entry);
      });
      setDoctorCommissionMap(migrated);
    } catch (error) {
      console.warn('[Pricing] failed to load doctor commissions:', error);
      setDoctorCommissionMap({});
    }
  }, [doctorCommissionKey]);

  useEffect(() => {
    try {
      window.localStorage.setItem(doctorCommissionKey, JSON.stringify(doctorCommissionMap));
    } catch (error) {
      console.warn('[Pricing] failed to save doctor commissions:', error);
    }
  }, [doctorCommissionKey, doctorCommissionMap]);

  const updateCostModel = (key, value) => {
    const numericValue = Math.max(0, Number(value) || 0);
    setCostModel(prev => ({ ...prev, [key]: numericValue }));
  };
  const addExtraEquipmentGroup = () => {
    setCostModel(prev => ({
      ...prev,
      extraEquipmentGroups: [...(prev.extraEquipmentGroups || []), { name: '', cost: 0, lifespanYears: 8 }],
    }));
  };
  const updateExtraEquipmentGroup = (index, key, value) => {
    const numericValue = key === 'lifespanYears'
      ? Math.max(1, Number(value) || 1)
      : Math.max(0, Number(value) || 0);
    setCostModel(prev => ({
      ...prev,
      extraEquipmentGroups: (prev.extraEquipmentGroups || []).map((group, groupIndex) => (
        groupIndex === index ? { ...group, [key]: key === 'name' ? String(value || '') : numericValue } : group
      )),
    }));
  };
  const removeExtraEquipmentGroup = (index) => {
    setCostModel(prev => ({
      ...prev,
      extraEquipmentGroups: (prev.extraEquipmentGroups || []).filter((_, groupIndex) => groupIndex !== index),
    }));
  };

  const updateDoctorCommission = (serviceId, patch) => {
    setDoctorCommissionMap(prev => {
      const current = normalizeCommissionEntry(prev[serviceId]);
      return {
        ...prev,
        [serviceId]: {
          ...current,
          ...patch,
          mode: patch.mode === 'percent' ? 'percent' : patch.mode === 'amount' ? 'amount' : current.mode,
          value: patch.value != null ? Math.max(0, Number(patch.value) || 0) : current.value,
        },
      };
    });
  };
  useEffect(() => {
    const nextDrafts = {};
    allSvcs.forEach(svc => {
      nextDrafts[svc.id] = Number(svc.price) || 0;
    });
    setPriceDrafts(nextDrafts);
  }, [allSvcs]);
  const saveServicePrice = async (serviceId) => {
    const draftValue = Math.max(0, Number(priceDrafts[serviceId]) || 0);
    const service = allSvcs.find(svc => svc.id === serviceId);
    if (!service) return;
    if (draftValue === (Number(service.price) || 0)) return;
    try {
      const { data, error } = await SB.from('services')
        .update({ price: draftValue })
        .eq('id', serviceId)
        .select()
        .single();
      if (error) throw error;
      const updatedService = {
        ...service,
        ...(data || {}),
        price: Number((data && data.price) != null ? data.price : draftValue) || 0,
      };
      if (setServices) {
        setServices(prev => prev.map(item => item.id === serviceId ? updatedService : item));
      }
    } catch (error) {
      console.warn('[Pricing] failed to update service price:', error);
      setPriceDrafts(prev => ({ ...prev, [serviceId]: Number(service.price) || 0 }));
      if (toast) toast('تعذر حفظ سعر الخدمة');
    }
  };

  const saveServiceDuration = async (serviceId) => {
    const draftValue = Math.max(5, parseInt(durationDrafts[serviceId], 10) || 30);
    const service = allSvcs.find(svc => svc.id === serviceId);
    if (!service) return;
    if (draftValue === (Number(service.duration) || 30)) return;
    try {
      const { data, error } = await SB.from('services')
        .update({ duration: draftValue })
        .eq('id', serviceId)
        .select()
        .single();
      if (error) throw error;
      const updatedService = { ...service, ...(data || {}), duration: draftValue };
      if (setServices) setServices(prev => prev.map(item => item.id === serviceId ? updatedService : item));
    } catch (error) {
      console.warn('[Pricing] failed to update service duration:', error);
      setDurationDrafts(prev => ({ ...prev, [serviceId]: Number(service.duration) || 30 }));
      if (toast) toast('تعذر حفظ مدة الخدمة');
    }
  };

  const serviceSnapshot = allSvcs
    .map(svc => `${svc.id}:${Number(svc.price) || 0}:${Number(svc.duration) || 0}`)
    .join('|');
  const inventorySnapshot = allInv
    .map(item => `${item.id}:${Number(item.price) || 0}`)
    .join('|');

  useEffect(() => {
    let cancelled = false;

    const loadBomStats = async () => {
      if (!allSvcs.length) {
        setBomStats({});
        setLoadingBom(false);
        return;
      }

      setLoadingBom(true);
      const inventoryPriceMap = {};
      allInv.forEach(item => {
        inventoryPriceMap[item.id] = getInventoryMeasureUnitPrice(item, pricingUsageUnitsMap);
      });
      const nextStats = {};

      await Promise.all(allSvcs.map(async (svc) => {
        try {
          const bom = await DB.getBomForService(svc.id);
          nextStats[svc.id] = {
            cost: bom.reduce((sum, entry) => sum + ((inventoryPriceMap[entry.inventoryId] || 0) * (Number(entry.standardQty) || 0)), 0),
            itemsCount: bom.length,
          };
        } catch (error) {
          nextStats[svc.id] = { cost: 0, itemsCount: 0 };
        }
      }));

      if (!cancelled) {
        setBomStats(nextStats);
        setLoadingBom(false);
      }
    };

    loadBomStats();
    return () => { cancelled = true; };
  }, [clinicId, serviceSnapshot, inventorySnapshot, JSON.stringify(pricingUsageUnitsMap)]);

  const workingHoursPerMonth = Math.max(
    0,
    (Number(costModel.workingHoursPerDay) || 0)
      * (Number(costModel.workingDaysPerWeek) || 0)
      * (Number(costModel.weeksPerMonth) || 0)
  );
  const extraEquipmentGroups = Array.isArray(costModel.extraEquipmentGroups) ? costModel.extraEquipmentGroups : [];
  const extraEquipmentDepreciationPerYear = extraEquipmentGroups.reduce((sum, group) => (
    sum + ((Number(group.cost) || 0) / Math.max(1, Number(group.lifespanYears) || 1))
  ), 0);
  const extraEquipmentDepreciationPerMonth = extraEquipmentGroups.reduce((sum, group) => (
    sum + ((Number(group.cost) || 0) / (Math.max(1, Number(group.lifespanYears) || 1) * 12))
  ), 0);
  const equipmentLifespanYears = Math.max(1, Number(costModel.equipmentLifespanYears) || 1);
  const equipmentLifespanMonths = equipmentLifespanYears * 12;
  const equipmentDepreciationPerYear = ((Number(costModel.equipmentInvestmentTotal) || 0) / equipmentLifespanYears) + extraEquipmentDepreciationPerYear;
  const equipmentDepreciationPerMonth = ((Number(costModel.equipmentInvestmentTotal) || 0) / equipmentLifespanMonths) + extraEquipmentDepreciationPerMonth;
  const equipmentDepreciationPerHour = workingHoursPerMonth > 0 ? equipmentDepreciationPerMonth / workingHoursPerMonth : 0;
  const runningFixedPerHour = workingHoursPerMonth > 0 ? (Number(costModel.runningFixedMonthly) || 0) / workingHoursPerMonth : 0;
  const salariesPerHour = workingHoursPerMonth > 0 ? (Number(costModel.salariesMonthly) || 0) / workingHoursPerMonth : 0;
  const otherFixedPerHour = workingHoursPerMonth > 0 ? (Number(costModel.otherFixedMonthly) || 0) / workingHoursPerMonth : 0;
  const totalFixedMonthly = equipmentDepreciationPerMonth
    + (Number(costModel.runningFixedMonthly) || 0)
    + (Number(costModel.salariesMonthly) || 0)
    + (Number(costModel.otherFixedMonthly) || 0);
  const totalFixedPerHour = workingHoursPerMonth > 0 ? totalFixedMonthly / workingHoursPerMonth : 0;

  const pricingGuidance = [
    'ابدأ من تكلفة الساعة الحقيقية، ثم أضف المواد والعمولة قبل التفكير في سعر البيع.',
    'اربط كل خدمة بموادها الفعلية من المخزون حتى لا تظهر الربحية أعلى من الواقع.',
    'لو الطبيب يأخذ نسبة، اختر نسبة. ولو يأخذ مبلغًا ثابتًا، اختر مبلغًا ثابتًا كما هو.',
    'راجع مدة الخدمة بدقة لأن ربع ساعة أو ساعة ونصف يغيّران التكلفة الثابتة مباشرة.',
    'إذا كانت الربحية ضعيفة، راجع السعر أو الوقت أو المواد قبل اعتماد الخدمة.',
    'الإهلاك ليس ربحًا للسحب، بل حصالة شهرية تضمن سيولة لتجديد الأجهزة عند انتهاء عمرها.',
    'راجع أسعار خدماتك كل 6 أشهر لضبط هامش الربح ومواجهة التضخم وتغيرات السوق.',
  ];

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, '📊 التسعير والربحية'),
        h('div', { className: 'page-subtitle' }, 'احسب تكلفة الساعة الحقيقية أولًا، ثم أضف المواد وعمولة الطبيب، وبعدها فقط قرر هامش الربح وسعر البيع المناسب لكل خدمة.'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20, marginBottom: 20 } },
        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 8 } }, '⏱️ ساعات التشغيل الشهرية'),
          h('div', { style: { display: 'grid', gap: 12 } },
            [
              ['workingHoursPerDay', 'ساعات العمل يوميًا', 'عدد الساعات الفعلية التي تعملها العيادة كل يوم'],
              ['workingDaysPerWeek', 'أيام العمل أسبوعيًا', 'عدد الأيام الفعلية التي تعملها العيادة كل أسبوع'],
              ['weeksPerMonth', 'أسابيع العمل شهريًا', 'اكتب 4 أو 4.3 حسب متوسط التشغيل الشهري'],
            ].map(([key, label, hint]) => h('div', {
              key,
              style: { display: 'grid', gridTemplateColumns: '1.3fr auto', gap: 12, alignItems: 'center' },
            },
              h('div', null,
                renderFieldLabel(label, hint),
              ),
              h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
                h('input', {
                  className: 'input',
                  type: 'number',
                  min: 0,
                  style: { width: 110, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  value: costModel[key],
                  onChange: e => updateCostModel(key, e.target.value),
                }),
                h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, key === 'workingHoursPerDay' ? 'ساعة' : key === 'workingDaysPerWeek' ? 'يوم' : 'أسبوع'),
              ),
            )),
          ),
          h('div', {
            style: {
              marginTop: 18,
              padding: '16px 18px',
              background: 'var(--bg-subtle)',
              borderRadius: 'var(--radius-lg)',
              border: '1px solid var(--border)',
            },
          },
            h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 6 } }, 'ساعات العمل الشهرية الفعلية'),
            h('div', { style: { fontSize: 28, fontWeight: 900, color: 'var(--accent)', marginBottom: 6 } }, `${fmtNumber(workingHoursPerMonth)} ساعة`),
            h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.7 } }, 'هذا الرقم هو أساس توزيع التكاليف الثابتة على الخدمات. كلما كان أدق، كانت تكلفة الساعة أقرب للواقع.'),
          ),
          h('div', {
            style: {
              marginTop: 14,
              border: '1px solid var(--border)',
              borderRadius: 'var(--radius)',
              overflow: 'hidden',
              background: 'var(--panel)',
            },
          },
            h('button', {
              type: 'button',
              onClick: () => setShowPricingGuidance(v => !v),
              style: {
                width: '100%',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                gap: 12,
                padding: '14px 16px',
                background: 'transparent',
                border: 'none',
                color: 'var(--text)',
                cursor: 'pointer',
                fontSize: 14,
                fontWeight: 800,
              },
            },
              h('span', null, '💡 نصائح ذهبية لتسعير عيادتك'),
              h('span', { style: { fontSize: 18, color: 'var(--text-secondary)' } }, showPricingGuidance ? '−' : '+'),
            ),
            showPricingGuidance ? h('div', {
              style: {
                padding: '0 16px 16px',
                display: 'grid',
                gap: 8,
                fontSize: 12,
                color: 'var(--text-secondary)',
              },
            },
              pricingGuidance.map((note, index) => h('div', {
                key: index,
                style: { lineHeight: 1.8, fontWeight: 600 },
              }, `${index + 1}. ${note}`)),
            ) : null,
          ),
        ),
        h('div', { className: 'card p-20' },
          h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 8 } }, '🏗️ التكلفة الثابتة الحقيقية'),
          h('div', { style: { display: 'grid', gap: 12 } },
            h('div', { style: { display: 'grid', gridTemplateColumns: '1.3fr auto auto', gap: 12, alignItems: 'center' } },
              h('div', null,
                renderFieldLabel('قيمة الأجهزة والتجهيزات', 'اجمع فيها الأجهزة والكرسي والوحدات وكل أصل تريد تحميل إهلاكه على الخدمات'),
              ),
              h('input', {
                className: 'input',
                type: 'number',
                min: 0,
                style: { width: 120, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                value: costModel.equipmentInvestmentTotal,
                onChange: e => updateCostModel('equipmentInvestmentTotal', e.target.value),
              }),
              h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'ج.م'),
            ),
            h('div', { style: { display: 'grid', gridTemplateColumns: '1.3fr auto auto', gap: 12, alignItems: 'center' } },
              h('div', null,
                renderFieldLabel('العمر المحاسبي للأجهزة والتجهيزات', 'يشمل الأجهزة والتجهيزات والديكورات والتشطيبات وكل أصل ثابت تريد تحميله على الخدمات. 5 سنوات للأجهزة الاقتصادية، و7-10 سنوات للأجهزة الأعلى تحمّلًا. أما Instruments والأدوات الدقيقة فغالبًا من سنة إلى 3 سنوات.'),
              ),
              h('input', {
                className: 'input',
                type: 'number',
                min: 1,
                style: { width: 90, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                value: costModel.equipmentLifespanYears,
                onChange: e => updateCostModel('equipmentLifespanYears', e.target.value),
              }),
              h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'سنة'),
            ),
            h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10 } },
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, 'لو عندك أجهزة بأعمار مختلفة، أضفها هنا بشكل اختياري'),
              h('button', {
                className: 'btn sm outline',
                type: 'button',
                onClick: () => setShowExtraEquipment(v => !v),
              }, showExtraEquipment ? 'إخفاء الأعمار المختلفة' : 'إضافة أجهزة بعمر مختلف'),
            ),
            showExtraEquipment ? h('div', { style: { display: 'grid', gap: 10, padding: '12px 0 4px' } },
              extraEquipmentGroups.length ? extraEquipmentGroups.map((group, index) => h('div', {
                key: `equipment-group-${index}`,
                style: { display: 'grid', gridTemplateColumns: '1.2fr 120px 90px auto', gap: 10, alignItems: 'center' },
              },
                h('input', {
                  className: 'input',
                  type: 'text',
                  value: group.name || '',
                  onChange: e => updateExtraEquipmentGroup(index, 'name', e.target.value),
                  style: { padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  placeholder: 'اسم الأصل أو المجموعة',
                }),
                h('input', {
                  className: 'input',
                  type: 'number',
                  min: 0,
                  value: group.cost,
                  onChange: e => updateExtraEquipmentGroup(index, 'cost', e.target.value),
                  style: { padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  placeholder: 'التكلفة',
                }),
                h('input', {
                  className: 'input',
                  type: 'number',
                  min: 1,
                  value: group.lifespanYears,
                  onChange: e => updateExtraEquipmentGroup(index, 'lifespanYears', e.target.value),
                  style: { padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                  placeholder: 'السنوات',
                }),
                h('button', {
                  className: 'btn sm ghost',
                  type: 'button',
                  onClick: () => removeExtraEquipmentGroup(index),
                }, 'حذف'),
              )) : h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, 'لا توجد مجموعات إضافية بعد'),
              h('button', {
                className: 'btn sm outline',
                type: 'button',
                onClick: addExtraEquipmentGroup,
                style: { width: 'fit-content' },
              }, 'إضافة أصل آخر'),
            ) : null,
            [
              ['runningFixedMonthly', 'التشغيل الثابت الشهري', 'إيجار، كهرباء، مياه، إنترنت، تسويق...'],
              ['salariesMonthly', 'الرواتب الثابتة', 'الرواتب الثابتة بعيدًا عن عمولات الأطباء'],
              ['otherFixedMonthly', 'أي بند إضافي ثابت', 'أي بند شهري ثابت تريد إدخاله في تكلفة الساعة'],
            ].map(([key, label, hint]) => h('div', {
              key,
              style: { display: 'grid', gridTemplateColumns: '1.3fr auto auto', gap: 12, alignItems: 'center' },
            },
              h('div', null,
                renderFieldLabel(label, hint),
              ),
              h('input', {
                className: 'input',
                type: 'number',
                min: 0,
                style: { width: 120, padding: '6px 10px', fontSize: 13, textAlign: 'left' },
                value: costModel[key],
                onChange: e => updateCostModel(key, e.target.value),
              }),
              h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'ج.م'),
            )),
          ),
          h('div', { className: 'grid cols-2', style: { gap: 14, marginTop: 18 } },
            [
              {
                label: 'إجمالي التكاليف الشهرية الثابتة',
                value: fmtMoney(totalFixedMonthly),
                color: 'var(--danger)',
                details: [
                  `إهلاك شهري: ${fmtMoney(equipmentDepreciationPerMonth)}`,
                  `تشغيل: ${fmtMoney(costModel.runningFixedMonthly)}`,
                  `رواتب: ${fmtMoney(costModel.salariesMonthly)}`,
                  `إضافي: ${fmtMoney(costModel.otherFixedMonthly)}`,
                ],
              },
              {
                label: 'تكلفة الساعة الفعالة',
                value: fmtMoney(totalFixedPerHour),
                color: 'var(--warning)',
                details: [
                  `ساعات العمل/شهر: ${fmtNumber(workingHoursPerMonth)} ساعة`,
                  `إهلاك/ساعة: ${fmtMoney(equipmentDepreciationPerHour)}`,
                  `تشغيل/ساعة: ${fmtMoney(runningFixedPerHour)}`,
                  `رواتب/ساعة: ${fmtMoney(salariesPerHour)}`,
                  `إضافي/ساعة: ${fmtMoney(otherFixedPerHour)}`,
                ],
              },
            ].map((item) => h('div', {
              key: item.label,
              style: {
                padding: 18,
                background: 'var(--bg-subtle)',
                borderRadius: 'var(--radius-lg)',
                border: '1px solid var(--border)',
              },
            },
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 6 } }, item.label),
              h('div', { style: { fontSize: 28, fontWeight: 900, color: item.color, marginBottom: 10 } }, item.value),
              h('div', { style: { display: 'grid', gap: 4, fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.7 } },
                item.details.map((detail, index) => h('div', { key: index }, detail)),
              ),
            )),
          ),
        ),
      ),

      /* ===== Profitability Snapshot Chart ===== */
      (() => {
        if (loadingBom || allSvcs.length === 0) return null;
        const items = allSvcs.map(svc => {
          const price     = Number(svc.price) || 0;
          const matCost   = Number(bomStats[svc.id]?.cost) || 0;
          const fixedCost = (Number(svc.duration)||30)/60 * totalFixedPerHour;
          const totalCost = matCost + fixedCost;
          const profit    = Math.round(price - totalCost);
          const margin    = price > 0 ? Math.round((price - totalCost) / price * 100) : 0;
          const color     = profit >= 500 ? '#22c55e' : profit >= 200 ? '#f59e0b' : profit >= 0 ? '#f97316' : '#ef4444';
          return { name: svc.name, profit, margin, color, price, totalCost };
        }).sort((a, b) => b.profit - a.profit);   // ← مرتب حسب المبلغ
        const maxP = Math.max(...items.map(i => Math.abs(i.profit)), 1);
        return h('div', { className: 'card p-20', style: { marginBottom: 20 } },
          h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 } },
            h('div', null,
              h('div', { style: { fontWeight: 800, fontSize: 14 } }, '📈 لمحة سريعة — ربح كل خدمة بالجنيه'),
              h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 2 } },
                'مرتب من الأعلى ربحاً · بدون عمولة طبيب'),
            ),
            h('div', { style: { display: 'flex', gap: 8, fontSize: 11 } },
              [['#22c55e','≥500'],['#f59e0b','200–500'],['#f97316','0–200'],['#ef4444','خسارة']]
              .map(([c,l],i) => h('span',{key:i,style:{display:'flex',alignItems:'center',gap:3}},
                h('span',{style:{width:8,height:8,borderRadius:99,background:c,display:'inline-block'}}),l,' ج.م')),
            ),
          ),
          h('div', { style: { display: 'flex', flexDirection: 'column', gap: 7 } },
            items.slice(0, 15).map((item, i) => {
              const barW = Math.max(2, Math.abs(item.profit) / maxP * 100);
              return h('div', { key: i,
                title: `${item.name}\nالربح: ${item.profit} ج.م  (${item.margin}%)\nسعر البيع: ${item.price} ج.م  |  التكلفة: ${Math.round(item.totalCost)} ج.م`,
                style: { display: 'flex', alignItems: 'center', gap: 8 } },
                h('div', { style: { fontSize: 12, fontWeight: 600, minWidth: 140, maxWidth: 140, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--text-primary)' } }, item.name),
                h('div', { style: { flex: 1, background: 'var(--bg-subtle)', borderRadius: 99, height: 10, overflow: 'hidden' } },
                  h('div', { style: { width: barW + '%', height: '100%', background: item.color, borderRadius: 99, transition: 'width 0.4s' } }),
                ),
                h('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-end', minWidth: 90 } },
                  h('span', { style: { fontSize: 14, fontWeight: 900, color: item.color, lineHeight: 1.1 } },
                    (item.profit > 0 ? '+' : '') + item.profit + ' ج.م'),
                  h('span', { style: { fontSize: 10, fontWeight: 600, color: item.color, opacity: 0.7 } },
                    (item.margin > 0 ? '+' : '') + item.margin + '%'),
                ),
              );
            }),
          ),
        );
      })(),

      /* ===== Modals ===== */
      showAddServiceP ? h(AddServiceModal, {
        onClose: () => setShowAddServiceP(false),
        onSaved: (svc) => { if (setServices) setServices(prev => [svc, ...prev]); setShowAddServiceP(false); },
      }) : null,
      editServiceP ? h(EditServiceModal, {
        service: editServiceP,
        onClose: () => setEditServiceP(null),
        onSaved: (updated) => { if (setServices) setServices(prev => prev.map(s => s.id === updated.id ? updated : s)); setEditServiceP(null); },
      }) : null,

      /* ===== Profitability Analysis (with inline duration editing) ===== */
      h('div', { className: 'card', style: { overflow: 'hidden' } },
        h('div', { style: { padding: '14px 20px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
          h('div', null,
            h('div', { style: { fontWeight: 800, fontSize: 15 } }, '💰 تحليل ربحية الخدمات'),
            loadingBom ? h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, 'جاري تحميل تكاليف المواد...') : null,
          ),
          h('button', { className: 'btn primary', onClick: () => setShowAddServiceP(true) },
            h(Icons.Plus, { size: 15 }), 'خدمة جديدة',
          ),
        ),
        h('table', { className: 'data-table' },
          h('thead', null, h('tr', null,
            ['الخدمة والمدة', 'سعر البيع', 'تكلفة المواد', 'التكلفة الثابتة', 'عمولة الطبيب', 'تكلفة إجمالية', 'هامش الربح', 'نسبة الربح', 'التقييم', ''].map((t, i) =>
              h('th', { key: i }, t))
          )),
          h('tbody', null,
            allSvcs.length === 0 ?
              h('tr', null, h('td', { colSpan: 10, style: { textAlign: 'center', padding: 32, color: 'var(--text-tertiary)' } }, 'لا توجد خدمات — اضغط "خدمة جديدة" للبدء')) :
            allSvcs.map(svc => {
              const servicePrice = Number(svc.price) || 0;
              const durationMinutes = Number(svc.duration) || 30;
              const durationHours = durationMinutes / 60;
              const materialStats = bomStats[svc.id] || { cost: 0, itemsCount: 0 };
              const materialCost = Number(materialStats.cost) || 0;
              const commissionEntry = normalizeCommissionEntry(doctorCommissionMap[svc.id]);
              const doctorCommission = commissionEntry.mode === 'percent'
                ? (servicePrice * (commissionEntry.value || 0)) / 100
                : (commissionEntry.value || 0);
              const loadedFixedCost = totalFixedPerHour * durationHours;
              const totalCost = materialCost + loadedFixedCost + doctorCommission;
              const profit = servicePrice - totalCost;
              const margin = servicePrice > 0 ? (profit / servicePrice) * 100 : 0;
              const rating = profit < 0
                ? '🔴 خاسرة'
                : margin >= 55
                  ? '🟢 ممتازة'
                  : margin >= 35
                    ? '🟡 جيدة'
                    : margin >= 15
                      ? '🟠 تحتاج تحسين'
                      : '🔴 ضعيفة';

              return h('tr', { key: svc.id },
                h('td', null,
                  h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
                    h('span', { style: { fontWeight: 700 } }, svc.name),
                    h('div', {
                      style: {
                        display: 'flex', alignItems: 'center', gap: 3,
                        background: 'var(--bg-subtle)', borderRadius: 6, padding: '2px 6px',
                      },
                    },
                      h('input', {
                        className: 'input',
                        type: 'number', min: 5, step: 5,
                        value: durationDrafts[svc.id] ?? durationMinutes,
                        onChange: e => setDurationDrafts(prev => ({ ...prev, [svc.id]: e.target.value })),
                        onBlur: () => saveServiceDuration(svc.id),
                        onKeyDown: e => { if (e.key === 'Enter') e.currentTarget.blur(); },
                        style: { width: 46, padding: '2px 4px', fontSize: 11, textAlign: 'center', border: 'none', background: 'transparent' },
                        title: 'المدة بالدقيقة — تؤثر مباشرة على التكلفة الثابتة',
                      }),
                      h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'د'),
                    ),
                  ),
                ),
                h('td', null,
                  h('input', {
                    className: 'input',
                    type: 'number',
                    min: 0,
                    value: priceDrafts[svc.id] ?? servicePrice,
                    onChange: e => setPriceDrafts(prev => ({ ...prev, [svc.id]: e.target.value })),
                    onBlur: () => saveServicePrice(svc.id),
                    onKeyDown: e => { if (e.key === 'Enter') { e.currentTarget.blur(); } },
                    style: { width: 96, padding: '6px 8px', fontSize: 13, textAlign: 'left', fontWeight: 800, color: 'var(--accent)' },
                    title: 'يتحدث في الخدمات والأسعار أيضًا',
                  }),
                ),
                h('td', { style: { color: 'var(--danger)' } },
                  h('div', { style: { fontWeight: 700 } }, fmtMoney(materialCost)),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, materialStats.itemsCount ? `${fmtNumber(materialStats.itemsCount)} مادة مرتبطة` : 'لا توجد مواد مرتبطة'),
                ),
                h('td', { style: { color: 'var(--warning)' } },
                  h('div', { style: { fontWeight: 800, fontSize: 14 } }, fmtMoney(loadedFixedCost)),
                  h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, `تكلفة الساعة: ${fmtMoney(totalFixedPerHour)}`),
                ),
                h('td', null,
                  h('div', {
                    style: { display: 'flex', alignItems: 'center', gap: 6, minWidth: 144 },
                    title: `العمولة الفعلية: ${fmtMoney(doctorCommission)}`,
                  },
                    h('select', {
                      className: 'input',
                      value: commissionEntry.mode,
                      onChange: e => updateDoctorCommission(svc.id, { mode: e.target.value }),
                      style: { width: 74, padding: '6px 4px', fontSize: 12 },
                    },
                      h('option', { value: 'amount' }, 'مبلغ'),
                      h('option', { value: 'percent' }, 'نسبة'),
                    ),
                    h('input', {
                      className: 'input',
                      type: 'number',
                      min: 0,
                      value: commissionEntry.value,
                      onChange: e => updateDoctorCommission(svc.id, { value: e.target.value }),
                      style: { width: 62, padding: '6px 8px', fontSize: 13, textAlign: 'left' },
                    }),
                    h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)', minWidth: 28 } }, commissionEntry.mode === 'percent' ? '%' : 'ج.م'),
                  ),
                ),
                h('td', { style: { fontWeight: 700, color: 'var(--danger)' } }, fmtMoney(totalCost)),
                h('td', { style: { fontWeight: 800, color: profit >= 0 ? 'var(--success)' : 'var(--danger)' } }, fmtMoney(profit)),
                h('td', null,
                  h('div', { className: 'flex ai-c gap-8' },
                    h('div', { className: 'progress', style: { flex: 1, height: 6 } },
                      h('div', { className: 'progress-bar', style: { width: Math.max(0, Math.min(100, margin)) + '%', background: margin >= 55 ? 'var(--success)' : margin >= 35 ? 'var(--accent)' : margin >= 15 ? 'var(--warning)' : 'var(--danger)' } }),
                    ),
                    h('span', { style: { fontSize: 12, fontWeight: 700, minWidth: 50 } }, fmtPercent(margin)),
                  ),
                ),
                h('td', null, h('span', { style: { fontSize: 12 } }, rating)),
                h('td', null,
                  h('div', { style: { display: 'flex', gap: 4 } },
                    h('button', { className: 'btn sm outline', title: 'تعديل', onClick: () => setEditServiceP(svc) },
                      h(Icons.Edit, { size: 12 }),
                    ),
                    h('button', {
                      className: 'btn sm danger outline',
                      title: 'حذف',
                      onClick: async () => {
                        if (!window.confirm('حذف الخدمة ومكوناتها؟')) return;
                        try {
                          await DB.deleteService(svc.id);
                          if (setServices) setServices(prev => prev.filter(x => x.id !== svc.id));
                          toast('تم حذف الخدمة');
                        } catch (e) { toast('❌ ' + (e.message || 'تعذر الحذف')); }
                      },
                    }, h(Icons.Trash, { size: 12 })),
                  ),
                ),
              );
            }),
          ),
        ),
      ),
    ),
  );
}

// ============================================================
// WhatsApp Reminders Screen
// ============================================================
const WA_TEMPLATES = [
  { id: 'reminder',  label: 'تذكير بالموعد',    icon: '📅', text: (p) => `مرحباً ${p.name}، نذكّركم بموعدكم في عيادة سِنان كلينيك غداً الساعة ${p.time} مع ${p.doctor}. نرجو الحضور في الوقت المحدد. 🦷` },
  { id: 'recall',    label: 'استدعاء دوري',      icon: '🔄', text: (p) => `مرحباً ${p.name}، حان موعد كشفكم الدوري في عيادة سِنان كلينيك. يسعدنا حجز موعد مناسب لكم. تواصلوا معنا لتحديد الموعد. 📅` },
  { id: 'lab',       label: 'جاهزية التاج',      icon: '👑', text: (p) => `مرحباً ${p.name}، نسعدكم بإخباركم أن التاج/التركيب جاهز. يرجى التواصل لحجز موعد التركيب في أقرب وقت. 🦷✨` },
  { id: 'followup',  label: 'متابعة بعد العلاج', icon: '💊', text: (p) => `مرحباً ${p.name}، نتمنى أن تكونوا بصحة وعافية بعد زيارتكم لعيادة سِنان كلينيك. هل تحتاجون لأي استفسار؟ نحن في خدمتكم. 🦷` },
];

function sendWhatsApp(phone, message) {
  const cleaned = String(phone || '').replace(/\D/g, '').replace(/^0/, '20');
  if (!cleaned || cleaned.length < 10) { alert('رقم الهاتف غير صحيح'); return; }
  window.open(`https://wa.me/${cleaned}?text=${encodeURIComponent(message)}`, '_blank');
}

function WhatsAppReminders() {
  const { appointments, patients } = useContext(AppContext);
  const allAppts    = appointments || window.APPOINTMENTS || [];
  const allPatients = patients     || window.PATIENTS     || [];
  const [templateId, setTemplateId] = useState('reminder');
  const [sent, setSent]             = useState({});
  const [search, setSearch]         = useState('');
  const tmpl = WA_TEMPLATES.find(t => t.id === templateId);
  const tomorrowStr   = new Date(Date.now() + 86400000).toISOString().slice(0, 10);
  const tomorrowAppts = allAppts.filter(a => a.date === tomorrowStr && a.status !== 'cancelled');
  const activePats    = allPatients.filter(p => p.name.includes(search) || (p.phone||'').includes(search)).slice(0, 30);
  const isReminderMode= templateId === 'reminder';
  const previewMsg    = tmpl.text({ name: 'محمد أحمد', time: '10:00 ص', doctor: 'د. سِنان' });

  const handleSend = (appt) => {
    const pat = allPatients.find(p => p.id === appt.patientId) || {};
    sendWhatsApp(pat.phone || '', tmpl.text({ name: appt.patient, time: appt.time, doctor: appt.doctor, ...pat }));
    setSent(s => ({ ...s, [appt.id]: true }));
  };
  const handleSendPat = (pat) => {
    sendWhatsApp(pat.phone || '', tmpl.text({ name: pat.name, time: '—', doctor: '—', ...pat }));
    setSent(s => ({ ...s, [pat.id]: true }));
  };

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, '💬 تذكيرات واتساب'),
        h('div', { className: 'page-subtitle' }, 'إرسال رسائل واتساب للمرضى بضغطة واحدة'),
      ),
    ),
    h('div', { className: 'page-content' },
      // Template selector
      h('div', { className: 'card p-20', style: { marginBottom: 16 } },
        h('div', { style: { fontWeight: 800, fontSize: 14, marginBottom: 12 } }, 'اختر نوع الرسالة'),
        h('div', { style: { display: 'flex', gap: 10, flexWrap: 'wrap' } },
          WA_TEMPLATES.map(t => h('button', {
            key: t.id, className: 'btn ' + (templateId === t.id ? 'primary' : 'outline'),
            onClick: () => setTemplateId(t.id),
          }, t.icon + ' ' + t.label)),
        ),
      ),
      h('div', { style: { display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 16 } },
        // List
        h('div', null,
          isReminderMode
            ? h('div', { className: 'card' },
                h('div', { style: { padding: '14px 20px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
                  h('div', null,
                    h('div', { style: { fontWeight: 800, fontSize: 14 } }, '📅 مواعيد الغد'),
                    h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, tomorrowAppts.length + ' موعد — ' + tomorrowStr),
                  ),
                  tomorrowAppts.length > 0 && h('button', { className: 'btn wa-green sm', onClick: () => tomorrowAppts.forEach(a => handleSend(a)) }, '📤 إرسال للكل'),
                ),
                h('div', { style: { padding: 12, display: 'flex', flexDirection: 'column', gap: 8 } },
                  tomorrowAppts.length === 0
                    ? h('div', { style: { padding: 24, textAlign: 'center', color: 'var(--text-tertiary)', fontSize: 13 } }, 'لا توجد مواعيد غداً')
                    : tomorrowAppts.map(a => {
                        const pat = allPatients.find(p => p.id === a.patientId) || {};
                        return h('div', { key: a.id, style: { display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', background: 'var(--bg-hover)', borderRadius: 'var(--radius)', border: '1px solid var(--border)' } },
                          h('div', { className: 'avatar sm' }, (a.patient||'?').charAt(0)),
                          h('div', { style: { flex: 1, minWidth: 0 } },
                            h('div', { style: { fontSize: 13, fontWeight: 700 } }, a.patient),
                            h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, a.time + ' · ' + (a.doctor||'—') + (pat.phone ? ' · ' + pat.phone : '')),
                          ),
                          sent[a.id]
                            ? h('span', { className: 'chip success', style: { fontSize: 11 } }, '✓ أُرسل')
                            : h('button', { className: 'btn wa-green sm', style: { fontSize: 11 }, onClick: () => handleSend(a) }, '📤'),
                        );
                      }),
                ),
              )
            : h('div', { className: 'card' },
                h('div', { style: { padding: '14px 20px', borderBottom: '1px solid var(--border)' } },
                  h('div', { style: { fontWeight: 800, fontSize: 14, marginBottom: 8 } }, '👥 المرضى'),
                  h('input', { className: 'input', placeholder: 'ابحث بالاسم أو الهاتف...', value: search, onInput: e => setSearch(e.target.value) }),
                ),
                h('div', { style: { padding: 12, maxHeight: 400, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 8 } },
                  activePats.map(p => h('div', { key: p.id, style: { display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', background: 'var(--bg-hover)', borderRadius: 'var(--radius)', border: '1px solid var(--border)' } },
                    h('div', { className: 'avatar sm' }, p.avatar || p.name?.charAt(0) || '?'),
                    h('div', { style: { flex: 1, minWidth: 0 } },
                      h('div', { style: { fontSize: 13, fontWeight: 700 } }, p.name),
                      h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, p.phone || 'لا يوجد هاتف'),
                    ),
                    p.phone
                      ? (sent[p.id] ? h('span', { className: 'chip success', style: { fontSize: 11 } }, '✓ أُرسل') : h('button', { className: 'btn wa-green sm', style: { fontSize: 11 }, onClick: () => handleSendPat(p) }, '📤'))
                      : h('span', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'لا هاتف'),
                  )),
                ),
              ),
        ),
        // Preview
        h('div', null,
          h('div', { className: 'card p-20' },
            h('div', { style: { fontWeight: 800, fontSize: 14, marginBottom: 12 } }, '👁 معاينة الرسالة'),
            h('div', { className: 'wa-template-preview' }, previewMsg),
            h('div', { style: { marginTop: 10, fontSize: 12, color: 'var(--text-tertiary)' } }, '* الاسم والوقت يتغيران تلقائياً لكل مريض'),
          ),
          h('div', { className: 'card p-20', style: { marginTop: 14 } },
            h('div', { style: { fontWeight: 700, fontSize: 13, marginBottom: 8 } }, 'ℹ ملاحظات'),
            h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.9 } },
              h('div', null, '• يفتح واتساب على المتصفح أو الموبايل'),
              h('div', null, '• يعمل مع أرقام مصرية (+20)'),
              h('div', null, '• الإرسال الجماعي التلقائي يحتاج WhatsApp Business API'),
            ),
          ),
        ),
      ),
    ),
  );
}

function WhatsAppRemindersV2() {
  const { appointments, patients, toast, clinicId } = useContext(AppContext);
  const allAppts = appointments || window.APPOINTMENTS || [];
  const allPatients = patients || window.PATIENTS || [];
  const notify = (message) => {
    if (typeof toast === 'function') toast(message);
    else if (typeof window.toast === 'function') window.toast(message);
    else window.alert(message);
  };

  const [templates, setTemplates] = useState(() => loadWaTemplates(clinicId));
  const [templateId, setTemplateId] = useState(() => loadWaTemplates(clinicId)[0]?.id || 'reminder');
  const [editor, setEditor] = useState({ label: '', body: '' });
  const [sent, setSent] = useState({});
  const [search, setSearch] = useState('');
  const [selectedKey, setSelectedKey] = useState('');
  const editorRef = useRef(null);

  useEffect(() => {
    const nextTemplates = loadWaTemplates(clinicId);
    setTemplates(nextTemplates);
    setTemplateId((current) => nextTemplates.some(t => t.id === current) ? current : (nextTemplates[0]?.id || 'reminder'));
  }, [clinicId]);

  const tmpl = useMemo(
    () => templates.find(t => t.id === templateId) || templates[0] || cloneWaTemplate(WA_DEFAULT_TEMPLATES[0]),
    [templates, templateId],
  );

  useEffect(() => {
    setEditor({ label: tmpl?.label || '', body: tmpl?.body || '' });
  }, [tmpl?.id, tmpl?.label, tmpl?.body]);

  const todayStr = getCairoTodayStr();
  const tomorrowStr = addDaysToIsoDate(todayStr, 1);
  const normalizedSearch = String(search || '').trim().toLowerCase();
  const isReminderMode = templateId === 'reminder';

  const reminderRows = useMemo(() => allAppts
    .filter(a => a.date === tomorrowStr && a.status !== 'cancelled')
    .map((appt) => {
      const patient = allPatients.find(p => p.id === appt.patientId) || {};
      return {
        key: `appt:${appt.id}`,
        appointment: appt,
        patient,
        phone: patient.phone || '',
        title: appt.patient || patient.name || 'مريض',
        subtitle: [appt.time || '—', appt.doctor || '—', patient.phone || 'لا يوجد هاتف'].filter(Boolean).join(' · '),
      };
    })
    .filter((row) => {
      if (!normalizedSearch) return true;
      return [row.title, row.subtitle, row.phone, row.appointment?.doctor]
        .join(' ')
        .toLowerCase()
        .includes(normalizedSearch);
    }), [allAppts, allPatients, normalizedSearch, tomorrowStr]);

  const patientRows = useMemo(() => allPatients
    .filter((patient) => {
      if (!normalizedSearch) return true;
      return [patient.name, patient.phone, patient.email]
        .join(' ')
        .toLowerCase()
        .includes(normalizedSearch);
    })
    .slice(0, 50)
    .map((patient) => ({
      key: `pat:${patient.id}`,
      patient,
      phone: patient.phone || '',
      title: patient.name || 'مريض',
      subtitle: patient.phone || 'لا يوجد هاتف',
    })), [allPatients, normalizedSearch]);

  const rows = isReminderMode ? reminderRows : patientRows;

  useEffect(() => {
    if (!rows.length) {
      setSelectedKey('');
      return;
    }
    if (!rows.some(row => row.key === selectedKey)) setSelectedKey(rows[0].key);
  }, [rows, selectedKey]);

  const selectedRow = rows.find(row => row.key === selectedKey) || null;

  const previewPayload = useMemo(() => {
    const patient = selectedRow?.patient || {};
    const appointment = selectedRow?.appointment || {};
    return {
      name: patient.name || appointment.patient || 'محمد أحمد',
      doctor: appointment.doctor || 'د. سِنان',
      date: formatWaDate(appointment.date || tomorrowStr),
      time: appointment.time || '10:00 ص',
      clinic: WA_DEFAULT_CLINIC_NAME,
      phone: patient.phone || '01000000000',
      room: appointment.room || 'الغرفة',
    };
  }, [selectedRow, tomorrowStr]);

  const previewMsg = interpolateWaTemplate(editor.body || tmpl.body, previewPayload);
  const validCount = rows.filter(row => isValidWhatsAppPhone(row.phone)).length;
  const missingCount = rows.length - validCount;

  const persistTemplates = (nextTemplates, nextSelectedId = templateId) => {
    setTemplates(nextTemplates);
    setTemplateId(nextSelectedId);
    saveWaTemplates(clinicId, nextTemplates);
  };

  const handleSaveTemplate = () => {
    const nextLabel = String(editor.label || '').trim();
    const nextBody = String(editor.body || '').trim();
    if (!nextLabel) { notify('اكتب اسم الرسالة أولاً'); return; }
    if (!nextBody) { notify('اكتب نص الرسالة أولاً'); return; }
    const nextTemplates = templates.map((template) => template.id === tmpl.id
      ? { ...template, label: nextLabel, body: nextBody }
      : template);
    persistTemplates(nextTemplates, tmpl.id);
    notify('تم حفظ القالب ✅');
  };

  const handleAddTemplate = () => {
    const id = `custom-${Date.now()}`;
    const newTemplate = {
      id,
      label: 'رسالة جديدة',
      icon: '💬',
      body: 'مرحباً {name}، هذه رسالة جديدة من {clinic}.',
      locked: false,
    };
    const nextTemplates = [...templates, newTemplate];
    persistTemplates(nextTemplates, id);
    notify('تمت إضافة رسالة جديدة');
  };

  const handleResetTemplate = () => {
    const fallback = WA_DEFAULT_TEMPLATES.find(template => template.id === tmpl.id);
    if (!fallback) return;
    const nextTemplates = templates.map((template) => template.id === tmpl.id ? cloneWaTemplate(fallback) : template);
    persistTemplates(nextTemplates, tmpl.id);
    notify('تمت استعادة النص الافتراضي');
  };

  const handleDeleteTemplate = () => {
    if (tmpl.locked) return;
    if (!window.confirm(`حذف الرسالة "${tmpl.label}"؟`)) return;
    const nextTemplates = templates.filter(template => template.id !== tmpl.id);
    persistTemplates(nextTemplates, nextTemplates[0]?.id || 'reminder');
    notify('تم حذف الرسالة');
  };

  const insertVariable = (token) => {
    const textarea = editorRef.current;
    if (!textarea) {
      setEditor(current => ({ ...current, body: `${current.body || ''}${token}` }));
      return;
    }
    const start = textarea.selectionStart || 0;
    const end = textarea.selectionEnd || 0;
    const nextBody = `${editor.body.slice(0, start)}${token}${editor.body.slice(end)}`;
    setEditor(current => ({ ...current, body: nextBody }));
    requestAnimationFrame(() => {
      textarea.focus();
      const caret = start + token.length;
      textarea.setSelectionRange(caret, caret);
    });
  };

  const payloadForRow = (row) => ({
    ...previewPayload,
    name: row?.patient?.name || row?.appointment?.patient || previewPayload.name,
    doctor: row?.appointment?.doctor || previewPayload.doctor,
    date: formatWaDate(row?.appointment?.date || tomorrowStr),
    time: row?.appointment?.time || previewPayload.time,
    phone: row?.patient?.phone || previewPayload.phone,
    room: row?.appointment?.room || previewPayload.room,
  });

  const copyMessageForRow = async (row) => {
    if (!row) return;
    const copied = await copyText(interpolateWaTemplate(editor.body || tmpl.body, payloadForRow(row)));
    notify(copied ? 'تم نسخ الرسالة ✅' : 'تعذر نسخ الرسالة');
  };

  const openWhatsAppForRow = (row) => {
    if (!row || !isValidWhatsAppPhone(row.phone)) {
      notify('رقم الهاتف غير صالح أو غير موجود');
      return false;
    }
    const opened = window.open(
      `https://wa.me/${normalizeWhatsAppPhone(row.phone)}?text=${encodeURIComponent(interpolateWaTemplate(editor.body || tmpl.body, payloadForRow(row)))}`,
      '_blank',
    );
    if (!opened) {
      notify('المتصفح منع فتح واتساب. اسمح بالنوافذ المنبثقة ثم حاول مرة أخرى');
      return false;
    }
    const sentKey = row.appointment?.id || row.patient?.id || row.key;
    setSent(current => ({ ...current, [sentKey]: true }));
    return true;
  };

  const handleBulkSend = () => {
    const validRows = rows.filter(row => isValidWhatsAppPhone(row.phone)).slice(0, 20);
    if (!validRows.length) {
      notify('لا توجد أرقام صالحة للإرسال');
      return;
    }
    if (!window.confirm(`سيتم فتح واتساب لـ ${validRows.length} مريض. هل تريد المتابعة؟`)) return;
    validRows.forEach((row, index) => {
      window.setTimeout(() => openWhatsAppForRow(row), index * 350);
    });
  };

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, '💬 تذكيرات واتساب'),
        h('div', { className: 'page-subtitle' }, 'إدارة القوالب ومعاينة الرسائل ثم الإرسال أو النسخ بسرعة'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'card p-20', style: { marginBottom: 16 } },
        h('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', alignItems: 'center', marginBottom: 12 } },
          h('div', { style: { fontWeight: 800, fontSize: 14 } }, 'اختر نوع الرسالة'),
          h('button', { className: 'btn outline sm', onClick: handleAddTemplate }, h(Icons.Plus, { size: 14 }), 'إضافة رسالة'),
        ),
        h('div', { style: { display: 'flex', gap: 10, flexWrap: 'wrap' } },
          templates.map(t => h('button', {
            key: t.id,
            className: 'btn ' + (templateId === t.id ? 'primary' : 'outline'),
            onClick: () => setTemplateId(t.id),
          }, t.icon + ' ' + t.label)),
        ),
        h('div', { className: 'wa-stats' },
          h('div', { className: 'wa-stat' },
            h('div', { className: 'wa-stat-label' }, isReminderMode ? 'مواعيد الغد' : 'النتائج'),
            h('div', { className: 'wa-stat-value' }, rows.length),
          ),
          h('div', { className: 'wa-stat' },
            h('div', { className: 'wa-stat-label' }, 'أرقام صالحة'),
            h('div', { className: 'wa-stat-value', style: { color: 'var(--success)' } }, validCount),
          ),
          h('div', { className: 'wa-stat' },
            h('div', { className: 'wa-stat-label' }, 'أرقام ناقصة'),
            h('div', { className: 'wa-stat-value', style: { color: 'var(--danger)' } }, missingCount),
          ),
        ),
      ),
      h('div', { style: { display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 16 } },
        h('div', null,
          h('div', { className: 'card' },
            h('div', { style: { padding: '14px 20px', borderBottom: '1px solid var(--border)' } },
              h('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 } },
                h('div', { style: { fontWeight: 800, fontSize: 14 } }, isReminderMode ? '📅 مواعيد الغد' : '👥 قائمة المرضى'),
                h('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap' } },
                  h('button', { className: 'btn outline sm', onClick: () => copyMessageForRow(selectedRow), disabled: !selectedRow }, h(Icons.Copy, { size: 14 }), 'نسخ المعاينة'),
                  rows.length > 0 && h('button', { className: 'btn wa-green sm', onClick: handleBulkSend }, 'فتح الصالحين'),
                ),
              ),
              h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 10 } },
                isReminderMode ? `${rows.length} موعد مستحق غداً — ${formatWaDate(tomorrowStr)}` : 'ابحث بالاسم أو الهاتف لاختيار المستقبل المناسب'),
              h('input', { className: 'input', placeholder: 'ابحث بالاسم أو الهاتف...', value: search, onInput: e => setSearch(e.target.value) }),
            ),
            h('div', { style: { padding: 12, maxHeight: 520, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 8 } },
              rows.length === 0
                ? h('div', { style: { padding: 24, textAlign: 'center', color: 'var(--text-tertiary)', fontSize: 13 } }, isReminderMode ? 'لا توجد مواعيد غداً بهذا البحث' : 'لا توجد نتائج مطابقة')
                : rows.map((row) => {
                    const sentKey = row.appointment?.id || row.patient?.id || row.key;
                    const selected = row.key === selectedKey;
                    const hasPhone = isValidWhatsAppPhone(row.phone);
                    return h('div', {
                      key: row.key,
                      className: 'wa-recipient-row' + (selected ? ' selected' : ''),
                      onClick: () => setSelectedKey(row.key),
                    },
                      h('div', { className: 'avatar sm' }, (row.title || '?').charAt(0)),
                      h('div', { style: { flex: 1, minWidth: 0 } },
                        h('div', { style: { fontSize: 13, fontWeight: 700, display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
                          row.title,
                          sent[sentKey] && h('span', { className: 'chip success', style: { fontSize: 10 } }, 'أُرسل'),
                          !hasPhone && h('span', { className: 'chip danger', style: { fontSize: 10 } }, 'بدون رقم صالح'),
                        ),
                        h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, row.subtitle),
                      ),
                      h('div', { style: { display: 'flex', gap: 6, flexWrap: 'wrap' } },
                        h('button', {
                          className: 'btn outline sm',
                          onClick: (event) => { event.stopPropagation(); copyMessageForRow(row); },
                        }, h(Icons.Copy, { size: 14 }), 'نسخ'),
                        h('button', {
                          className: 'btn wa-green sm',
                          disabled: !hasPhone,
                          onClick: (event) => { event.stopPropagation(); openWhatsAppForRow(row); },
                        }, 'واتساب'),
                      ),
                    );
                  }),
            ),
          ),
        ),
        h('div', null,
          h('div', { className: 'card p-20' },
            h('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', alignItems: 'center', marginBottom: 12 } },
              h('div', { style: { fontWeight: 800, fontSize: 14 } }, 'تحرير الرسالة'),
              !tmpl.locked && h('button', { className: 'btn outline sm danger', onClick: handleDeleteTemplate }, h(Icons.Trash, { size: 14 }), 'حذف الرسالة'),
            ),
            h('div', { className: 'wa-template-editor' },
              h('div', null,
                h('div', { className: 'label' }, 'اسم الرسالة'),
                h('input', {
                  className: 'input',
                  value: editor.label,
                  onChange: (event) => setEditor(current => ({ ...current, label: event.target.value })),
                  placeholder: 'مثال: تذكير قبل الموعد',
                }),
              ),
              h('div', null,
                h('div', { className: 'label' }, 'المتغيرات الجاهزة'),
                h('div', { className: 'wa-variable-list' },
                  WA_TEMPLATE_VARIABLES.map((item) => h('button', {
                    key: item.token,
                    type: 'button',
                    className: 'wa-variable-chip',
                    onClick: () => insertVariable(item.token),
                  }, item.label)),
                ),
              ),
            ),
            h('div', { className: 'label', style: { marginTop: 12 } }, 'نص الرسالة'),
            h('textarea', {
              ref: editorRef,
              className: 'input',
              rows: 7,
              style: { resize: 'vertical', minHeight: 164 },
              value: editor.body,
              onChange: (event) => setEditor(current => ({ ...current, body: event.target.value })),
              placeholder: 'اكتب الرسالة هنا...',
            }),
            h('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 12 } },
              h('button', { className: 'btn primary sm', onClick: handleSaveTemplate }, h(Icons.Edit, { size: 14 }), 'حفظ التعديلات'),
              tmpl.locked && h('button', { className: 'btn outline sm', onClick: handleResetTemplate }, h(Icons.RefreshCw, { size: 14 }), 'استعادة الافتراضي'),
              h('button', { className: 'btn outline sm', onClick: () => copyText(previewMsg).then(ok => notify(ok ? 'تم نسخ المعاينة ✅' : 'تعذر النسخ')) }, h(Icons.Copy, { size: 14 }), 'نسخ المعاينة'),
            ),
          ),
          h('div', { className: 'card p-20', style: { marginTop: 14 } },
            h('div', { style: { fontWeight: 800, fontSize: 14, marginBottom: 12 } }, '👁 معاينة الرسالة'),
            h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginBottom: 10 } },
              selectedRow ? `المعاينة الحالية لـ ${previewPayload.name}` : 'المعاينة الافتراضية'),
            h('div', { className: 'wa-template-preview' }, previewMsg),
            h('div', { style: { marginTop: 10, fontSize: 12, color: 'var(--text-tertiary)' } }, '* الاسم والتاريخ والوقت والطبيب تتغير تلقائياً لكل مريض'),
          ),
          h('div', { className: 'card p-20', style: { marginTop: 14 } },
            h('div', { style: { fontWeight: 700, fontSize: 13, marginBottom: 8 } }, 'ℹ ملاحظات'),
            h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.9 } },
              h('div', null, '• الرسائل الآن قابلة للتعديل والإضافة من نفس الشاشة'),
              h('div', null, '• زر "فتح الصالحين" يفتح حتى 20 محادثة كحد أقصى في كل مرة'),
              h('div', null, '• الإرسال الجماعي التلقائي الحقيقي يحتاج WhatsApp Business API'),
            ),
          ),
        ),
      ),
    ),
  );
}

// ============================================================
// Lab Orders Screen
// ============================================================
const LAB_STATUSES = {
  pending: { label: 'في الانتظار', chip: 'lab-pending', icon: '⏳' },
  sent:    { label: 'عند المختبر', chip: 'lab-sent',    icon: '🔬' },
  done:    { label: 'استُلم',       chip: 'lab-done',    icon: '✅' },
  late:    { label: 'متأخر',        chip: 'lab-late',    icon: '🔴' },
};
const LAB_WORK_TYPES = ['تاج بورسلين','تاج زيركون','جسر','فينير','ريتينر','طقم أسنان كامل','جبيرة','حشو مختبري','أخرى'];

function LabOrders() {
  const { clinicId, patients, toast } = useContext(AppContext);
  const allPatients = patients || window.PATIENTS || [];
  const todayStr    = new Date().toISOString().slice(0, 10);

  const [orders, setOrders]           = useState([]);
  const [filterStatus, setFilterStatus]= useState('all');
  const [search, setSearch]           = useState('');
  const [showModal, setShowModal]     = useState(false);
  const [editOrder, setEditOrder]     = useState(null);
  const [loadingOrders, setLoadingOrders] = useState(true);
  const [dbError, setDbError]         = useState(false);
  const [saving, setSaving]           = useState(false);

  const enriched = orders.map(o => ({
    ...o, effectiveStatus: o.status !== 'done' && o.due_date < todayStr ? 'late' : o.status,
  }));

  React.useEffect(() => {
    if (!clinicId) return;
    setLoadingOrders(true);
    DB.getLabOrders(clinicId)
      .then(data => { setOrders(data || []); setDbError(false); })
      .catch(e => { console.error(e); setDbError(true); })
      .finally(() => setLoadingOrders(false));
  }, [clinicId]);

  const filtered = enriched.filter(o =>
    (filterStatus === 'all' || o.effectiveStatus === filterStatus) &&
    (!search || (o.patient_name||'').includes(search) || (o.lab_name||'').includes(search) || (o.work_type||'').includes(search))
  ).sort((a, b) => a.due_date > b.due_date ? 1 : -1);

  const kpis = [
    { key: 'all',     label: 'الكل',          val: enriched.length },
    { key: 'pending', label: 'في الانتظار',   val: enriched.filter(o => o.effectiveStatus==='pending').length },
    { key: 'sent',    label: 'عند المختبر',   val: enriched.filter(o => o.effectiveStatus==='sent').length    },
    { key: 'late',    label: 'متأخر',         val: enriched.filter(o => o.effectiveStatus==='late').length    },
    { key: 'done',    label: 'مكتمل',         val: enriched.filter(o => o.effectiveStatus==='done').length    },
  ];

  const mutate = async (fn, successMsg) => {
    try { await fn(); if (successMsg) toast(successMsg); }
    catch(e) { toast('حدث خطأ — ' + (e.message || '')); }
  };

  const handleMarkSent    = (o) => mutate(async () => { await DB.updateLabOrder(o.id, { status: 'sent' }); setOrders(p => p.map(x => x.id===o.id ? {...x, status:'sent'} : x)); }, '🔬 تم — عند المختبر');
  const handleReceive     = (o) => mutate(async () => { await DB.updateLabOrder(o.id, { status:'done', received_date: todayStr }); setOrders(p => p.map(x => x.id===o.id ? {...x, status:'done', received_date: todayStr} : x)); }, '✅ تم تسجيل الاستلام');
  const handleDelete      = async (o) => { if (!confirm('حذف هذا الطلب؟')) return; mutate(async () => { await DB.deleteLabOrder(o.id); setOrders(p => p.filter(x => x.id!==o.id)); }, 'تم الحذف'); };

  const handleSave = async (form) => {
    setSaving(true);
    try {
      if (editOrder) {
        await DB.updateLabOrder(editOrder.id, form);
        setOrders(p => p.map(o => o.id===editOrder.id ? {...o, ...form} : o));
        toast('✅ تم التحديث');
      } else {
        const newO = await DB.addLabOrder(clinicId, form);
        setOrders(p => [newO, ...p]);
        toast('✅ تمت الإضافة');
      }
      setShowModal(false); setEditOrder(null);
    } catch(e) { toast('خطأ: ' + (e.message || 'تحقق من البيانات')); }
    finally { setSaving(false); }
  };

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, '🔬 الطلبات المخبرية'),
        h('div', { className: 'page-subtitle' }, 'تتبع التيجان والجسور والريتينرات المرسلة للمختبر'),
      ),
      h('button', { className: 'btn primary', onClick: () => { setEditOrder(null); setShowModal(true); } },
        h(Icons.Plus, { size: 16 }), 'طلب جديد',
      ),
    ),
    h('div', { className: 'page-content' },
      // DB Error
      dbError && h('div', { style: { background:'var(--danger-soft)', border:'1px solid var(--danger)', borderRadius:'var(--radius)', padding:'12px 16px', marginBottom:16, fontSize:13 } },
        h('div', { style: { fontWeight:700, marginBottom:6 } }, '⚠ خطأ في الوصول إلى جدول الطلبات المخبرية'),
        h('div', { style: { marginBottom:8, color:'var(--text-secondary)' } }, 'يبدو أن الـ RLS معطّل. شغّل هذا الكود في Supabase → SQL Editor:'),
        h('code', { style: { display:'block', background:'var(--bg-subtle)', padding:'8px 12px', borderRadius:6, fontFamily:'monospace', fontSize:12 } },
          'ALTER TABLE lab_orders DISABLE ROW LEVEL SECURITY;'
        ),
      ),
      // KPIs
      h('div', { className: 'grid cols-5', style: { marginBottom: 16 } },
        kpis.map(k => h('button', {
          key: k.key, className: 'card', style: { padding:'12px 16px', textAlign:'center', cursor:'pointer', outline: filterStatus===k.key ? '2px solid var(--accent)' : '' },
          onClick: () => setFilterStatus(k.key),
        },
          h('div', { style: { fontSize:20, fontWeight:900 } }, k.val),
          h('div', { style: { fontSize:11, color:'var(--text-tertiary)', marginTop:4 } }, k.label),
        )),
      ),
      // Search
      h('div', { style: { marginBottom: 14 } },
        h('input', { className: 'input', placeholder: 'ابحث بالمريض أو المختبر...', value: search, onInput: e => setSearch(e.target.value) }),
      ),
      // Table
      h('div', { className: 'card', style: { overflow:'hidden' } },
        loadingOrders
          ? h('div', { style: { padding:40, textAlign:'center', color:'var(--text-tertiary)' } }, 'جاري التحميل...')
          : filtered.length === 0
          ? h('div', { style: { padding:40, textAlign:'center', color:'var(--text-tertiary)' } }, dbError ? 'تعذّر التحميل' : 'لا توجد طلبات مخبرية')
          : h('table', { className: 'data-table' },
            h('thead', null, h('tr', null,
              ['المريض','المختبر','نوع الشغل','السن','اللون','الإرسال','الاستلام المتوقع','الحالة','إجراءات']
                .map(col => h('th', { key: col }, col)),
            )),
            h('tbody', null, filtered.map(o => {
              const st   = LAB_STATUSES[o.effectiveStatus] || LAB_STATUSES.pending;
              const late = o.effectiveStatus === 'late';
              return h('tr', { key: o.id, className: late ? 'lab-late-row' : '' },
                h('td', null, h('b', null, o.patient_name || '—')),
                h('td', null, o.lab_name),
                h('td', null, o.work_type),
                h('td', null, o.tooth_ref || '—'),
                h('td', null, o.color ? h('code', { style:{fontSize:11} }, o.color) : '—'),
                h('td', null, o.sent_date || '—'),
                h('td', null, h('span', { style:{color: late?'var(--danger)':'inherit', fontWeight: late?800:400} }, o.due_date||'—')),
                h('td', null, h('span', { className: 'chip ' + st.chip }, st.icon + ' ' + st.label)),
                h('td', null, h('div', { style:{display:'flex', gap:4} },
                  o.effectiveStatus === 'pending' && h('button', { className:'btn ghost sm', style:{fontSize:11}, onClick:()=>handleMarkSent(o) }, '📤 أرسل'),
                  o.effectiveStatus !== 'done'    && h('button', { className:'btn primary sm', style:{fontSize:11}, onClick:()=>handleReceive(o) }, '✅ استُلم'),
                  h('button', { className:'btn ghost sm', style:{fontSize:11}, onClick:()=>{ setEditOrder(o); setShowModal(true); } }, h(Icons.Edit, {size:12})),
                  h('button', { className:'btn ghost sm', style:{fontSize:11, color:'var(--danger)'}, onClick:()=>handleDelete(o) }, h(Icons.Trash, {size:12})),
                )),
              );
            })),
          ),
      ),
    ),
    showModal && h(LabOrderModal, { order:editOrder, patients:allPatients, onSave:handleSave, onClose:()=>{setShowModal(false);setEditOrder(null);}, saving }),
  );
}

function LabOrderModal({ order, patients, onSave, onClose, saving }) {
  const today3     = new Date(Date.now() + 3*86400000).toISOString().slice(0,10);
  const todayStr   = new Date().toISOString().slice(0,10);
  const [form, setForm] = useState({
    patient_id:'', patient_name:'', lab_name:'', work_type:LAB_WORK_TYPES[0],
    tooth_ref:'', color:'', sent_date:todayStr, due_date:today3, cost:'', notes:'', status:'pending',
    ...(order||{}),
  });
  const set = (k,v) => setForm(f => ({...f,[k]:v}));
  const handlePat = e => { const p=patients.find(x=>x.id===e.target.value)||{}; set('patient_id',e.target.value); if(p.name) set('patient_name',p.name); };
  const handleSubmit = e => { e.preventDefault(); if(!form.lab_name||!form.work_type||!form.due_date){alert('يرجى ملء الحقول المطلوبة');return;} onSave(form); };

  return h('div', { className:'modal-backdrop', onClick:onClose },
    h('div', { className:'modal-box modal-lg', onClick:e=>e.stopPropagation() },
      h('div', { className:'modal-header' },
        h('div', { className:'modal-title' }, order?'✏ تعديل طلب مخبري':'🔬 طلب مخبري جديد'),
        h('button', { className:'icon-btn', onClick:onClose }, h(Icons.X, {size:18})),
      ),
      h('form', { onSubmit:handleSubmit },
        h('div', { style:{padding:'20px 24px', display:'grid', gridTemplateColumns:'1fr 1fr', gap:14} },
          h('div', null, h('label', {className:'label'}, 'المريض'),
            h('select', {className:'input', value:form.patient_id, onChange:handlePat},
              h('option', {value:''}, '— اختر المريض —'),
              patients.map(p=>h('option',{key:p.id,value:p.id},p.name)),
            ),
          ),
          h('div', null, h('label', {className:'label'}, 'اسم المختبر *'),
            h('input', {className:'input', required:true, value:form.lab_name, onInput:e=>set('lab_name',e.target.value), placeholder:'مختبر النور...'}),
          ),
          h('div', null, h('label', {className:'label'}, 'نوع الشغل *'),
            h('select', {className:'input', value:form.work_type, onChange:e=>set('work_type',e.target.value)},
              LAB_WORK_TYPES.map(t=>h('option',{key:t,value:t},t)),
            ),
          ),
          h('div', null, h('label', {className:'label'}, 'السن / الفك'),
            h('input', {className:'input', value:form.tooth_ref, onInput:e=>set('tooth_ref',e.target.value), placeholder:'مثال: 21 أو الفك العلوي'}),
          ),
          h('div', null, h('label', {className:'label'}, 'لون البورسلين'),
            h('input', {className:'input', value:form.color, onInput:e=>set('color',e.target.value), placeholder:'A2, B1...'}),
          ),
          h('div', null, h('label', {className:'label'}, 'تكلفة المختبر (ج.م)'),
            h('input', {className:'input', type:'number', value:form.cost, onInput:e=>set('cost',e.target.value)}),
          ),
          h('div', null, h('label', {className:'label'}, 'تاريخ الإرسال'),
            h('input', {className:'input', type:'date', value:form.sent_date, onInput:e=>set('sent_date',e.target.value)}),
          ),
          h('div', null, h('label', {className:'label'}, 'موعد الاستلام المتوقع *'),
            h('input', {className:'input', type:'date', required:true, value:form.due_date, onInput:e=>set('due_date',e.target.value)}),
          ),
          h('div', {style:{gridColumn:'1/-1'}}, h('label', {className:'label'}, 'ملاحظات'),
            h('textarea', {className:'input', rows:2, value:form.notes, onInput:e=>set('notes',e.target.value), placeholder:'تعليمات خاصة، تشطيب، إلخ...'}),
          ),
        ),
        h('div', {className:'modal-footer'},
          h('button', {type:'button', className:'btn outline', onClick:onClose}, 'إلغاء'),
          h('button', {type:'submit', className:'btn primary', disabled:saving}, saving?'جاري الحفظ...':(order?'تحديث':'إضافة الطلب')),
        ),
      ),
    ),
  );
}

window.Screens = Object.assign(window.Screens || {}, {
  NewAppointment, Billing, Sessions, NewInvoice, Treatments, Inventory, Staff, Reports,
  Messages, Settings, Insurance, Accounting, Prescriptions, Xrays, PatientPortal,
  Pricing: PricingV3,
  WhatsAppReminders: WhatsAppRemindersV2,
  LabOrders,
});
