import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useNavigate, useSearchParams } from 'react-router';
import { PlusIcon, ChevronRightIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { toast } from 'sonner';
import { api } from '../lib/api';
import type { ApiResponse } from '../lib/api';
import { useAuthStore } from '../stores/authStore';
import PersianDateInput from '../components/ui/PersianDateInput';
import PriceInput from '../components/ui/PriceInput';
import DigitInput from '../components/ui/DigitInput';
import SearchableSelect from '../components/ui/SearchableSelect';
import { WalletChargeLink } from '../components/AppointmentActions';
import { useDoctorBookingServices } from '../hooks/useDoctorBookingServices';
import { useResources } from '../hooks/useResources';
import { useResourceBookingServices } from '../hooks/useResourceBookingServices';
import { useClinicContext } from '../hooks/useClinicContext';
import ServiceSlotPicker from '../components/appointments/ServiceSlotPicker';
import SlotPicker, { type PickedSlot } from '../components/appointments/SlotPicker';
import { tehranWallClockToUnix, rialToToman, tomanToRial } from '../lib/utils';
import BackButton from '../components/ui/BackButton';
import { digitsOnly, todayIso, formatNumber } from '../lib/utils';
import Switch from '../components/ui/Switch';

/**
 * افزودن نوبت — صفحهٔ کامل (بازسازی `CreateTurn.jsx` طرح tauri). از همان endpointهای
 * موجود استفاده می‌کند: `POST /api/v1/my/appointment` (یا admin) + در صورت نیاز
 * `PATCH .../status`. هیچ endpoint جدیدی ساخته نشده است.
 */

interface Option { uuid: string; name?: string; full_name?: string }
interface PatientRow { uuid: string; user_name?: string; user_mobile?: string; user_national_code?: string }

const toEpoch = (isoDate: string, time: string) => tehranWallClockToUnix(isoDate, time);
const addMinutes = (time: string, min: number) => {
  const [h, m] = time.split(':').map(Number);
  const t = h * 60 + m + min;
  return `${String(Math.floor(t / 60) % 24).padStart(2, '0')}:${String(t % 60).padStart(2, '0')}`;
};

const label = { fontSize: 12.5, color: 'var(--text-3)', display: 'block' } as const;
const sectionTitle: React.CSSProperties = { fontSize: 18, fontWeight: 700, color: 'var(--text)', margin: '22px 0 14px' };

export default function AppointmentCreatePage() {
  const navigate = useNavigate();
  const [params] = useSearchParams();
  const qc = useQueryClient();
  const primaryRole = useAuthStore(s => s.primaryRole);
  const dbUuid = useAuthStore(s => s.dbUuid);
  const isDoctor = primaryRole === 'doctor';

  const today = todayIso();

  // ── پزشک
  // در محیط کلینیک، `dbUuid` شناسهٔ کلینیک است نه پزشک؛ uuid پزشک فقط از `doctorUuid`
  // می‌آید. بدون این، پزشکِ مهمانِ کلینیک uuid کلینیک را به‌عنوان پزشک می‌فرستاد.
  const ownDoctorUuid = useAuthStore(s => s.doctorUuid);
  const [doctorUuid, setDoctorUuid] = useState(
    isDoctor ? (ownDoctorUuid ?? dbUuid ?? '') : (params.get('doctor') ?? ''),
  );
  // hydrate شدنِ استور بعد از رندر اول، پزشک را خالی می‌گذاشت.
  useEffect(() => {
    if (isDoctor && !doctorUuid && ownDoctorUuid) setDoctorUuid(ownDoctorUuid);
  }, [isDoctor, doctorUuid, ownDoctorUuid]);
  const clinicDoctorsQuery = useQuery<ApiResponse<{ data: { uuid: string; name: string }[] }>>({
    queryKey: ['clinic-doctors', dbUuid],
    queryFn: () => api.get(`/api/v1/clinic/doctor-list/${dbUuid}`),
    enabled: !isDoctor && !!dbUuid,
  });
  const doctorOptions = (clinicDoctorsQuery.data?.data?.data ?? []).map(d => ({ value: d.uuid, label: d.name }));

  // ── هدفِ نوبت: خودِ پزشک، یا یکی از منابعِ تحت نظرش
  //
  // منبع تقویم مستقل دارد، پس انتخابش کلِ منطق زمان را عوض می‌کند: سرویس‌ها از خودِ
  // منبع می‌آیند و وقت آزاد از تقاطعِ تقویم همان منبع — نه از برنامهٔ هفتگیِ پزشک.
  // این تنها جایی است که این دو شاخه از هم جدا می‌شوند؛ باقی فرم مشترک است.
  const clinicUuid = useClinicContext();
  const { resources: bookableResources } = useResources({ active: '1' });
  const supervisedResources = useMemo(
    () => (doctorUuid ? bookableResources.filter(r => r.supervisor?.uuid === doctorUuid) : []),
    [bookableResources, doctorUuid],
  );
  const [resourceUuid, setResourceUuid] = useState('');
  // تعویض پزشک ⇒ منبعِ پزشک قبلی دیگر زیر نظرِ او نیست.
  useEffect(() => { setResourceUuid(''); }, [doctorUuid]);
  const activeResource = supervisedResources.find(r => r.uuid === resourceUuid) ?? null;
  const resourceMode = activeResource !== null;
  const { services: resourceServices } = useResourceBookingServices(activeResource?.uuid);

  // ── بیمار: جستجوی رکورد موجود یا ورود شخص جدید
  const [patientSearch, setPatientSearch] = useState('');
  const [picked, setPicked] = useState<PatientRow | null>(null);
  const [newPatient, setNewPatient] = useState(false); // فرم «مراجعه کننده جدید» فعال است؟
  const [name, setName] = useState('');
  const [mobile, setMobile] = useState('');
  const [nationalCode, setNationalCode] = useState('');
  const patientsQ = useQuery<ApiResponse<PatientRow[]>>({
    queryKey: ['create-patients', patientSearch],
    queryFn: () => api.get(`/api/v1/patients?search=${encodeURIComponent(patientSearch)}&limit=10`),
    enabled: patientSearch.trim().length >= 2,
  });
  const patients = useMemo(() => patientsQ.data?.data ?? [], [patientsQ.data]);

  // ورود از تب «نوبت‌ها»ی پروندهٔ بیمار: مراجعه‌کننده از قبل معلوم است، پس به‌جای
  // جستجو، خودِ پرونده خوانده و قفل می‌شود.
  const fromRecordUuid = params.get('record') ?? '';

  /**
   * «ثبت نوبت این جلسه» — بیمار می‌تواند چند دورهٔ باز داشته باشد، پس فرم باید بگوید
   * این نوبت به کدام جلسه می‌چسبد و همان را به سرور بفرستد. بدونش اتصال به حدسِ
   * سرویس سپرده می‌شود و سرویسِ اشتباه یک پروندهٔ موازی می‌سازد.
   */
  const targetSessionUuid = params.get('session') ?? '';
  const targetSessionQ = useQuery<ApiResponse<{
    uuid: string;
    session_number: number;
    total_sessions: number;
    case_uuid: string;
    service: { uuid: string; name: string };
    patient: { record_uuid: string; name: string | null };
  }>>({
    queryKey: ['create-appt-session', targetSessionUuid],
    queryFn: () => api.get(`/api/v1/treatment-session/${targetSessionUuid}`),
    enabled: !!targetSessionUuid,
  });
  const targetSession = targetSessionQ.data?.data;
  const recordQ = useQuery<ApiResponse<PatientRow & { user_name?: string }>>({
    queryKey: ['create-appt-record', fromRecordUuid],
    queryFn: () => api.get(`/api/v1/patient/${fromRecordUuid}`),
    enabled: !!fromRecordUuid,
  });
  useEffect(() => {
    const rec: any = (recordQ.data?.data as any)?.data ?? recordQ.data?.data;
    if (!rec) return;
    setPicked({
      uuid: rec.uuid,
      user_name: rec.user_name,
      user_mobile: rec.user_mobile,
      user_national_code: rec.user_national_code ?? rec.profile?.national_code,
    });
    setNationalCode(String(rec.user_national_code ?? rec.profile?.national_code ?? '').replace(/\D/g, '').slice(0, 10));
  }, [recordQ.data]);

  // ── مشخصات سرویس
  const [sectionUuid, setSectionUuid] = useState(''); // بخشِ در حال مرور (برای دیدن سرویس‌هایش)
  // سرویس‌های انتخاب‌شده — انباشته از چند بخش؛ هر کدام قابل حذف. نام را نگه می‌داریم تا در chip نشان دهیم.
  const [selectedServices, setSelectedServices] = useState<{ uuid: string; name: string }[]>([]);
  const [staffUuid, setStaffUuid] = useState('');
  const toggleServiceItem = (uuid: string, name: string) =>
    setSelectedServices(prev => prev.some(s => s.uuid === uuid)
      ? prev.filter(s => s.uuid !== uuid)
      : [...prev, { uuid, name }]);
  const removeService = (uuid: string) =>
    setSelectedServices(prev => prev.filter(s => s.uuid !== uuid));
  const sectionsQ = useQuery<ApiResponse<Option[]>>({ queryKey: ['service-sections'], queryFn: () => api.get('/api/v1/service-sections') });
  const itemsQ = useQuery<ApiResponse<Option[]>>({
    queryKey: ['service-items', sectionUuid],
    queryFn: () => api.get(`/api/v1/service-items/${sectionUuid}`),
    enabled: !!sectionUuid,
  });
  const staffQ = useQuery<ApiResponse<Option[]>>({ queryKey: ['staff-list'], queryFn: () => api.get('/api/v1/staff') });

  // ── روش نوبت‌دهی پزشک (سرویسی/اسلاتی)
  const { bookingMode, services } = useDoctorBookingServices(doctorUuid);
  // منبع همیشه سرویسی است: اسلات ثابتی ندارد که بشود رویش نشست.
  const serviceMode = resourceMode || bookingMode === 'service';
  const [servicePick, setServicePick] = useState<{ serviceUuids: string[]; durations: Record<string, number>; slot: { start: number; end: number } | null }>({ serviceUuids: [], durations: {}, slot: null });

  // ── زمان نوبت
  const [date, setDate] = useState(params.get('date') || today);
  // حالت اسلاتی: انتخاب از اسلات‌های واقعیِ برنامهٔ پزشک. ورود دستیِ ساعت فقط وقتی
  // باقی می‌ماند که پزشک برای آن روز اصلاً برنامه‌ای نداشته باشد (نوبت خارج از برنامه).
  const [slotPick, setSlotPick] = useState<PickedSlot | null>(null);
  const [manualTime, setManualTime] = useState(false);
  const [duration, setDuration] = useState(40);
  const [start, setStart] = useState('15:00');
  const [end, setEnd] = useState(addMinutes('15:00', 40));
  useEffect(() => { setEnd(addMinutes(start, duration)); }, [start, duration]);
  // تعویض پزشک/تاریخ ⇒ اسلات انتخاب‌شده دیگر معتبر نیست.
  useEffect(() => { setSlotPick(null); }, [doctorUuid, date]);

  // ── بیعانه / وضعیت / توضیحات
  const [depositRequired, setDepositRequired] = useState(false);
  const [depositToman, setDepositToman] = useState(0);
  const [note, setNote] = useState('');

  // ── هزینه ویزیت — الزامی بودن از تنظیمات «الزامی کردن هزینه ویزیت» (کاربر بدون
  // پروفایل doctor/clinic از این endpoint 403 می‌گیرد → فلگ false و فیلد اختیاری می‌ماند)
  const pricingQ = useQuery<{ data: { free_visit_price_rials: number; require_visit_price: boolean } }>({
    queryKey: ['insurance-pricing'],
    queryFn: () => api.get('/api/v1/insurance-pricing'),
  });
  const freeVisit = (pricingQ.data as any)?.data?.free_visit_price_rials ?? 0;
  const requireVisit = (pricingQ.data as any)?.data?.require_visit_price ?? false;
  // فیلد UI تومان است؛ API ریالی (visit_price_rials).
  const [visitPriceToman, setVisitPriceToman] = useState(0);
  const [visitPriceTouched, setVisitPriceTouched] = useState(false);
  useEffect(() => {
    if (!visitPriceTouched && freeVisit > 0) setVisitPriceToman(rialToToman(freeVisit));
  }, [freeVisit, visitPriceTouched]);

  const effectiveName = picked?.user_name || name.trim();
  const effectiveMobile = picked?.user_mobile || mobile.trim();
  const effectiveNationalCode = (picked?.user_national_code || nationalCode).replace(/\D/g, '');
  const timingValid = serviceMode
    ? (servicePick.serviceUuids.length > 0 && !!servicePick.slot)
    : (manualTime ? (!!start && !!end) : !!slotPick);
  const valid = !!doctorUuid && !!date && effectiveName.length >= 2 && effectiveMobile.length >= 10
    && effectiveNationalCode.length === 10 && timingValid && (!requireVisit || visitPriceToman > 0);

  const create = useMutation({
    mutationFn: async () => {
      // اندپوینت ادمین `resource_uuid` نمی‌شناسد؛ نوبتِ منبع همیشه از مسیر پنل می‌رود.
      const createEndpoint = primaryRole === 'admin' && !resourceMode
        ? '/api/v1/admin/appointment'
        : '/api/v1/my/appointment';
      const slotStart = serviceMode ? servicePick.slot!.start : (slotPick ? slotPick.start : toEpoch(date, start));
      const slotEnd   = serviceMode ? servicePick.slot!.end   : (slotPick ? slotPick.end   : toEpoch(date, end));

      const payload: Record<string, unknown> = {
        doctor_uuid: doctorUuid,
        slot_start: slotStart,
        slot_end: slotEnd,
        patient_name: effectiveName,
        patient_mobile: effectiveMobile,
        patient_national_code: effectiveNationalCode,
        // محل نوبت‌دهی: بدون `clinic_uuid` سرور نوبت را به مطب شخصیِ پزشک می‌نشاند —
        // و در حالت منبع، منبعِ کلینیک اصلاً «متعلق به این محیط» شناخته نمی‌شود (۴۲۲).
        ...(clinicUuid ? { clinic_uuid: clinicUuid } : {}),
        ...(resourceMode ? { resource_uuid: activeResource!.uuid } : {}),
        ...(targetSessionUuid ? { treatment_session_uuid: targetSessionUuid } : {}),
        ...(serviceMode
          ? { service_item_uuids: servicePick.serviceUuids, duration_from_services: true, service_durations: servicePick.durations }
          : {
              ...(sectionUuid ? { service_section_uuid: sectionUuid } : {}),
              ...(selectedServices.length ? { service_item_uuids: selectedServices.map(s => s.uuid) } : {}),
            }),
        // پرسنل فقط در حالت پزشک معنا دارد؛ در حالت منبع، خودِ منبع مجریِ نوبت است.
        ...(staffUuid && !resourceMode ? { staff_uuid: staffUuid } : {}),
        ...(depositRequired ? { deposit_required: true, deposit_amount_rials: tomanToRial(depositToman) } : {}),
        ...(visitPriceToman > 0 ? { visit_price_rials: tomanToRial(visitPriceToman) } : {}),
        ...(note.trim() ? { note: note.trim() } : {}),
      };
      // سرور نوبت را «ثبت‌شده» متولد می‌کند؛ این صفحه اما نوبتِ **قطعی** می‌سازد، پس
      // بلافاصله همان endpoint قطعی‌کردن صدا زده می‌شود (بدون پرداخت — پرداخت از
      // مودال «قطعی کردن» یا صفحهٔ پرداخت انجام می‌شود).
      const created: any = await api.post(createEndpoint, payload);
      const uuid = created?.data?.uuid ?? created?.data?.data?.uuid;
      if (!uuid) return created;

      try {
        await api.post(`/api/v1/appointment/${uuid}/confirm`, { payments: [] });
      } catch (e: any) {
        // نوبت ثبت شده و اسلات را گرفته؛ فقط قطعی نشده. کاربر باید بداند.
        toast.error(e?.message || 'نوبت ثبت شد ولی قطعی نشد؛ از لیست نوبت‌ها قطعی کنید');
      }

      return created;
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['appointments'] });
      toast.success('نوبت قطعی ثبت شد');
      // به همان روزِ نوبت برگرد، نه امروز.
      navigate(`/admin/appointments?date=${date}`);
    },
    onError: (e: any) => toast.error(e.message || 'خطا در ثبت نوبت'),
  });

  return (
    <div style={{ padding: '20px 24px', maxWidth: 1080, margin: '0 auto' }}>
      {/* بردکرامب */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 18 }}>
        <BackButton fallback="/admin/appointments" />
        <span style={{ fontSize: 13, color: 'var(--text-3)' }}>نوبت ها</span>
        <span style={{ color: 'var(--text-3)' }}>›</span>
        <span style={{ fontSize: 15, fontWeight: 700, color: 'var(--text)' }}>ثبت نوبت جدید</span>
      </div>

      {/* فرم باید صریح بگوید این نوبت برای کدام دوره است؛ بیمارِ چنددوره‌ای بدون این،
          اتصال را به حدسِ سرویس می‌سپارد. */}
      {targetSessionUuid !== '' && (
        <div style={{
          marginBottom: 16, padding: '12px 16px', borderRadius: 'var(--r-sm)',
          background: 'var(--primary-soft)', display: 'flex', gap: 14, flexWrap: 'wrap', fontSize: 13,
        }}>
          {targetSessionQ.isLoading ? (
            <span style={{ color: 'var(--text-3)' }}>در حال خواندن جلسهٔ درمان…</span>
          ) : targetSession ? (
            <>
              <span>
                <span style={{ color: 'var(--text-3)' }}>این نوبت برای: </span>
                <b>جلسهٔ {formatNumber(targetSession.session_number)} از {formatNumber(targetSession.total_sessions)}</b>
              </span>
              <span>
                <span style={{ color: 'var(--text-3)' }}>دوره: </span>
                <b>{targetSession.service.name}</b>
              </span>
              <span>
                <span style={{ color: 'var(--text-3)' }}>بیمار: </span>
                <b>{targetSession.patient.name || 'بدون نام'}</b>
              </span>
            </>
          ) : (
            <span style={{ color: 'var(--danger)' }}>
              جلسهٔ درمان یافت نشد — نوبت بدون اتصال به دوره ثبت می‌شود.
            </span>
          )}
        </div>
      )}

      <div style={{ background: 'var(--surface)', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', padding: 28 }}>
        {/* پزشک — فقط برای admin/clinic */}
        {!isDoctor && (
          <>
            <div style={{ ...sectionTitle, marginTop: 0 }}>پزشک:</div>
            <label style={label}>انتخاب پزشک</label>
            <div style={{ margin: '6px 0 4px', maxWidth: 400 }}>
              <SearchableSelect
                options={doctorOptions}
                value={doctorUuid || null}
                onChange={(v) => setDoctorUuid(v ? String(v) : '')}
                placeholder="انتخاب پزشک..."
                isClearable
                height={44}
              />
            </div>
          </>
        )}

        {/* هدف نوبت — فقط وقتی این پزشک منبعی زیر نظر دارد */}
        {supervisedResources.length > 0 && (
          <>
            <div style={{ ...sectionTitle, marginTop: isDoctor ? 0 : 18 }}>هدف نوبت:</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, margin: '6px 0 2px' }}>
              {[{ uuid: '', name: 'خودِ پزشک' }, ...supervisedResources.map(r => ({ uuid: r.uuid, name: r.name }))].map(t => {
                const active = resourceUuid === t.uuid;
                return (
                  <button key={t.uuid || 'doctor'} type="button" onClick={() => setResourceUuid(t.uuid)}
                    style={{
                      fontSize: 13, padding: '8px 14px', borderRadius: 'var(--r-pill)', cursor: 'pointer',
                      fontFamily: 'inherit', minHeight: 36,
                      border: active ? '1px solid var(--primary)' : '1px solid var(--border)',
                      background: active ? 'var(--primary)' : 'var(--surface)',
                      color: active ? 'var(--on-primary)' : 'var(--text)',
                    }}>
                    {t.name}
                  </button>
                );
              })}
            </div>
            <div style={{ fontSize: 12.5, color: 'var(--text-3)', marginTop: 6 }}>
              {resourceMode
                ? 'زمان‌ها از تقویم خودِ منبع می‌آیند و سرویس‌ها همان‌هایی‌اند که روی این منبع فعال‌اند.'
                : 'زمان‌ها از برنامهٔ هفتگی پزشک می‌آیند.'}
            </div>
          </>
        )}

        {/* مراجعه کننده */}
        <div style={{ ...sectionTitle, marginTop: isDoctor && supervisedResources.length === 0 ? 0 : 18 }}>اطلاعات مراجعه کننده :</div>

        {/* آمده از پروندهٔ بیمار: مراجعه‌کننده معلوم است، جستجو معنا ندارد. */}
        {fromRecordUuid ? (
          <div style={{ maxWidth: 400, border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', padding: 12, marginBottom: 8 }}>
            <div style={{ fontSize: 13.5, fontWeight: 600, marginBottom: 6 }}>
              {picked?.user_name ?? 'در حال بارگذاری پرونده...'}
              <span style={{ color: 'var(--text-3)', direction: 'ltr', fontWeight: 400 }}> {picked?.user_mobile ?? ''}</span>
            </div>
            {picked && !/^\d{10}$/.test(effectiveNationalCode) ? (
              <>
                <label style={label}>کد ملی (در پرونده ثبت نشده — وارد کنید)</label>
                <div className="field" style={{ marginTop: 6, height: 44 }}>
                  <DigitInput value={nationalCode} onChange={setNationalCode} maxDigits={10}
                    placeholder="کد ملی مراجعه کننده" />
                </div>
              </>
            ) : (
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 13 }}>
                <span style={{ color: 'var(--text-3)' }}>کد ملی</span>
                <span dir="ltr" style={{ fontWeight: 600 }}>{effectiveNationalCode}</span>
              </div>
            )}
          </div>
        ) : (
        <>
        {/* حالت جستجوی مراجعه‌کنندهٔ موجود */}
        {!newPatient && (
          <>
            <label style={label}>انتخاب مراجعه کننده</label>
            <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 12, margin: '6px 0 8px' }}>
              <div className="field" style={{ width: 400, maxWidth: '100%' }}>
                <MagnifyingGlassIcon style={{ width: 18, height: 18, color: 'var(--text-3)', flexShrink: 0 }} />
                <input value={picked ? `${picked.user_name ?? ''} — ${picked.user_mobile ?? ''}` : patientSearch}
                  onChange={e => { setPicked(null); setPatientSearch(e.target.value); }}
                  placeholder="جستجوی نام، شماره تماس، شماره پرونده..." />
              </div>
              <button type="button" className="btn outline"
                onClick={() => { setPicked(null); setPatientSearch(''); setNewPatient(true); }}
                style={{ height: 44, minWidth: 161, gap: 6 }}>
                <PlusIcon style={{ width: 16, height: 16 }} /> مراجعه کننده جدید
              </button>
            </div>
            {!picked && patients.length > 0 && (
              <div style={{ border: '1px solid var(--border)', borderRadius: 'var(--r-sm)', marginBottom: 10, overflow: 'hidden', maxWidth: 400 }}>
                {patients.map(p => (
                  <button key={p.uuid}
                    onClick={() => { setPicked(p); setNationalCode((p.user_national_code ?? '').replace(/\D/g, '').slice(0, 10)); }}
                    style={{
                      display: 'block', width: '100%', padding: '8px 10px', fontSize: 13, textAlign: 'right',
                      background: 'transparent', border: 'none', cursor: 'pointer', fontFamily: 'inherit',
                    }}>
                    {p.user_name} <span style={{ color: 'var(--text-3)', direction: 'ltr' }}>{p.user_mobile}</span>
                  </button>
                ))}
              </div>
            )}

            {/* کارت بیمارِ انتخاب‌شده + کد ملی (برای ثبت نوبت الزامی است) */}
            {picked && (
              <div style={{ maxWidth: 400, border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', padding: 12, marginBottom: 8 }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
                  <span style={{ fontSize: 13.5, fontWeight: 600 }}>
                    {picked.user_name} <span style={{ color: 'var(--text-3)', direction: 'ltr', fontWeight: 400 }}>{picked.user_mobile}</span>
                  </span>
                  <button type="button" className="btn sm ghost"
                    onClick={() => { setPicked(null); setNationalCode(''); }}>تغییر</button>
                </div>
                {/^\d{10}$/.test((picked.user_national_code ?? '').replace(/\D/g, '')) ? (
                  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 13 }}>
                    <span style={{ color: 'var(--text-3)' }}>کد ملی</span>
                    <span dir="ltr" style={{ fontWeight: 600 }}>{nationalCode}</span>
                  </div>
                ) : (
                  <>
                    <label style={label}>کد ملی (ثبت‌نشده — وارد کنید)</label>
                    <div className="field" style={{ marginTop: 6, height: 44 }}>
                      <DigitInput value={nationalCode} onChange={setNationalCode} maxDigits={10}
                        placeholder="کد ملی مراجعه کننده" />
                    </div>
                  </>
                )}
              </div>
            )}
          </>
        )}

        {/* حالت ثبت مراجعه‌کنندهٔ جدید */}
        {newPatient && (
          <>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', margin: '2px 0 6px' }}>
              <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-2)' }}>مراجعه کننده جدید</span>
              <button type="button" className="btn sm ghost"
                onClick={() => { setName(''); setMobile(''); setNationalCode(''); setNewPatient(false); }}>
                انتخاب از لیست موجود
              </button>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginTop: 4 }}>
              <div>
                <label style={label}>نام و نام خانوادگی مراجعه کننده</label>
                <div className="field" style={{ marginTop: 6, height: 44 }}>
                  <input value={name} onChange={e => setName(e.target.value)} placeholder="نام و نام خانوادگی مراجعه کننده" />
                </div>
              </div>
              <div>
                <label style={label}>شماره تماس</label>
                <div className="field" style={{ marginTop: 6, height: 44 }}>
                  <DigitInput value={mobile} onChange={setMobile} maxDigits={11} placeholder="شماره تماس مراجعه کننده" />
                </div>
              </div>
              <div>
                <label style={label}>کد ملی</label>
                <div className="field" style={{ marginTop: 6, height: 44 }}>
                  <DigitInput value={nationalCode} onChange={setNationalCode} maxDigits={10}
                    placeholder="کد ملی مراجعه کننده" />
                </div>
              </div>
            </div>
          </>
        )}
        </>
        )}

        {/* مشخصات سرویس — در حالت منبع، سرویس‌ها داخل انتخابگر زمانِ همان منبع انتخاب
            می‌شوند (فقط سرویس‌هایی که روی آن منبع فعال‌اند)، پس این بخش جا ندارد. */}
        {!resourceMode && <div style={sectionTitle}>مشخصات سرویس</div>}
        {resourceMode ? null : !serviceMode ? (
          <>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16, marginBottom: 10 }}>
              <div>
                <label style={label}>بخش</label>
                <div style={{ marginTop: 6 }}>
                  <SearchableSelect
                    inputId="appt-section-select"
                    options={(sectionsQ.data?.data ?? []).map(o => ({ value: o.uuid, label: o.name ?? '' }))}
                    value={sectionUuid || null}
                    onChange={v => setSectionUuid(v ? String(v) : '')}
                    placeholder="ابتدا بخش را انتخاب کنید"
                    isLoading={sectionsQ.isLoading}
                    isClearable
                    height={44}
                  />
                </div>
              </div>
              <div>
                <label style={label}>پرسنل</label>
                <div style={{ marginTop: 6 }}>
                  <SearchableSelect
                    options={(staffQ.data?.data ?? []).map(o => ({ value: o.uuid, label: o.full_name ?? '' }))}
                    value={staffUuid || null}
                    onChange={v => setStaffUuid(v ? String(v) : '')}
                    placeholder="انتخاب پرسنل"
                    isLoading={staffQ.isLoading}
                    isClearable
                    height={44}
                  />
                </div>
              </div>
            </div>

            {/* سرویس‌های بخشِ انتخاب‌شده — چند انتخابی، به لیست انباشته اضافه می‌شوند */}
            {sectionUuid && (
              <>
                <label style={label}>سرویس‌های این بخش (یک یا چند)</label>
                {itemsQ.isLoading ? (
                  <div style={{ fontSize: 12.5, color: 'var(--text-3)', margin: '6px 0 10px' }}>در حال بارگذاری...</div>
                ) : (itemsQ.data?.data ?? []).length === 0 ? (
                  <div style={{ fontSize: 12.5, color: 'var(--text-3)', margin: '6px 0 10px' }}>سرویسی در این بخش تعریف نشده است.</div>
                ) : (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 6, margin: '6px 0 12px' }}>
                    {(itemsQ.data?.data ?? []).map(o => {
                      const active = selectedServices.some(s => s.uuid === o.uuid);
                      return (
                        <button key={o.uuid} type="button" onClick={() => toggleServiceItem(o.uuid, o.name ?? '')}
                          style={{
                            display: 'flex', alignItems: 'center', gap: 8, padding: '9px 12px', borderRadius: 'var(--r-sm)',
                            cursor: 'pointer', textAlign: 'right', fontFamily: 'inherit', fontSize: 13,
                            border: active ? '1px solid var(--primary)' : '1px solid var(--border)',
                            background: active ? 'var(--primary-soft)' : 'var(--surface)',
                          }}>
                          <span style={{
                            width: 16, height: 16, borderRadius: 4, display: 'grid', placeItems: 'center', flexShrink: 0,
                            border: active ? '1px solid var(--primary)' : '1px solid var(--border-2)',
                            background: active ? 'var(--primary)' : 'transparent',
                          }}>
                            {active && <span style={{ width: 8, height: 8, background: 'var(--surface)', borderRadius: 2 }} />}
                          </span>
                          {o.name}
                        </button>
                      );
                    })}
                  </div>
                )}
              </>
            )}

            {/* لیستِ انباشتهٔ سرویس‌های انتخاب‌شده (از هر بخش) — قابل حذف */}
            {selectedServices.length > 0 && (
              <div style={{ margin: '4px 0 12px' }}>
                <label style={label}>سرویس‌های انتخاب‌شده ({selectedServices.length})</label>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 6 }}>
                  {selectedServices.map(s => (
                    <span key={s.uuid} style={{
                      display: 'inline-flex', alignItems: 'center', gap: 6, padding: '5px 6px 5px 10px',
                      borderRadius: 'var(--r-pill)', fontSize: 12.5, background: 'var(--primary-soft)',
                      color: 'var(--primary-700)', border: '1px solid var(--primary)',
                    }}>
                      {s.name}
                      <button type="button" aria-label={`حذف ${s.name}`} onClick={() => removeService(s.uuid)}
                        style={{
                          display: 'grid', placeItems: 'center', width: 16, height: 16, borderRadius: 999,
                          border: 'none', cursor: 'pointer', background: 'var(--primary)', color: 'var(--on-primary)',
                          fontSize: 12, lineHeight: 1, fontFamily: 'inherit',
                        }}>×</button>
                    </span>
                  ))}
                </div>
              </div>
            )}
          </>
        ) : (
          <div style={{ maxWidth: 400, marginBottom: 10 }}>
            <label style={label}>پرسنل</label>
            <div style={{ marginTop: 6 }}>
              <SearchableSelect
                options={(staffQ.data?.data ?? []).map(o => ({ value: o.uuid, label: o.full_name ?? '' }))}
                value={staffUuid || null}
                onChange={v => setStaffUuid(v ? String(v) : '')}
                placeholder="انتخاب پرسنل"
                isLoading={staffQ.isLoading}
                isClearable
                height={44}
              />
            </div>
          </div>
        )}

        {/* زمان نوبت */}
        <div style={sectionTitle}>زمان نوبت{resourceMode ? ` — ${activeResource!.name}` : ''}</div>
        {serviceMode ? (
          <>
            <label style={label}>انتخاب تاریخ</label>
            <div style={{ margin: '6px 0 10px', maxWidth: 400 }}><PersianDateInput value={date} onChange={setDate} /></div>
            <div style={{ marginBottom: 12 }}>
              {doctorUuid ? (
                <ServiceSlotPicker
                  doctorUuid={doctorUuid}
                  resourceUuid={activeResource?.uuid}
                  date={date}
                  services={resourceMode ? resourceServices : services}
                  onSelect={setServicePick}
                />
              ) : (
                <div style={{ fontSize: 12.5, color: 'var(--text-3)' }}>ابتدا پزشک را انتخاب کنید.</div>
              )}
            </div>
          </>
        ) : (
          <>
            <div style={{ maxWidth: 400, marginBottom: 12 }}>
              <label style={label}>انتخاب تاریخ</label>
              <div style={{ marginTop: 6 }}><PersianDateInput value={date} onChange={setDate} /></div>
            </div>

            {!manualTime ? (
              <div style={{ marginBottom: 12 }}>
                <label style={label}>انتخاب زمان از برنامهٔ پزشک</label>
                <div style={{ marginTop: 6 }}>
                  {doctorUuid ? (
                    <SlotPicker doctorUuid={doctorUuid} date={date} value={slotPick} onSelect={setSlotPick} />
                  ) : (
                    <div style={{ fontSize: 12.5, color: 'var(--text-3)' }}>ابتدا پزشک را انتخاب کنید.</div>
                  )}
                </div>
                <button type="button" className="btn sm ghost" style={{ marginTop: 8 }}
                  onClick={() => { setManualTime(true); setSlotPick(null); }}>
                  ثبت خارج از برنامه (ورود دستی ساعت)
                </button>
              </div>
            ) : (
              <>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginBottom: 8 }}>
                  <div>
                    <label style={label}>زمان پیش فرض (دقیقه)</label>
                    <div className="field" style={{ marginTop: 6, height: 44 }}>
                      <input aria-label="زمان پیش فرض" type="text" inputMode="numeric" value={duration} onChange={e => setDuration(Math.max(5, Number(digitsOnly(e.target.value)) || 0))} dir="ltr" />
                    </div>
                  </div>
                  <div>
                    <label style={label}>ساعت شروع</label>
                    <div className="field" style={{ marginTop: 6, height: 44 }}><input aria-label="ساعت شروع" type="time" value={start} onChange={e => setStart(e.target.value)} dir="ltr" /></div>
                  </div>
                  <div>
                    <label style={label}>ساعت پایان</label>
                    <div className="field" style={{ marginTop: 6, height: 44 }}><input aria-label="ساعت پایان" type="time" value={end} onChange={e => setEnd(e.target.value)} dir="ltr" /></div>
                  </div>
                </div>
                <button type="button" className="btn sm ghost" style={{ marginBottom: 12 }}
                  onClick={() => setManualTime(false)}>
                  بازگشت به انتخاب از برنامهٔ پزشک
                </button>
              </>
            )}
          </>
        )}

        {/* بیعانه */}
        <div style={sectionTitle}>بیعانه</div>
        <Switch
          inline
          checked={depositRequired}
          onChange={setDepositRequired}
          label="بیعانه مورد نیاز است."
        />
        {depositRequired && (
          <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'flex-end', gap: 12, margin: '12px 0' }}>
            <div style={{ width: 300, maxWidth: '100%' }}>
              <label style={label}>مبلغ بیعانه (تومان)</label>
              <div className="field" style={{ marginTop: 6, height: 44 }}><PriceInput value={depositToman} onChange={setDepositToman} /></div>
            </div>
            <WalletChargeLink mobile={effectiveMobile} />
          </div>
        )}

        {/* هزینه ویزیت */}
        <div style={sectionTitle}>هزینه ویزیت</div>
        <div style={{ width: 300, maxWidth: '100%', marginBottom: 12 }}>
          <label style={label}>
            هزینه ویزیت (تومان){requireVisit && <span style={{ color: 'var(--danger)' }}> *</span>}
          </label>
          <div className="field" style={{ marginTop: 6, height: 44 }}>
            <PriceInput value={visitPriceToman} onChange={(v) => { setVisitPriceToman(v); setVisitPriceTouched(true); }} />
          </div>
          {requireVisit && visitPriceToman <= 0 && (
            <span style={{ fontSize: 12, color: 'var(--danger)', display: 'block', marginTop: 4 }}>هزینه ویزیت الزامی است</span>
          )}
        </div>

        <label style={label}>توضیحات</label>
        <div className="field" style={{ height: 'auto', margin: '6px 0 16px' }}>
          <textarea value={note} onChange={e => setNote(e.target.value)} rows={4} placeholder="توضیحات..."
            style={{ width: '100%', border: 'none', background: 'transparent', fontFamily: 'inherit', resize: 'vertical' }} />
        </div>

        <div style={{ display: 'flex', justifyContent: 'flex-end', paddingTop: 4 }}>
          <button className="btn primary lg" disabled={!valid || create.isPending} onClick={() => create.mutate()}>
            {create.isPending ? '...' : 'ثبت اطلاعات'}
          </button>
        </div>
      </div>
    </div>
  );
}
