﻿/* global React, Icons, AppContext, DB, SB, InvoiceDetailModal, AddSessionModal */
const { useState, useRef, useEffect, useContext, useMemo, 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;
};

// ==================== Image Lightbox ====================
function ImageLightbox({ img, onClose }) {
  const sourceUrl = img?.dataUrl || img?.url || '';
  return h(Fragment, null,
    h('div', {
      onClick: onClose,
      style: { position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.88)', zIndex: 1000, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', cursor: 'zoom-out' },
    },
      h('div', { style: { position: 'absolute', top: 16, insetInlineEnd: 16, zIndex: 1001 } },
        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: sourceUrl ? 'transparent' : 'repeating-linear-gradient(45deg,#1a1a2e,#1a1a2e 12px,#2a2a3e 12px,#2a2a3e 24px)', width: 600, height: 450, borderRadius: 12, display: 'grid', placeItems: 'center', color: '#fff', position: 'relative', overflow: 'hidden' },
      },
        sourceUrl
          ? h('img', { src: sourceUrl, style: { width: '100%', height: '100%', objectFit: 'contain' } })
          : h('div', { style: { textAlign: 'center', 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: '16px 20px', background: 'rgba(0,0,0,0.5)', borderRadius: '0 0 12px 12px' } },
          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 (!downloadFromUrl(sourceUrl, `${String(img?.label || 'image').replace(/[\\/:*?"<>|]/g, '_')}.png`)) {
              window.print();
            }
          },
        }, h(Icons.Download, { size: 14 }), 'تحميل'),
      ),
    ),
  );
}

const DEFAULT_PATIENT_DOCUMENTS = [
  { id: 'seed-consent', name: 'نموذج الموافقة.pdf', sizeLabel: '245 KB', kind: 'PDF', date: '2026-04-10' },
  { id: 'seed-insurance', name: 'شهادة التأمين.pdf', sizeLabel: '180 KB', kind: 'PDF', date: '2026-03-28' },
  { id: 'seed-xray', name: 'أشعة بانوراما.jpg', sizeLabel: '2.4 MB', kind: 'IMAGE', date: '2026-02-20' },
];

const PATIENT_PROFILE_PREFIX = 'senan-patient-profile:';

function getPatientProfileKey(patientId) {
  return PATIENT_PROFILE_PREFIX + normalizePatientKey(patientId);
}

function readPatientProfile(patientId) {
  try {
    const raw = window.localStorage.getItem(getPatientProfileKey(patientId));
    return raw ? JSON.parse(raw) : {};
  } catch (error) {
    console.warn('[Senan] failed to read patient profile:', error);
    return {};
  }
}

function getPatientProfileSource(patient) {
  const legacyProfile = readPatientProfile(patient?.id);
  if (patient?.profileData && typeof patient.profileData === 'object') {
    return { ...legacyProfile, ...patient.profileData };
  }
  return legacyProfile;
}

function makeDocPreviewDataUrl(title, subtitle, tone = '#0891b2') {
  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="${tone}" stop-opacity="0.18"/>
          <stop offset="100%" stop-color="#0f172a" stop-opacity="0.9"/>
        </linearGradient>
      </defs>
      <rect width="1200" height="900" rx="40" fill="url(#g)"/>
      <rect x="140" y="120" width="920" height="660" rx="32" fill="#ffffff" fill-opacity="0.08" stroke="#ffffff" stroke-opacity="0.16"/>
      <text x="600" y="330" text-anchor="middle" fill="#ffffff" font-size="84" font-family="Arial" font-weight="700">${safeTitle}</text>
      <text x="600" y="420" text-anchor="middle" fill="#dbeafe" font-size="42" font-family="Arial">${safeSubtitle}</text>
      <text x="600" y="600" text-anchor="middle" fill="#e2e8f0" font-size="34" font-family="Arial">SENAN CLINIC</text>
    </svg>`;
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
}

function makeSeedDocument(doc, patient) {
  const kind = String(doc.kind || '').toUpperCase();
  const previewTone = kind === 'PDF' ? '#7c3aed' : '#0891b2';
  return {
    ...doc,
    patient: patient?.name || '',
    url: doc.url || makeDocPreviewDataUrl(doc.name.replace(/\.[^.]+$/, ''), `${doc.date || ''} · ${patient?.name || ''}`, previewTone),
  };
}

function normalizePatientKey(value) {
  return String(value || '').trim().toLowerCase();
}

function matchesPatientRecord(entry, patient) {
  if (!entry || !patient) return false;
  const patientId = normalizePatientKey(patient.id);
  const patientName = normalizePatientKey(patient.name);
  const entryPatientId = normalizePatientKey(entry.patientId || entry.patient_id);
  const entryPatientName = normalizePatientKey(entry.patient || entry.patientName || entry.name);
  return (patientId && entryPatientId && entryPatientId === patientId) || (patientName && entryPatientName && entryPatientName === patientName);
}

function parseAppointmentDateTime(appt) {
  if (!appt) return null;
  const datePart = String(appt.date || '').trim();
  if (!datePart) return null;
  const rawTime = String(appt.time || '').trim();
  const ampm = rawTime.match(/^(\d{1,2})(?::(\d{2}))?\s*([ap]m)$/i);
  let timePart = '00:00:00';
  if (ampm) {
    let hours = parseInt(ampm[1], 10);
    const minutes = (ampm[2] || '00').padStart(2, '0');
    const period = ampm[3].toLowerCase();
    if (period === 'pm' && hours !== 12) hours += 12;
    if (period === 'am' && hours === 12) hours = 0;
    timePart = `${String(hours).padStart(2, '0')}:${minutes}:00`;
  } else {
    const hm = rawTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?/);
    if (hm) timePart = `${hm[1].padStart(2, '0')}:${hm[2]}:${hm[3] || '00'}`;
  }
  const dt = new Date(`${datePart}T${timePart}`);
  return Number.isNaN(dt.getTime()) ? null : dt;
}

function formatFileSize(bytes) {
  const size = Number(bytes) || 0;
  if (size >= 1024 * 1024) return `${(size / 1024 / 1024).toFixed(size % (1024 * 1024) === 0 ? 0 : 1)} MB`;
  if (size >= 1024) return `${Math.round(size / 1024)} KB`;
  return `${size} B`;
}

function buildSeedDocuments(patient) {
  return DEFAULT_PATIENT_DOCUMENTS.map((doc, index) => makeSeedDocument({
    ...doc,
    id: `${doc.id}-${patient?.id || index}`,
  }, patient));
}

function loadStoredPatientDocuments(patient) {
  const profile = getPatientProfileSource(patient);
  if (Object.prototype.hasOwnProperty.call(profile, 'documents')) return Array.isArray(profile.documents) ? profile.documents : [];
  return [];
}

function buildDefaultMedicalRecord(patient, latestDoctorName) {
  return {
    phone: patient?.phone || '',
    location: patient?.location || '',
    age: patient?.age || '',
    gender: patient?.gender || '',
    doctor: latestDoctorName || patient?.doctor || '',
    bloodType: 'O+',
    bloodPressure: 'طبيعي',
    condition: 'مستقرة',
    smoking: 'لا',
    pregnancy: patient?.gender === 'أنثى' ? 'لا' : '—',
    allergy: (patient?.notes || '').includes('حساسية') ? 'البنسلين' : 'لا يوجد',
    notes: patient?.notes || '',
  };
}

function loadStoredMedicalRecord(patient, latestDoctorName) {
  const profile = getPatientProfileSource(patient);
  return { ...buildDefaultMedicalRecord(patient, latestDoctorName), ...(profile.medicalRecord || {}) };
}

function loadStoredPatientNotes(patient) {
  const profile = getPatientProfileSource(patient);
  if (Object.prototype.hasOwnProperty.call(profile, 'notes')) return Array.isArray(profile.notes) ? profile.notes : [];
  return [];
}

function loadStoredToothChart(patient) {
  const profile = getPatientProfileSource(patient);
  return {
    states: profile.dentalChart?.states || { ...window.TOOTH_STATES },
    notes: profile.dentalChart?.notes || {},
    selectedTooth: profile.dentalChart?.selectedTooth || null,
  };
}

function loadStoredXrays(patient) {
  const profile = getPatientProfileSource(patient);
  if (Object.prototype.hasOwnProperty.call(profile, 'xrays')) return Array.isArray(profile.xrays) ? profile.xrays : [];
  return [];
}

async function fileToDataUrl(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 fileToDataUrl(file);
  return file.type.startsWith('image/') ? compressImageDataUrl(dataUrl) : dataUrl;
}

function downloadFromUrl(url, filename) {
  if (!url) return false;
  const link = document.createElement('a');
  link.href = url;
  link.download = filename || 'download';
  link.rel = 'noopener';
  document.body.appendChild(link);
  link.click();
  link.remove();
  return true;
}

async function buildStoredAssetEntry(patient, file, category, extra = {}) {
  let uploadedAsset = null;
  try {
    uploadedAsset = await DB.uploadPatientAsset(patient?.clinic_id, patient?.id, file, category);
  } catch (error) {
    console.warn(`[Senan] storage upload fallback for ${category}:`, error);
  }

  const fallbackDataUrl = uploadedAsset?.url ? '' : await fileToStoredDataUrl(file);
  return {
    ...extra,
    id: extra.id || `${category}-${Date.now()}`,
    name: file.name,
    bucket: uploadedAsset?.bucket || '',
    storagePath: uploadedAsset?.path || '',
    url: uploadedAsset?.url || fallbackDataUrl,
    dataUrl: fallbackDataUrl,
  };
}

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

function getRecordDateTime(date, time) {
  if (!date) return null;
  const dt = parseAppointmentDateTime({ date, time });
  return dt && !Number.isNaN(dt.getTime()) ? dt : null;
}

function getLatestPatientDoctorName(patientInvoices, patientAppts, allDoctors) {
  const allDoctorsList = Array.isArray(allDoctors) ? allDoctors : [];
  const timeline = [];

  (patientInvoices || []).forEach(inv => {
    const doctorName = String(inv.doctorName || inv.doctor || '').trim();
    const invoiceDate = getRecordDateTime(inv.date, '23:59');
    if (doctorName) timeline.push({ dt: invoiceDate, doctorName });
  });

  (patientAppts || []).forEach(appt => {
    const doctorName = String(appt.doctor || '').trim();
    const apptDate = getRecordDateTime(appt.date, appt.time);
    if (doctorName) timeline.push({ dt: apptDate, doctorName });
  });

  timeline.sort((a, b) => {
    const aTime = a.dt ? a.dt.getTime() : -Infinity;
    const bTime = b.dt ? b.dt.getTime() : -Infinity;
    return bTime - aTime;
  });

  if (timeline.length) return timeline[0].doctorName;
  const fallbackDoctor = allDoctorsList[0]?.name || '';
  return fallbackDoctor;
}

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

function buildPatientSessions(patientInvoices, invoiceSessions = []) {
  const groupedSessions = new Map();

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

  const entries = [];

  (patientInvoices || []).forEach(inv => {
    const sessionsForInvoice = [...(groupedSessions.get(String(inv.id)) || [])].sort((a, b) => {
      const aDt = getRecordDateTime(a.date || inv.date, '23:59');
      const bDt = getRecordDateTime(b.date || inv.date, '23:59');
      if (aDt && bDt) return aDt - bDt;
      if (aDt) return -1;
      if (bDt) return 1;
      return String(a.created_at || '').localeCompare(String(b.created_at || ''));
    });
    const baseServices = (inv.items || []).map(it => it.name).filter(Boolean).join('، ');

    if (!sessionsForInvoice.length) return;

    let cumulativePaid = 0;
    sessionsForInvoice.forEach(session => {
      const sessionPaid = Number(session.paidAmount) || 0;
      cumulativePaid += sessionPaid;
      entries.push({
        id: session.id || `${inv.id}-${session.date || session.created_at || Date.now()}`,
        sessionId: session.id,
        dt: getRecordDateTime(session.date || inv.date, '23:59'),
        date: session.date || inv.date || '',
        invoiceId: formatInvoiceCode(inv.id),
        doctorName: String(session.doctor || inv.doctorName || inv.doctor || '').trim(),
        services: String(session.workDone || '').trim() || baseServices || 'خدمة غير محددة',
        total: Number(inv.total) || 0,
        paid: sessionPaid,
        invoicePaid: Number(inv.paid) || 0,
        remaining: Math.max(0, (Number(inv.total) || 0) - cumulativePaid),
        status: inv.status || 'unpaid',
        notes: session.notes || '',
        nextAppt: session.nextAppt || null,
        source: 'session',
      });
    });
  });

  return entries.sort((a, b) => {
    if (a.dt && b.dt) return b.dt - a.dt;
    if (a.dt) return -1;
    if (b.dt) return 1;
    return String(b.date || '').localeCompare(String(a.date || ''));
  });
}

function buildPrintablePatientSummary({ patient, patientInvoices, patientAppts, patientDocuments }) {
  const totalBilled = patientInvoices.reduce((s, i) => s + (Number(i.total) || 0), 0);
  const totalPaid = patientInvoices.reduce((s, i) => s + (Number(i.paid) || 0), 0);
  const upcomingAppts = [...patientAppts]
    .map(appt => ({ ...appt, _dt: parseAppointmentDateTime(appt) }))
    .sort((a, b) => {
      if (a._dt && b._dt) return a._dt - b._dt;
      if (a._dt) return -1;
      if (b._dt) return 1;
      return String(a.date || '').localeCompare(String(b.date || ''));
    });
  const docRows = patientDocuments.map(doc => `<tr><td>${printableText(doc.name)}</td><td>${printableText(doc.sizeLabel)}</td><td>${printableText(doc.date)}</td></tr>`).join('');
  const apptRows = upcomingAppts.slice(0, 5).map(appt => `<tr><td>${printableText(appt.date)}</td><td>${printableText(appt.time)}</td><td>${printableText(appt.type)}</td><td>${printableText(appt.doctor)}</td></tr>`).join('');
  return `
    <div style="font-family:Arial,Helvetica,sans-serif;direction:rtl;padding:28px;max-width:900px;margin:auto;color:#111827">
      <h1 style="margin:0 0 6px;font-size:24px">ملف المريض</h1>
      <div style="color:#6b7280;margin-bottom:22px">${printableText(patient?.name, '')}</div>
      <div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-bottom:20px">
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><strong>الهاتف:</strong> ${printableText(patient?.phone)}</div>
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><strong>المنطقة:</strong> ${printableText(patient?.location)}</div>
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><strong>الطبيب:</strong> ${printableText(patient?.doctor)}</div>
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><strong>البريد:</strong> ${printableText(patient?.email)}</div>
      </div>
      <div style="display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin-bottom:20px">
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><div style="font-size:12px;color:#6b7280">مفوتر</div><div style="font-size:18px;font-weight:700">${printableText(window.fmtEGP(totalBilled), '0')}</div></div>
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><div style="font-size:12px;color:#6b7280">مدفوع</div><div style="font-size:18px;font-weight:700">${printableText(window.fmtEGP(totalPaid), '0')}</div></div>
        <div style="padding:14px;border:1px solid #e5e7eb;border-radius:14px"><div style="font-size:12px;color:#6b7280">الرصيد</div><div style="font-size:18px;font-weight:700">${printableText(window.fmtEGP(patient?.balance || 0), '0')}</div></div>
      </div>
      <h2 style="font-size:18px;margin:24px 0 10px">المواعيد</h2>
      <table style="width:100%;border-collapse:collapse;margin-bottom:20px">
        <thead>
          <tr>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">التاريخ</th>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">الوقت</th>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">الإجراء</th>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">الطبيب</th>
          </tr>
        </thead>
        <tbody>${apptRows || `<tr><td colspan="4" style="padding:12px;color:#6b7280">لا توجد مواعيد مسجلة</td></tr>`}</tbody>
      </table>
      <h2 style="font-size:18px;margin:24px 0 10px">الوثائق</h2>
      <table style="width:100%;border-collapse:collapse">
        <thead>
          <tr>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">الاسم</th>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">الحجم</th>
            <th style="text-align:right;border-bottom:1px solid #e5e7eb;padding:10px">التاريخ</th>
          </tr>
        </thead>
        <tbody>${docRows || `<tr><td colspan="3" style="padding:12px;color:#6b7280">لا توجد وثائق</td></tr>`}</tbody>
      </table>
    </div>
  `;
}

function EditMedicalRecordModal({ patient, medicalRecord, latestDoctorName, onClose, onSaved }) {
  const { toast } = useContext(AppContext);
  const [saving, setSaving] = useState(false);
  const [form, setForm] = useState(() => ({
    ...medicalRecord,
    doctor: medicalRecord?.doctor || latestDoctorName || patient?.doctor || '',
  }));

  useEffect(() => {
    setForm({
      ...medicalRecord,
      doctor: medicalRecord?.doctor || latestDoctorName || patient?.doctor || '',
    });
  }, [medicalRecord, latestDoctorName, patient?.doctor]);

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

  const handleSave = async () => {
    setSaving(true);
    const nextRecord = {
      ...medicalRecord,
      ...form,
      doctor: latestDoctorName || form.doctor || patient?.doctor || '',
      notes: String(form.notes || '').trim(),
    };
    try {
      if (onSaved) await onSaved(nextRecord);
      toast('تم حفظ السجل الطبي ✅');
      onClose();
    } catch (error) {
      console.error(error);
      toast('حدث خطأ أثناء الحفظ');
    } finally {
      setSaving(false);
    }
  };

  return h(Fragment, null,
    h('div', { onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 500 } }),
    h('div', {
      onClick: e => e.stopPropagation(),
      style: {
        position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%,-50%)',
        background: 'var(--bg-elevated)', borderRadius: 'var(--radius-lg)', padding: 28,
        width: 620, zIndex: 501, boxShadow: 'var(--shadow-lg)', maxHeight: '90vh', overflowY: 'auto',
      },
    },
      h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18 } },
        h('div', null,
          h('div', { style: { fontWeight: 800, fontSize: 18 } }, 'تعديل السجل الطبي'),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 4 } }, patient?.name || '—'),
        ),
        h('button', { className: 'icon-btn', onClick: onClose }, h(Icons.X, { size: 18 })),
      ),
      h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 12 } },
        h('div', { style: { gridColumn: '1 / -1' } },
          h('div', { className: 'label' }, 'الطبيب المعالج'),
          h('input', { className: 'input', value: latestDoctorName || form.doctor || '—', readOnly: true }),
        ),
        h('div', null,
          h('div', { className: 'label' }, 'الحساسية'),
          h('input', { className: 'input', placeholder: 'مثال: البنسلين', value: form.allergy || '', onChange: e => set('allergy', e.target.value) }),
        ),
        h('div', null,
          h('div', { className: 'label' }, 'فصيلة الدم'),
          h('input', { className: 'input', placeholder: 'مثال: O+', value: form.bloodType || '', onChange: e => set('bloodType', e.target.value) }),
        ),
        h('div', null,
          h('div', { className: 'label' }, 'ضغط الدم'),
          h('input', { className: 'input', placeholder: 'مثال: طبيعي / مرتفع', value: form.bloodPressure || '', onChange: e => set('bloodPressure', e.target.value) }),
        ),
        h('div', null,
          h('div', { className: 'label' }, 'الحالة العامة'),
          h('input', { className: 'input', placeholder: 'مثال: مستقرة', value: form.condition || '', onChange: e => set('condition', e.target.value) }),
        ),
        h('div', null,
          h('div', { className: 'label' }, 'التدخين'),
          h('select', { className: 'select', value: form.smoking || 'لا', onChange: e => set('smoking', e.target.value) },
            ['لا', 'نعم', 'أقلع'].map(v => h('option', { key: v, value: v }, v)),
          ),
        ),
        h('div', null,
          h('div', { className: 'label' }, 'الحمل'),
          h('select', { className: 'select', value: form.pregnancy || '—', onChange: e => set('pregnancy', e.target.value) },
            ['—', 'لا', 'نعم', 'غير معلوم'].map(v => h('option', { key: v, value: v }, v)),
          ),
        ),
        h('div', { style: { gridColumn: '1 / -1' } },
          h('div', { className: 'label' }, 'ملاحظات'),
          h('textarea', { className: 'textarea', rows: 3, placeholder: 'أي ملاحظات طبية تظهر في السجل...', value: form.notes || '', onChange: e => set('notes', e.target.value) }),
        ),
      ),
      h('div', { style: { display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 20 } },
        h('button', { className: 'btn outline', onClick: onClose }, 'إلغاء'),
        h('button', { className: 'btn primary', disabled: saving, onClick: handleSave }, saving ? 'جاري الحفظ...' : 'حفظ السجل الطبي'),
      ),
    ),
  );
}

// ==================== New Prescription Modal ====================
function NewRxModal({ patient, onClose, onSaved }) {
  const { toast, clinicId, setPrescriptions } = useContext(AppContext);
  const today = new Date().toISOString().split('T')[0];
  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 updateMed = (i, k, v) => setMeds(m => m.map((med, j) => j === i ? { ...med, [k]: v } : med));

  const handlePrint = () => {
    const medsHtml = 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('');
    const content = `
      <div style="font-family:Arial;direction:rtl;padding:24px;max-width:600px;margin:auto">
        <h2 style="text-align:center;margin-bottom:4px">وصفة طبية</h2>
        <p style="text-align:center;color:#666;font-size:13px">التاريخ: ${printableText(today, '')}</p>
        <hr/>
        <p><strong>المريض:</strong> ${printableText(patient?.name, '')}</p>
        <hr/>
        <h3>الأدوية:</h3>
        ${medsHtml}
        ${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: content, features: 'width=760,height=840' })) {
      toast('تعذر فتح نافذة الطباعة');
    }
  };

  const handleSave = async () => {
    if (!meds[0].name.trim()) { toast('أضف دواء واحداً على الأقل'); return; }
    try {
      const rx = await DB.addPrescription(clinicId, {
        patientId: patient?.id || null,
        date: today,
        notes,
      }, meds);
      setPrescriptions(prev => [rx, ...(prev || [])]);
      toast('تم حفظ الوصفة ✅');
      if (onSaved) onSaved(rx);
      onClose();
    } catch (error) {
      console.error(error);
      toast('تعذر حفظ الوصفة');
    }
  };

  return h(Fragment, null,
    h('div', { onClick: onClose, style: { position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 500 } }),
    h('div', { onClick: e => e.stopPropagation(), style: { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', background: 'var(--bg-elevated)', borderRadius: 'var(--radius-lg)', padding: 28, width: 520, zIndex: 501, boxShadow: 'var(--shadow-lg)', 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 })),
      ),
      patient && h('div', { style: { padding: '8px 12px', background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', marginBottom: 16, fontSize: 13, fontWeight: 600 } }, '👤 ' + patient.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, position: 'relative' } },
          h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr auto', gap: 8 } },
            h('input', { className: 'input', placeholder: 'اسم الدواء', value: m.name, onChange: e => updateMed(i, 'name', e.target.value) }),
            h('input', { className: 'input', placeholder: 'الجرعة (مثل: 500mg)', value: m.dose, onChange: e => updateMed(i, 'dose', e.target.value) }),
            h('select', { className: 'input', value: m.duration, onChange: e => updateMed(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', onClick: () => removeMed(i), style: { color: 'var(--danger)' } }, 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 }), 'حفظ الوصفة'),
      ),
    ),
  );
}

// ==================== Patient File ====================
function PatientFile() {
  const { screenParams, setScreen, toast, clinicId, user, patients, setPatients, invoices, appointments, doctors, prescriptions } = useContext(AppContext);
  const docsInputRef = useRef(null);

  // Get real data with fallback to window globals
  const allPatients = (patients && patients.length) ? patients : (window.PATIENTS || []);
  const allInvoices = (invoices && invoices.length) ? invoices : (window.INVOICES || []);
  const allAppts    = (appointments && appointments.length) ? appointments : (window.APPOINTMENTS || []);
  const allDoctors   = (doctors && doctors.length) ? doctors : (window.DOCTORS || []);
  const allPrescriptions = Array.isArray(prescriptions) ? prescriptions : [];

  const patientId = screenParams?.patientId;
  const patient = allPatients.find(p => p.id === patientId) || allPatients[0];
  const [tab, setTab] = useState('overview');
  const [showEdit, setShowEdit] = useState(false);
  const [showMedicalEdit, setShowMedicalEdit] = useState(false);
  const [patientSessions, setPatientSessions] = useState([]);
  const [sessionsLoading, setSessionsLoading] = useState(false);

  if (!patient) return h('div', { className: 'page-content', style: { padding: 40, textAlign: 'center' } },
    h('div', { style: { color: 'var(--text-tertiary)' } }, 'لم يتم العثور على المريض'),
    h('button', { className: 'btn primary mt-16', onClick: () => setScreen('patients') }, 'العودة للمرضى'),
  );

  const patientInvoices = allInvoices.filter(inv => matchesPatientRecord(inv, patient));
  const patientAppts    = allAppts.filter(appt => matchesPatientRecord(appt, patient));
  const invoiceIdsKey = patientInvoices.map(inv => String(inv.id)).join('|');
  const latestDoctorName = getLatestPatientDoctorName(patientInvoices, patientAppts, allDoctors);
  const latestSessionDoctorName = patientSessions.find(session => session.doctorName)?.doctorName || '';
  const effectiveDoctorName = latestSessionDoctorName || latestDoctorName;
  const medicalRecord = loadStoredMedicalRecord(patient, effectiveDoctorName);
  const patientDocuments = loadStoredPatientDocuments(patient);
  const patientChart = loadStoredToothChart(patient);
  const patientXrays = loadStoredXrays(patient);
  const patientNotes = loadStoredPatientNotes(patient);
  const patientRx = allPrescriptions.filter(r => (
    normalizePatientKey(r.patientId || '') === normalizePatientKey(patient.id) ||
    normalizePatientKey(r.patient || '') === normalizePatientKey(patient.name)
  ));

  const persistPatientProfile = async (profilePatch, summaryNotesOverride) => {
    const currentProfile = getPatientProfileSource(patient);
    const nextProfile = {
      medicalRecord: Object.prototype.hasOwnProperty.call(profilePatch || {}, 'medicalRecord') ? (profilePatch.medicalRecord || {}) : (currentProfile.medicalRecord || {}),
      notes: Object.prototype.hasOwnProperty.call(profilePatch || {}, 'notes') ? (Array.isArray(profilePatch.notes) ? profilePatch.notes : []) : (Array.isArray(currentProfile.notes) ? currentProfile.notes : []),
      dentalChart: Object.prototype.hasOwnProperty.call(profilePatch || {}, 'dentalChart') ? (profilePatch.dentalChart || {}) : (currentProfile.dentalChart || {}),
      xrays: Object.prototype.hasOwnProperty.call(profilePatch || {}, 'xrays') ? (Array.isArray(profilePatch.xrays) ? profilePatch.xrays : []) : (Array.isArray(currentProfile.xrays) ? currentProfile.xrays : []),
      documents: Object.prototype.hasOwnProperty.call(profilePatch || {}, 'documents') ? (Array.isArray(profilePatch.documents) ? profilePatch.documents : []) : (Array.isArray(currentProfile.documents) ? currentProfile.documents : []),
    };
    const summaryNotes = summaryNotesOverride !== undefined ? summaryNotesOverride : patient.notes;
    const updated = await DB.savePatientProfile(patient.id, patient.clinic_id, summaryNotes, nextProfile);
    setPatients(prev => (prev || []).map(p => (p.id === updated.id ? updated : p)));
    return updated;
  };

  useEffect(() => {
    let cancelled = false;
    const loadSessions = async () => {
      if (!patientInvoices.length) {
        setPatientSessions([]);
        setSessionsLoading(false);
        return;
      }
      setSessionsLoading(true);
      try {
        const sessionLists = await Promise.all(
          patientInvoices.map(inv => DB.getInvoiceSessions(inv.id).catch(() => []))
        );
        if (cancelled) return;
        setPatientSessions(buildPatientSessions(patientInvoices, sessionLists.flat()));
      } catch (error) {
        console.error('[Senan] failed to load patient sessions:', error);
        if (!cancelled) setPatientSessions(buildPatientSessions(patientInvoices, []));
      } finally {
        if (!cancelled) setSessionsLoading(false);
      }
    };

    loadSessions();
    return () => { cancelled = true; };
  }, [patient?.id, invoiceIdsKey]);

  const handleDocumentUpload = async (files) => {
    const incoming = Array.from(files || []);
    if (!incoming.length) return;
    try {
      const nextDocs = await Promise.all(incoming.map(async (file, index) => buildStoredAssetEntry(patient, file, 'documents', {
        id: `doc-${Date.now()}-${index}`,
        name: file.name,
        sizeLabel: formatFileSize(file.size),
        kind: (file.name.split('.').pop() || '').toUpperCase() || (file.type.startsWith('image/') ? 'IMAGE' : 'FILE'),
        date: new Date().toISOString().split('T')[0],
      })));
      await persistPatientProfile({ documents: [...nextDocs, ...patientDocuments] });
      toast(`تم رفع ${nextDocs.length} وثيقة${nextDocs.length > 1 ? '' : ' واحدة'} ✅`);
    } catch (error) {
      console.error(error);
      toast('تعذر رفع الوثيقة');
    }
  };

  const handleRemoveDocument = async (docId) => {
    try {
      const targetDoc = patientDocuments.find(doc => doc.id === docId);
      if (targetDoc?.storagePath) {
        try {
          await DB.deletePatientAsset(targetDoc);
        } catch (error) {
          console.warn('[Senan] failed to delete storage document:', error);
        }
      }
      await persistPatientProfile({ documents: patientDocuments.filter(doc => doc.id !== docId) });
      toast('تم حذف الوثيقة');
    } catch (error) {
      console.error(error);
      toast('تعذر حذف الوثيقة');
    }
  };

  const handleMedicalRecordSave = async (record) => {
    await persistPatientProfile({ medicalRecord: record }, record?.notes || '');
    setShowMedicalEdit(false);
    setTab('overview');
  };

  const handleDentalChartSave = async (chart) => {
    await persistPatientProfile({ dentalChart: chart });
  };

  const handleXrayUpload = async (entry, file) => {
    const nextEntry = file
      ? await buildStoredAssetEntry(patient, file, 'xrays', { ...entry, id: `xray-${Date.now()}` })
      : { ...entry, id: `xray-${Date.now()}` };
    await persistPatientProfile({ xrays: [nextEntry, ...patientXrays] });
    return nextEntry;
  };

  const handleXrayDelete = async (xrayId) => {
    const targetXray = patientXrays.find(im => im.id === xrayId);
    if (targetXray?.storagePath) {
      try {
        await DB.deletePatientAsset(targetXray);
      } catch (error) {
        console.warn('[Senan] failed to delete storage xray:', error);
      }
    }
    await persistPatientProfile({ xrays: patientXrays.filter(im => im.id !== xrayId) });
  };

  const handleAddPatientNote = async (text) => {
    const cleanText = String(text || '').trim();
    if (!cleanText) return;
    const author = String(user?.user_metadata?.admin_name || user?.user_metadata?.full_name || user?.email || 'أنت').trim();
    const nextEntry = {
      id: `note-${Date.now()}`,
      text: cleanText,
      date: new Date().toISOString().split('T')[0],
      author: author || 'أنت',
    };
    await persistPatientProfile({ notes: [nextEntry, ...patientNotes] });
    return nextEntry;
  };

  const handlePrint = () => {
    if (!openPrintableWindow({
      title: `ملف المريض - ${patient?.name || ''}`,
      bodyHtml: buildPrintablePatientSummary({ patient, patientInvoices, patientAppts, patientDocuments }),
      features: 'width=980,height=820',
    })) {
      toast('تعذر فتح نافذة الطباعة');
    }
  };

  return h('div', { className: 'fade-in' },
    showEdit ? h(EditPatientModal, {
      patient,
      onClose: () => setShowEdit(false),
      onSaved: (updated) => { setPatients(prev => prev.map(p => p.id === updated.id ? updated : p)); setShowEdit(false); },
    }) : null,
    showMedicalEdit ? h(EditMedicalRecordModal, {
      patient,
      medicalRecord,
      latestDoctorName: effectiveDoctorName,
      onClose: () => setShowMedicalEdit(false),
      onSaved: handleMedicalRecordSave,
    }) : null,
    h('div', { className: 'page-header' },
      h('div', { className: 'flex gap-12 ai-c' },
        h('button', { className: 'icon-btn', onClick: () => setScreen('patients') },
          h(Icons.ChevronRight, { size: 18 }),
        ),
        h('div', { className: 'avatar lg' }, patient.avatar),
        h('div', null,
          h('div', { className: 'page-title', style: { display: 'flex', alignItems: 'center', gap: 8 } },
            patient.name,
            h('span', { className: 'chip success' }, 'نشط'),
          ),
          h('div', { className: 'page-subtitle' },
            `${patient.id} · ${patient.age} سنة · ${patient.gender} · ${patient.phone}`,
          ),
        ),
      ),
      h('div', { className: 'flex gap-8' },
        h('button', { className: 'btn outline', onClick: () => setShowEdit(true) }, h(Icons.Edit2, { size: 16 }), 'تعديل'),
        h('button', { className: 'btn outline', onClick: handlePrint }, h(Icons.Printer, { size: 16 }), 'طباعة'),
        h('button', { className: 'btn primary', onClick: () => setScreen('new-appointment', { patientId: patient.id, patientName: patient.name }) }, h(Icons.Plus, { size: 16 }), 'موعد جديد'),
      ),
    ),
    h('div', { className: 'page-content' },
      h('div', { className: 'tabs' },
        [
          { id: 'overview', label: 'نظرة عامة' },
          { id: 'invoices', label: 'الفواتير' },
          { id: 'sessions', label: 'الجلسات' },
          { id: 'appointments', label: 'المواعيد' },
          { id: 'chart', label: 'مخطط الأسنان' },
          { id: 'prescriptions', label: 'الوصفات' },
          { id: 'xrays', label: 'الأشعة' },
          { id: 'notes', label: 'الملاحظات' },
        ].map(t => h('button', {
          key: t.id,
          className: 'tab' + (tab === t.id ? ' active' : ''),
          onClick: () => setTab(t.id),
        }, t.label)),
      ),

      tab === 'overview' && h(PatientOverview, {
        patient,
        patientInvoices,
        patientAppts,
        patientDocuments,
        medicalRecord,
        latestDoctorName: effectiveDoctorName,
        patientSessions,
        sessionsLoading,
        onEditPatient: () => setShowEdit(true),
        onEditMedicalRecord: () => setShowMedicalEdit(true),
        onUploadDocuments: () => docsInputRef.current && docsInputRef.current.click(),
        onRemoveDocument: handleRemoveDocument,
      }),
      tab === 'invoices' && h(PatientInvoices, { invoices: patientInvoices }),
      tab === 'sessions' && h(PatientSessionsList, { sessions: patientSessions, loading: sessionsLoading }),
      tab === 'appointments' && h(PatientAppts, { appts: patientAppts }),
      tab === 'chart' && h(DentalChart, { patient, chart: patientChart, onSaveChart: handleDentalChartSave }),
      tab === 'prescriptions' && h(PatientRx, { rxs: patientRx, patient }),
      tab === 'xrays' && h(XrayGallery, { patient, xrays: patientXrays, onUploadXray: handleXrayUpload, onDeleteXray: handleXrayDelete }),
      tab === 'notes' && h(PatientNotes, { patient, notes: patientNotes, onAddNote: handleAddPatientNote }),
    ),
    h('input', {
      ref: docsInputRef,
      type: 'file',
      multiple: true,
      accept: '*/*',
      style: { display: 'none' },
      onChange: (e) => {
        handleDocumentUpload(e.target.files);
        e.target.value = '';
      },
    }),
  );
}

function PatientOverview({ patient, patientInvoices, patientAppts, patientDocuments, medicalRecord, latestDoctorName, patientSessions, sessionsLoading, onEditPatient, onEditMedicalRecord, onUploadDocuments, onRemoveDocument }) {
  const { setScreen, toast } = useContext(AppContext);
  const totalBilled = patientInvoices.reduce((s, i) => s + i.total, 0);
  const totalPaid = patientInvoices.reduce((s, i) => s + i.paid, 0);
  const record = medicalRecord || buildDefaultMedicalRecord(patient, latestDoctorName);
  const patientApptCards = useMemo(() => {
    const now = new Date();
    const sorted = [...patientAppts]
      .map(appt => ({ ...appt, _dt: parseAppointmentDateTime(appt) }))
      .sort((a, b) => {
        const aTime = a._dt ? a._dt.getTime() : Number.POSITIVE_INFINITY;
        const bTime = b._dt ? b._dt.getTime() : Number.POSITIVE_INFINITY;
        return aTime - bTime;
      });
    const upcoming = sorted.filter(appt => appt._dt && appt._dt >= now);
    return upcoming.length ? upcoming : sorted;
  }, [patientAppts]);
  return h('div', { style: { display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 20 } },
    h('div', { style: { display: 'flex', flexDirection: 'column', gap: 16 } },
      h('div', { className: 'card p-20' },
        h('div', { className: 'mb-16', style: { fontWeight: 800, fontSize: 15 } }, 'معلومات الاتصال'),
        h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(5, minmax(0, 1fr))', gap: 12 } },
          [
            { label: 'رقم الهاتف', value: record.phone || patient.phone, icon: Icons.Phone, ltr: true },
            { label: 'المنطقة', value: record.location || patient.location, icon: Icons.MapPin },
            { label: 'السن', value: record.age || patient.age, icon: Icons.User },
            { label: 'النوع', value: record.gender || patient.gender, icon: Icons.Users },
            { label: 'الطبيب المعالج', value: record.doctor || latestDoctorName || patient.doctor || '—', icon: Icons.Stethoscope },
          ].map((f, i) => h('div', { key: i, style: { padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)' } },
            h('div', { style: { display: 'flex', gap: 10, alignItems: 'center' } },
              h('div', { style: { width: 36, height: 36, borderRadius: 10, background: 'var(--bg-elevated)', display: 'grid', placeItems: 'center', color: 'var(--accent)' } }, h(f.icon, { size: 16 })),
              h('div', null,
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, f.label),
                h('div', { style: { fontSize: 14, fontWeight: 700, direction: f.ltr ? 'ltr' : 'rtl', textAlign: 'right' } }, f.value || '—'),
              ),
            ),
          ))),
        h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 12, marginTop: 12 } },
          [
            { label: 'البريد الإلكتروني', value: patient.email, icon: Icons.Mail },
            { label: 'شركة التأمين', value: patient.insurance, icon: Icons.Shield },
          ].map((f, i) => h('div', { key: i, style: { padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)' } },
            h('div', { style: { display: 'flex', gap: 10, alignItems: 'center' } },
              h('div', { style: { width: 36, height: 36, borderRadius: 10, background: 'var(--bg-elevated)', display: 'grid', placeItems: 'center', color: 'var(--accent)' } }, h(f.icon, { size: 16 })),
              h('div', null,
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, f.label),
                h('div', { style: { fontSize: 14, fontWeight: 700, direction: 'rtl', textAlign: 'right' } }, f.value || '—'),
              ),
            ),
          )),
        ),
      ),
      h('div', { className: 'card p-20' },
        h('div', { className: 'flex jc-sb ai-c mb-16' },
          h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'السجل الطبي'),
          h('button', { className: 'btn ghost sm', onClick: onEditMedicalRecord || onEditPatient }, h(Icons.Edit, { size: 14 }), 'تعديل'),
        ),
        h('div', { className: 'grid cols-3', style: { gap: 12 } },
          [
            { label: 'الحساسية', value: record.allergy || 'لا يوجد', color: (String(record.allergy || '').includes('لا يوجد') ? 'var(--success)' : 'var(--danger)') },
            { label: 'ضغط الدم', value: record.bloodPressure || 'طبيعي', color: String(record.bloodPressure || '').includes('مرتفع') ? 'var(--warning)' : 'var(--success)' },
            { label: 'فصيلة الدم', value: record.bloodType || 'O+', color: 'var(--text-primary)' },
            { label: 'الحالة العامة', value: record.condition || 'مستقرة', color: 'var(--success)' },
            { label: 'التدخين', value: record.smoking || 'لا', color: 'var(--success)' },
            { label: 'الحمل', value: record.pregnancy || (patient.gender === 'أنثى' ? 'لا' : '—'), color: 'var(--text-tertiary)' },
          ].map((f, i) => h('div', { key: i, style: { padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)' } },
            h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', fontWeight: 600 } }, f.label),
            h('div', { style: { fontSize: 14, fontWeight: 800, color: f.color, marginTop: 4 } }, f.value),
          )),
        ),
        record.notes ? h('div', { style: { marginTop: 16, padding: 12, background: 'var(--warning-soft)', borderRadius: 'var(--radius)', color: 'var(--warning)', fontSize: 13, fontWeight: 600 } },
          h(Icons.AlertTriangle, { size: 14, style: { display: 'inline-block', verticalAlign: 'text-bottom', marginLeft: 6 } }),
          record.notes,
        ) : null,
      ),
      h('div', { className: 'card p-20' },
        h('div', { className: 'flex jc-sb ai-c mb-16' },
          h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'آخر الأنشطة'),
          h('button', { className: 'btn ghost sm' }, 'عرض الكل'),
        ),
        h('div', { className: 'timeline' },
          [
            { time: 'اليوم 10:24', title: 'تم تحديث خطة العلاج', desc: 'إضافة حشو عصب للضرس 36', icon: Icons.Edit },
            { time: 'أمس', title: 'تم إنشاء فاتورة', desc: 'INV-2026-0142 بقيمة 2,500 ج.م', icon: Icons.CreditCard },
            { time: 'منذ 3 أيام', title: 'زيارة مكتملة', desc: 'كشف وفحص دوري مع د. سارة', icon: Icons.Check },
            { time: 'منذ أسبوع', title: 'أشعة بانوراما', desc: 'تم رفع صورة أشعة جديدة', icon: Icons.Image },
          ].map((e, i) => h('div', { key: i, className: 'timeline-item' },
            h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginBottom: 2 } }, e.time),
            h('div', { style: { fontSize: 14, fontWeight: 700, marginBottom: 2 } }, e.title),
            h('div', { style: { fontSize: 12, color: 'var(--text-secondary)' } }, e.desc),
          )),
        ),
      ),
    ),
    h('div', { style: { display: 'flex', flexDirection: 'column', gap: 16 } },
      h('div', { className: 'card p-20' },
        h('div', { style: { fontWeight: 800, fontSize: 14, marginBottom: 14 } }, 'الملخص المالي'),
        h('div', { style: { padding: 14, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', marginBottom: 10 } },
          h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'الرصيد المستحق'),
          h('div', { style: { fontSize: 24, fontWeight: 800, color: 'var(--danger)', marginTop: 4 } }, window.fmtEGP(patient.balance)),
        ),
        h('div', { style: { display: 'flex', gap: 8 } },
          h('div', { style: { flex: 1, padding: 12, borderRadius: 'var(--radius)', border: '1px solid var(--border)' } },
            h('div', { style: { fontSize: 10, color: 'var(--text-tertiary)' } }, 'مفوتر'),
            h('div', { style: { fontWeight: 800, fontSize: 15, marginTop: 2 } }, window.fmtEGP(totalBilled)),
          ),
          h('div', { style: { flex: 1, padding: 12, borderRadius: 'var(--radius)', border: '1px solid var(--border)' } },
            h('div', { style: { fontSize: 10, color: 'var(--text-tertiary)' } }, 'مدفوع'),
            h('div', { style: { fontWeight: 800, fontSize: 15, color: 'var(--success)', marginTop: 2 } }, window.fmtEGP(totalPaid)),
          ),
        ),
        h('button', {
          className: 'btn primary w-full mt-16', style: { width: '100%' },
          onClick: () => setScreen('billing'),
        }, h(Icons.DollarSign, { size: 16 }), 'تسجيل دفعة'),
      ),
      h('div', { className: 'card p-20' },
        h('div', { className: 'flex jc-sb ai-c mb-14' },
          h('div', { style: { fontWeight: 800, fontSize: 14 } }, `الجلسات (${patientSessions.length})`),
          h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, sessionsLoading ? 'جاري التحميل...' : (patientSessions[0]?.date || 'لا توجد جلسات')),
        ),
        sessionsLoading ? h('div', { className: 'empty-state', style: { padding: 20 } },
          h('div', { style: { fontSize: 13 } }, 'جاري تحميل الجلسات...'),
        ) : patientSessions.length > 0 ? h('div', { style: { display: 'grid', gap: 10 } },
          patientSessions.slice(0, 3).map((session, index) => h('div', {
            key: session.id || index,
            style: {
              padding: 12,
              background: 'var(--bg-subtle)',
              borderRadius: 'var(--radius)',
              border: '1px solid var(--border)',
            },
          },
            h('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'center' } },
              h('div', null,
                h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, session.date || '—'),
                h('div', { style: { fontSize: 14, fontWeight: 800, marginTop: 2 } }, session.invoiceId),
                h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', marginTop: 4 } }, session.services || 'خدمة غير محددة'),
                session.nextAppt ? h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 } }, `الموعد القادم: ${session.nextAppt}`) : null,
              ),
              h('div', { style: { textAlign: 'left' } },
                h('div', { style: { fontSize: 12, fontWeight: 700 } }, session.doctorName || 'بدون طبيب'),
                h('span', { className: 'chip ' + (session.source === 'session' ? 'accent' : session.status === 'paid' ? 'success' : session.status === 'partial' ? 'warning' : 'danger') },
                  session.source === 'session' ? 'جلسة فعلية' : (session.status === 'paid' ? 'مدفوعة' : session.status === 'partial' ? 'جزئية' : 'غير مدفوعة')),
              ),
            ),
            h('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 12, marginTop: 8, fontSize: 12, color: 'var(--text-tertiary)' } },
              h('span', null, `الإجمالي: ${window.fmtEGP(session.total)}`),
              h('span', null, `المدفوع: ${window.fmtEGP(session.paid)}`),
              h('span', null, `المتبقي: ${window.fmtEGP(session.remaining)}`),
            ),
          )),
        ) : h('div', { className: 'empty-state', style: { padding: 20 } },
          h('div', { style: { fontSize: 13 } }, 'لا توجد جلسات مسجلة'),
        ),
      ),
      h('div', { className: 'card p-20' },
        h('div', { style: { fontWeight: 800, fontSize: 14, marginBottom: 14 } }, 'المواعيد القادمة'),
        patientApptCards.length > 0 ? h('div', { style: { display: 'grid', gap: 10 } },
          patientApptCards.slice(0, 3).map((appt, index) => {
            const apptDate = parseAppointmentDateTime(appt);
            const isUpcoming = apptDate ? apptDate >= new Date() : false;
            return h('div', {
              key: appt.id || `${appt.date}-${appt.time}-${index}`,
              style: {
                padding: 14,
                background: isUpcoming ? 'var(--accent-soft)' : 'var(--bg-subtle)',
                borderRadius: 'var(--radius)',
                color: isUpcoming ? 'var(--accent-text)' : 'var(--text-primary)',
              },
            },
              h('div', { style: { display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'center' } },
                h('div', null,
                  h('div', { style: { fontSize: 11, fontWeight: 600, opacity: 0.8 } }, isUpcoming ? 'القادم' : 'زيارة مسجلة'),
                  h('div', { style: { fontSize: 16, fontWeight: 800, marginTop: 4 } }, `${appt.date || '—'}${appt.time ? ` · ${appt.time}` : ''}`),
                  h('div', { style: { fontSize: 12, marginTop: 6 } }, `${appt.type || 'موعد'}${appt.doctor ? ` · ${appt.doctor}` : ''}`),
                ),
                h('span', { className: 'chip ' + (isUpcoming ? 'accent' : 'success') }, appt.status || (isUpcoming ? 'قادم' : 'مكتمل')),
              ),
            );
          }),
        ) : h('div', { className: 'empty-state', style: { padding: 20 } },
          h('div', { style: { fontSize: 13 } }, 'لا مواعيد قادمة'),
        ),
      ),
      h('div', { className: 'card p-20' },
        h('div', { className: 'flex jc-sb ai-c mb-14' },
          h('div', { style: { fontWeight: 800, fontSize: 14 } }, 'الوثائق'),
          h('button', { className: 'btn outline sm', onClick: onUploadDocuments }, h(Icons.Upload, { size: 14 }), 'رفع'),
        ),
        patientDocuments.length > 0 ? h('div', { style: { display: 'flex', flexDirection: 'column', gap: 8 } },
          patientDocuments.map((doc, i) => h('div', {
            key: doc.id || i,
            style: { padding: 10, border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' },
            onClick: () => {
              if (doc.url) {
                window.open(doc.url, '_blank');
              } else {
                toast('تم اختيار الوثيقة');
              }
            },
          },
            h('div', { style: { color: 'var(--accent)' } }, h(Icons.File, { size: 16 })),
            h('div', { style: { flex: 1, minWidth: 0, fontSize: 12 } },
              h('div', { style: { fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, doc.name),
              h('div', { style: { color: 'var(--text-tertiary)', fontSize: 10 } }, `${doc.sizeLabel || doc.size || ''}${doc.date ? ` · ${doc.date}` : ''}`),
            ),
            h('div', { style: { display: 'flex', gap: 6 } },
              doc.url ? h('button', {
                className: 'icon-btn',
                style: { width: 28, height: 28 },
                onClick: (e) => {
                  e.stopPropagation();
                  downloadFromUrl(doc.url, doc.name || 'document');
                },
                title: 'تحميل',
              }, h(Icons.Download, { size: 14 })) : null,
              h('button', {
                className: 'icon-btn',
                style: { width: 28, height: 28, color: 'var(--danger)' },
                onClick: (e) => { e.stopPropagation(); onRemoveDocument && onRemoveDocument(doc.id); },
                title: 'حذف',
              }, h(Icons.Trash, { size: 13 })),
            ),
          )),
        ) : h('div', { className: 'empty-state', style: { padding: 20 } },
          h('div', { style: { fontSize: 13 } }, 'لا توجد وثائق'),
        ),
      ),
    ),
  );
}

// ==================== Dental Chart ====================
function DentalChart({ patient, chart, onSaveChart }) {
  const { setScreen, toast } = useContext(AppContext);
  const initialChart = useMemo(() => chart || loadStoredToothChart(patient), [chart, patient?.id]);
  const [selectedTooth, setSelectedTooth] = useState(initialChart.selectedTooth);
  const [states, setStates] = useState(initialChart.states);
  const [tool, setTool] = useState('view'); // view | cavity | filled | crown | treated | missing
  const [toothNotes, setToothNotes] = useState(initialChart.notes);

  useEffect(() => {
    const nextChart = chart || loadStoredToothChart(patient);
    setSelectedTooth(nextChart.selectedTooth);
    setStates(nextChart.states);
    setToothNotes(nextChart.notes);
    setTool('view');
  }, [chart, patient?.id]);

  const legend = [
    { key: 'healthy', label: 'سليم', color: 'var(--bg-elevated)', border: 'var(--border-strong)' },
    { key: 'cavity', label: 'تسوس', color: 'var(--danger-soft)', border: 'var(--danger)' },
    { key: 'filled', label: 'حشو', color: 'var(--info-soft)', border: 'var(--info)' },
    { key: 'crown', label: 'تاج', color: 'var(--warning-soft)', border: 'var(--warning)' },
    { key: 'treated', label: 'علاج عصب', color: 'var(--success-soft)', border: 'var(--success)' },
    { key: 'missing', label: 'مفقود', color: 'var(--bg-subtle)', border: 'var(--text-muted)' },
  ];

  const toggleTooth = (num) => {
    if (tool === 'view') { setSelectedTooth(num); return; }
    setStates(prev => {
      const copy = { ...prev };
      if (copy[num] === tool) delete copy[num]; else copy[num] = tool;
      return copy;
    });
    setSelectedTooth(num);
  };

  const renderTooth = (num, isLower) => h('div', {
    key: num,
    className: 'tooth' + (isLower ? ' lower' : '') + (selectedTooth === num ? ' selected' : '') + (states[num] ? ' ' + states[num] : ''),
    onClick: () => toggleTooth(num),
    title: `سن رقم ${num}`,
  },
    h('div', { style: { fontSize: 16, lineHeight: 1 } }, toothEmoji(states[num])),
    h('span', null, num),
  );

  return h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 320px', gap: 20 } },
    h('div', { className: 'card p-20' },
      h('div', { className: 'flex jc-sb ai-c mb-16' },
        h('div', null,
          h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'مخطط الأسنان التفاعلي (FDI)'),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, 'اضغط على سن لتحديد حالته'),
        ),
        h('div', { className: 'flex gap-4' },
          legend.slice(1).map(l => h('button', {
            key: l.key,
            className: 'btn sm ' + (tool === l.key ? 'primary' : 'outline'),
            onClick: () => setTool(tool === l.key ? 'view' : l.key),
            style: { fontSize: 11 },
          }, l.label)),
        ),
      ),
      h('div', { style: { background: 'var(--bg-subtle)', padding: 16, borderRadius: 'var(--radius-lg)' } },
        h('div', { style: { textAlign: 'center', fontSize: 11, color: 'var(--text-tertiary)', fontWeight: 700, marginBottom: 8 } }, 'الفك العلوي'),
        h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(16, 1fr)', gap: 4 } },
          window.TOOTH_NUMBERS_UPPER.map(n => renderTooth(n, false)),
        ),
        h('div', { style: { height: 16 } }),
        h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(16, 1fr)', gap: 4 } },
          window.TOOTH_NUMBERS_LOWER.map(n => renderTooth(n, true)),
        ),
        h('div', { style: { textAlign: 'center', fontSize: 11, color: 'var(--text-tertiary)', fontWeight: 700, marginTop: 8 } }, 'الفك السفلي'),
      ),
      h('div', { className: 'flex gap-12 wrap mt-16' },
        legend.map(l => h('div', { key: l.key, className: 'flex ai-c gap-8' },
          h('div', { style: { width: 18, height: 18, borderRadius: 4, background: l.color, border: `2px solid ${l.border}` } }),
          h('span', { style: { fontSize: 12, color: 'var(--text-secondary)' } }, l.label),
        )),
      ),
    ),
    h('div', { className: 'card p-20' },
      h('div', { style: { fontWeight: 800, fontSize: 15, marginBottom: 14 } }, 'تفاصيل السن'),
      selectedTooth
        ? h(Fragment, null,
            h('div', { style: { textAlign: 'center', padding: '20px 0', borderBottom: '1px solid var(--border)', marginBottom: 16 } },
              h('div', { style: { fontSize: 48, lineHeight: 1 } }, toothEmoji(states[selectedTooth]) || '🦷'),
              h('div', { style: { fontSize: 32, fontWeight: 800, marginTop: 8 } }, selectedTooth),
              h('div', { style: { fontSize: 13, color: 'var(--text-tertiary)' } }, toothName(selectedTooth)),
              h('span', { className: 'chip accent mt-8', style: { marginTop: 10 } }, toothStateLabel(states[selectedTooth])),
            ),
            h('div', { className: 'label' }, 'ملاحظات'),
            h('textarea', {
              className: 'textarea', rows: 3, placeholder: 'أضف ملاحظة على هذا السن...',
              value: toothNotes[selectedTooth] || '',
              onChange: e => setToothNotes(prev => ({ ...prev, [selectedTooth]: e.target.value })),
            }),
            h('div', { style: { marginTop: 16 } },
              h('div', { className: 'label' }, 'التاريخ العلاجي'),
              h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius-sm)' } },
                selectedTooth === 16 ? 'فحص: 2026-04-10 — وُجد تسوس على السطح الإطباقي'
                : selectedTooth === 26 ? 'حشو كومبوزيت: 2026-03-15'
                : selectedTooth === 36 ? 'تاج زيركون: 2025-11-20'
                : 'لا يوجد سجل سابق',
              ),
            ),
            h('div', { style: { display: 'flex', gap: 8, marginTop: 16 } },
              h('button', {
                className: 'btn outline', style: { flex: 1 },
                onClick: async () => {
                  const nextChart = { states, notes: toothNotes, selectedTooth };
                  try {
                    if (onSaveChart) await onSaveChart(nextChart);
                    toast('تم حفظ المخطط ✅');
                  } catch (error) {
                    console.error(error);
                    toast('تعذر حفظ المخطط');
                  }
                },
              }, h(Icons.Check, { size: 14 }), 'حفظ'),
              h('button', {
                className: 'btn primary', style: { flex: 2 },
                onClick: () => setScreen('new-invoice', { patientId: patient?.id, patientName: patient?.name, toothNote: `سن ${selectedTooth}` }),
              }, h(Icons.Plus, { size: 16 }), 'إضافة إجراء / فاتورة'),
            ),
          )
        : h('div', { className: 'empty-state' },
            h('div', { className: 'empty-state-icon' }, h(Icons.Smile, { size: 24 })),
            h('div', { style: { fontSize: 13 } }, 'اضغط على سن لعرض تفاصيله'),
          ),
    ),
  );
}

function toothEmoji(state) {
  if (state === 'cavity') return '⚠';
  if (state === 'filled') return '▣';
  if (state === 'crown') return '♛';
  if (state === 'treated') return '✓';
  if (state === 'missing') return '✕';
  return '';
}
function toothStateLabel(state) {
  return { cavity: 'تسوس', filled: 'حشو', crown: 'تاج', treated: 'علاج عصب', missing: 'مفقود' }[state] || 'سليم';
}
function toothName(num) {
  const n = num % 10;
  if (n === 1) return 'قاطع أوسط';
  if (n === 2) return 'قاطع جانبي';
  if (n === 3) return 'ناب';
  if (n === 4 || n === 5) return 'ضاحك';
  return 'طاحن';
}

function TreatmentsList({ patient }) {
  const treatments = [
    { id: 'TR1', name: 'علاج شامل للفك السفلي', status: 'in-progress', progress: 60, totalCost: 8500, paid: 5000, startDate: '2026-02-15', items: 6 },
    { id: 'TR2', name: 'تبييض أسنان', status: 'completed', progress: 100, totalCost: 3000, paid: 3000, startDate: '2025-11-20', items: 3 },
  ];
  return h('div', { className: 'grid', style: { gap: 16 } },
    h('div', { className: 'flex jc-sb ai-c' },
      h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'خطط العلاج'),
      h('button', { className: 'btn primary' }, h(Icons.Plus, { size: 16 }), 'خطة جديدة'),
    ),
    treatments.map(t => h('div', { key: t.id, className: 'card p-20' },
      h('div', { className: 'flex jc-sb ai-c mb-12' },
        h('div', null,
          h('div', { style: { fontWeight: 800, fontSize: 16 } }, t.name),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, `بدأت: ${t.startDate} · ${t.items} إجراءات`),
        ),
        h('span', { className: 'chip ' + (t.status === 'completed' ? 'success' : 'info') }, t.status === 'completed' ? 'مكتملة' : 'جارية'),
      ),
      h('div', { className: 'flex jc-sb ai-c mb-8', style: { fontSize: 12, color: 'var(--text-secondary)' } },
        h('span', null, `التقدم ${t.progress}%`),
        h('span', null, `${window.fmtEGP(t.paid)} من ${window.fmtEGP(t.totalCost)}`),
      ),
      h('div', { className: 'progress' }, h('div', { className: 'progress-bar', style: { width: t.progress + '%' } })),
    )),
  );
}

function PatientAppts({ appts }) {
  const history = useMemo(() => {
    const now = new Date();
    return [...(appts || [])]
      .map(appt => ({ ...appt, _dt: parseAppointmentDateTime(appt) }))
      .sort((a, b) => {
        const aTime = a._dt ? a._dt.getTime() : Number.POSITIVE_INFINITY;
        const bTime = b._dt ? b._dt.getTime() : Number.POSITIVE_INFINITY;
        return bTime - aTime;
      })
      .map(appt => ({
        date: appt.date || '—',
        type: appt.type || 'موعد',
        doctor: appt.doctor || '—',
        status: appt.status || (appt._dt && appt._dt >= now ? 'scheduled' : 'completed'),
        duration: appt.duration || 0,
      }));
  }, [appts]);
  return h('div', { className: 'card', style: { overflow: 'hidden' } },
    h('table', { className: 'data-table' },
      h('thead', null, h('tr', null, ['التاريخ', 'الإجراء', 'الطبيب', 'المدة', 'الحالة', ''].map((t, i) => h('th', { key: i }, t)))),
      h('tbody', null,
        history.map((a, i) => h('tr', { key: i },
          h('td', { style: { fontWeight: 600 } }, a.date),
          h('td', null, a.type),
          h('td', null, a.doctor),
          h('td', null, a.duration + ' د'),
          h('td', null, h('span', { className: 'chip ' + (a.status === 'scheduled' ? 'accent' : 'success') }, a.status === 'scheduled' ? 'قادم' : 'مكتمل')),
          h('td', null, h('button', { className: 'btn ghost sm' }, 'عرض')),
        )),
      ),
    ),
  );
}

function PatientInvoices({ invoices }) {
  const { setInvoices } = useContext(AppContext);
  const [detailInv, setDetailInv] = useState(null);
  const statusColor = { paid:'success', partial:'warning', unpaid:'danger' };
  const statusLabel = { paid:'مدفوعة', partial:'جزئية', unpaid:'غير مدفوعة' };

  return h('div', null,
    /* فتح InvoiceDetailModal (مُعرَّف في other-screens.jsx — يُحمَّل بعد هذا الملف) */
    detailInv && typeof InvoiceDetailModal !== 'undefined' ?
      h(InvoiceDetailModal, {
        inv: detailInv,
        onClose: () => setDetailInv(null),
        onInvoiceUpdated: (upd) => {
          setDetailInv(upd);
          if (setInvoices) setInvoices(prev => (prev||[]).map(i => i.id === upd.id ? upd : i));
        },
      }) : null,

    invoices.length === 0 ?
      h('div', { className: 'card empty-state' },
        h('div', { className: 'empty-state-icon' }, h(Icons.FileText, { size: 24 })),
        h('div', null, 'لا توجد فواتير مسجلة لهذا المريض'),
      ) :
    h('div', { className: 'card', style: { overflow: 'hidden' } },
      h('table', { className: 'data-table' },
        h('thead', null, h('tr', null, ['رقم الفاتورة', 'التاريخ', 'الإجمالي', 'المدفوع', 'المتبقي', 'الحالة', ''].map((t, i) => h('th', { key: i }, t)))),
        h('tbody', null,
          invoices.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.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 ' + (statusColor[inv.status] || 'danger') }, statusLabel[inv.status] || '—')),
            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: 'btn ghost sm', onClick: e => e.stopPropagation() }, h(Icons.Printer, { size: 13 })),
              ),
            ),
          )),
        ),
      ),
    ),
  );
}

function PatientSessionsList({ sessions, loading }) {
  return h('div', null,
    loading ? h('div', { className: 'card empty-state' },
      h('div', { className: 'empty-state-icon' }, h(Icons.FileText, { size: 24 })),
      h('div', null, 'جاري تحميل الجلسات...'),
    ) :
    sessions.length === 0 ? h('div', { className: 'card empty-state' },
      h('div', { className: 'empty-state-icon' }, h(Icons.FileText, { size: 24 })),
      h('div', null, 'لا توجد جلسات مسجلة لهذا المريض'),
    ) :
    h('div', { className: 'card', style: { overflow: 'hidden' } },
      h('table', { className: 'data-table' },
        h('thead', null, h('tr', null, ['التاريخ', 'رقم الفاتورة', 'الطبيب', 'الخدمة / الشغل المنجز', 'إجمالي الفاتورة', 'مدفوع الجلسة', 'المتبقي', 'النوع'].map((t, i) => h('th', { key: i }, t)))),
        h('tbody', null,
          sessions.map(session => h('tr', { key: session.id },
            h('td', { style: { fontWeight: 700 } }, session.date || '—'),
            h('td', { style: { fontFamily: 'monospace', fontSize: 12, fontWeight: 700 } }, session.invoiceId),
            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 ' + (session.source === 'session' ? 'accent' : 'outline') }, session.source === 'session' ? 'جلسة فعلية' : 'من الفاتورة')),
          )),
        ),
      ),
    ),
  );
}

function PatientRx({ rxs, patient }) {
  const { toast } = useContext(AppContext);
  const [showNewRx, setShowNewRx] = useState(false);
  const [localRxs, setLocalRxs] = useState(rxs || []);

  useEffect(() => {
    setLocalRxs(rxs || []);
  }, [rxs]);

  const printRx = (r) => {
    const content = `<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: content, features: 'width=760,height=840' })) {
      toast('تعذر فتح نافذة الطباعة');
    }
  };

  return h('div', { className: 'grid', style: { gap: 16 } },
    showNewRx ? h(NewRxModal, { patient, onClose: () => setShowNewRx(false), onSaved: rx => setLocalRxs(p => [rx, ...p]) }) : null,
    h('div', { className: 'flex jc-sb ai-c' },
      h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'الوصفات الطبية'),
      h('button', { className: 'btn primary', onClick: () => setShowNewRx(true) }, h(Icons.Plus, { size: 16 }), 'وصفة جديدة'),
    ),
    localRxs.length > 0 ? localRxs.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 } }, r.id),
          h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)' } }, `${r.date} · ${r.doctor || '—'}`),
        ),
        h('div', { className: 'flex gap-8' },
          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 url = buildWhatsAppUrl(patient?.phone, `مرحبًا ${patient?.name || ''}، هذه وصفتي الطبية بتاريخ ${r.date}.`);
              if (!url) { toast('رقم الهاتف غير متاح'); return; }
              window.open(url, '_blank', 'noopener');
            },
          }, h(Icons.MessageCircle, { size: 14 }), 'واتساب'),
        ),
      ),
      r.meds.map((m, i) => h('div', { key: i, style: { padding: 12, background: 'var(--bg-subtle)', borderRadius: 'var(--radius)', marginBottom: 8 } },
        h('div', { style: { fontWeight: 700, fontSize: 14 } }, m.name),
        h('div', { style: { fontSize: 12, color: 'var(--text-secondary)', marginTop: 4 } },
          'الجرعة: ' + m.dose + ' · المدة: ' + m.duration,
        ),
      )),
    )) : h('div', { className: 'card empty-state' },
      h('div', { className: 'empty-state-icon' }, h(Icons.Pill, { size: 24 })),
      h('div', null, 'لا توجد وصفات مسجلة'),
      h('button', { className: 'btn primary mt-16', onClick: () => setShowNewRx(true) }, h(Icons.Plus, { size: 14 }), 'وصفة جديدة'),
    ),
  );
}

function XrayGallery({ patient, xrays, onUploadXray, onDeleteXray }) {
  const { toast } = useContext(AppContext);
  const fileRef = useRef(null);
  const [lightbox, setLightbox] = useState(null);
  const [imgs, setImgs] = useState(() => xrays || loadStoredXrays(patient));

  useEffect(() => {
    setImgs(xrays || loadStoredXrays(patient));
  }, [patient?.id, xrays]);

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

  const handleDelete = (id, e) => {
    e.stopPropagation();
    if (!confirm('حذف هذه الصورة؟')) return;
    Promise.resolve(onDeleteXray ? onDeleteXray(id) : null)
      .then(() => {
        setImgs(prev => prev.filter(im => im.id !== id));
        toast('تم الحذف');
      })
      .catch((error) => {
        console.error(error);
        toast('تعذر حذف الصورة');
      });
  };

  return h('div', null,
    lightbox ? h(ImageLightbox, { img: lightbox, onClose: () => setLightbox(null) }) : null,
    h('input', { ref: fileRef, type: 'file', accept: 'image/*,.pdf', style: { display: 'none' }, onChange: handleUpload }),
    h('div', { className: 'flex jc-sb ai-c mb-16' },
      h('div', null,
        h('div', { style: { fontWeight: 800, fontSize: 15 } }, 'الأشعة والصور'),
        h('div', { style: { fontSize: 12, color: 'var(--text-tertiary)', marginTop: 2 } }, imgs.length + ' صورة'),
      ),
      h('button', { className: 'btn primary', onClick: () => fileRef.current.click() }, h(Icons.Upload, { size: 16 }), 'رفع صورة'),
    ),
    imgs.length === 0 ? h('div', { className: 'card empty-state' },
      h('div', { className: 'empty-state-icon' }, h(Icons.Image, { size: 24 })),
      h('div', null, 'لا توجد أشعة مرفوعة'),
    ) :
    h('div', { className: 'grid cols-4', style: { gap: 16 } },
      imgs.map((im) => h('div', { key: im.id, className: 'card', style: { overflow: 'hidden', cursor: 'pointer', position: 'relative' } },
        (() => {
          const previewUrl = im.dataUrl || im.url || '';
          return h('div', {
          onClick: () => setLightbox(im),
          style: { aspectRatio: '4/3', background: previewUrl ? `url(${previewUrl}) center/cover` : 'repeating-linear-gradient(45deg,#2a2a3a,#2a2a3a 8px,#3a3a4a 8px,#3a3a4a 16px)', display: 'grid', placeItems: 'center', color: '#fff', position: 'relative' },
        },
          !previewUrl ? h('div', { style: { textAlign: 'center', opacity: 0.6 } },
            h(Icons.Image, { size: 32 }),
            h('div', { style: { fontFamily: 'monospace', fontSize: 10, marginTop: 8 } }, im.type.toUpperCase()),
          ) : null,
          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(Icons.Eye, { size: 28, style: { opacity: 0, transition: 'opacity 0.2s' } })),
          h('span', { className: 'chip', style: { position: 'absolute', top: 8, insetInlineEnd: 8, background: 'rgba(0,0,0,0.6)', color: '#fff', border: 'none', fontSize: 10 } }, im.type),
          h('button', {
            className: 'icon-btn',
            style: {
              position: 'absolute',
              top: 8,
              insetInlineStart: 8,
              width: 28,
              height: 28,
              color: 'var(--danger)',
              background: 'rgba(255,255,255,0.92)',
              zIndex: 2,
            },
            title: 'حذف',
            onClick: (e) => handleDelete(im.id, e),
          }, h(Icons.Trash, { size: 13 })),
        );
        })(),
          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: 11, color: 'var(--text-tertiary)', marginTop: 2 } }, im.date),
            ),
          h('div', { style: { display: 'flex', gap: 4 } },
            h('button', {
              className: 'icon-btn',
              style: { width: 28, height: 28 },
              onClick: (e) => {
                e.stopPropagation();
                downloadFromUrl(im.dataUrl || im.url || '', `${String(im.label || 'xray').replace(/[\\/:*?"<>|]/g, '_')}.png`);
              },
              title: 'تحميل',
            }, h(Icons.Download, { size: 13 })),
          ),
          ),
      )),
    ),
  );
}

function PatientNotes({ patient, notes: patientNotes, onAddNote }) {
  const { toast } = useContext(AppContext);
  const notes = Array.isArray(patientNotes) ? patientNotes : loadStoredPatientNotes(patient);
  const [newNote, setNewNote] = useState('');

  return h('div', null,
    h('div', { className: 'card p-20 mb-16' },
      h('div', { className: 'label' }, 'إضافة ملاحظة جديدة'),
      h('textarea', {
        className: 'textarea', rows: 3,
        value: newNote,
        placeholder: 'اكتب ملاحظة...',
        onChange: (e) => setNewNote(e.target.value),
      }),
      h('div', { className: 'flex jc-sb ai-c mt-8' },
        h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, 'مرئية لجميع الأطباء'),
        h('button', {
          className: 'btn primary sm',
          onClick: async () => {
            if (!newNote.trim()) return;
            try {
              if (onAddNote) await onAddNote(newNote);
              setNewNote('');
              toast('تم حفظ الملاحظة ✅');
            } catch (error) {
              console.error(error);
              toast('تعذر حفظ الملاحظة');
            }
          },
        }, 'إضافة'),
      ),
    ),
    h('div', { className: 'grid', style: { gap: 10 } },
      notes.map(n => h('div', { key: n.id, className: 'card p-16' },
        h('div', { className: 'flex jc-sb ai-c mb-8' },
          h('div', { style: { fontSize: 12, fontWeight: 700 } }, n.author),
          h('div', { style: { fontSize: 11, color: 'var(--text-tertiary)' } }, n.date),
        ),
        h('div', { style: { fontSize: 14, color: 'var(--text-secondary)', lineHeight: 1.7 } }, n.text),
      )),
    ),
  );
}

window.Screens = window.Screens || {};
window.Screens.PatientFile = PatientFile;
window.buildWhatsAppUrl = window.buildWhatsAppUrl || buildWhatsAppUrl;
window.downloadFromUrl = window.downloadFromUrl || downloadFromUrl;
window.Screens.DentalChartPage = function() {
  const { patients, setPatients, setScreen } = React.useContext(AppContext);
  const allPts = (patients && patients.length) ? patients : (window.PATIENTS || []);
  const [selId, setSel] = React.useState(allPts[0]?.id || null);
  const patient = allPts.find(p => p.id === selId) || allPts[0];
  const chart = patient ? loadStoredToothChart(patient) : null;

  const handleSaveChart = async (nextChart) => {
    if (!patient?.id) return null;
    const currentProfile = getPatientProfileSource(patient);
    const updated = await DB.savePatientProfile(patient.id, patient.clinic_id, patient.notes, {
      medicalRecord: currentProfile.medicalRecord || {},
      notes: Array.isArray(currentProfile.notes) ? currentProfile.notes : [],
      dentalChart: nextChart || {},
      xrays: Array.isArray(currentProfile.xrays) ? currentProfile.xrays : [],
      documents: Array.isArray(currentProfile.documents) ? currentProfile.documents : [],
    });
    setPatients(prev => (prev || []).map(p => (p.id === updated.id ? updated : p)));
    return updated;
  };

  return h('div', { className: 'fade-in' },
    h('div', { className: 'page-header' },
      h('div', null,
        h('div', { className: 'page-title' }, 'مخطط الأسنان التفاعلي'),
        h('div', { className: 'page-subtitle' }, patient ? patient.name : 'اختر مريض'),
      ),
      h('div', { className: 'flex gap-8' },
        h('select', {
          className: 'select',
          value: selId || '',
          onChange: e => setSel(e.target.value),
          style: { minWidth: 200 },
        }, allPts.map(p => h('option', { key: p.id, value: p.id }, p.name))),
      ),
    ),
    patient
      ? h('div', { className: 'page-content' }, h(DentalChart, { patient, chart, onSaveChart: handleSaveChart }))
      : h('div', { className: 'page-content', style: { textAlign: 'center', padding: 40, color: 'var(--text-tertiary)' } }, 'لا يوجد مرضى'),
  );
};

