import { useEffect, useMemo, useRef, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { api } from '../../lib/api';
import type { ApiResponse } from '../../lib/api';
import type { BookingService } from '../../hooks/useDoctorBookingServices';
import { useClinicContext } from '../../hooks/useClinicContext';
import { XMarkIcon } from '@heroicons/react/24/outline';
import SearchableSelect from '../ui/SearchableSelect';
import DigitInput from '../ui/DigitInput';

interface ServiceSlot { start: number; end: number; start_time: string }
export interface PickedService { uuid: string; name: string; section: string; duration: number }
export interface ServicePick { serviceUuids: string[]; durations: Record<string, number>; slot: ServiceSlot | null }

/**
 * انتخاب سرویس بر اساس بخش (بخش → سرویس، انباشته از چند بخش) + زمان‌های خالیِ پیشنهادی
 * برای نوبت‌دهی سرویسی. مدتِ هر سرویس در پنل قابل ویرایش است (فقط برای همین نوبت؛ پیش‌فرضِ
 * سرویس تغییر نمی‌کند). مدت کل = مجموع مدت‌ها؛ زمان‌ها از `appointment-service-slots`
 * با اعمال همان override محاسبه می‌شوند. انتخاب را از طریق onSelect بالا می‌فرستد.
 */
export default function ServiceSlotPicker({
  doctorUuid, resourceUuid, date, services, onSelect, editableDuration = true, clinicUuidOverride,
  excludeAppointmentUuid, initialSelection,
}: {
  doctorUuid: string;
  /**
   * نوبت‌دهی روی یک منبع: زمان‌ها از تقویم خودِ منبع می‌آیند، نه از برنامهٔ پزشک.
   *
   * فرمِ انتخاب سرویس در هر دو حالت یکی است (بخش → سرویس → مدت → زمان)، پس فقط
   * منبعِ زمان عوض می‌شود نه کامپوننت — دو نسخه یعنی دو رفتار.
   */
  resourceUuid?: string;
  date: string;
  services: BookingService[];
  onSelect: (v: ServicePick) => void;
  editableDuration?: boolean;
  /** undefined = context محیط جاری؛ مقدار صریح (شامل null) = محل انتخاب‌شده خارج از context */
  clinicUuidOverride?: string | null;
  /**
   * ویرایش نوبت: بازهٔ خودِ همین نوبت اشغال حساب نشود، وگرنه زمان فعلی‌اش در فهرست
   * نمی‌آید و کاربر نمی‌تواند «همان ساعت، سرویس متفاوت» را ثبت کند.
   */
  excludeAppointmentUuid?: string;
  /** سرویس‌های از قبل انتخاب‌شده (ویرایش نوبت موجود). فقط یک بار هیدریت می‌شود. */
  initialSelection?: PickedService[];
}) {
  const contextClinicUuid = useClinicContext();
  const clinicUuid = clinicUuidOverride === undefined ? contextClinicUuid : clinicUuidOverride;
  const [sectionUuid, setSectionUuid] = useState('');
  const [selected, setSelected] = useState<PickedService[]>(initialSelection ?? []);
  const [pickedSlot, setPickedSlot] = useState<ServiceSlot | null>(null);

  // بخش‌های یکتا از روی سرویس‌های bookable (بدون endpoint اضافه — همه یکجا آمده‌اند).
  const sections = useMemo(() => {
    const map = new Map<string, { uuid: string; name: string }>();
    services.forEach(s => { if (s.service_section) map.set(s.service_section.uuid, s.service_section); });
    return [...map.values()];
  }, [services]);
  const sectionServices = useMemo(
    () => services.filter(s => s.service_section?.uuid === sectionUuid),
    [services, sectionUuid],
  );

  // تعویض پزشک ⇒ لیست سرویس‌ها عوض می‌شود؛ انتخاب‌ها ریست شوند. اجرای نخست معاف است،
  // وگرنه initialSelection (ویرایش نوبت موجود) همان لحظه پاک می‌شد.
  const mounted = useRef(false);
  useEffect(() => {
    if (!mounted.current) { mounted.current = true; return; }
    setSelected([]); setSectionUuid('');
  }, [doctorUuid, resourceUuid]);
  useEffect(() => { setPickedSlot(null); }, [selected, date, doctorUuid, resourceUuid]);

  const serviceUuids = useMemo(() => selected.map(s => s.uuid), [selected]);
  const durations = useMemo(
    () => Object.fromEntries(selected.map(s => [s.uuid, s.duration])) as Record<string, number>,
    [selected],
  );

  useEffect(() => { onSelect({ serviceUuids, durations, slot: pickedSlot }); }, [serviceUuids, durations, pickedSlot]);

  const durationsQs = selected.map(s => `&durations[${encodeURIComponent(s.uuid)}]=${s.duration}`).join('');
  const servicesQs  = serviceUuids.map(u => `&service_item_uuids[]=${encodeURIComponent(u)}`).join('');
  const slotsQ = useQuery<ApiResponse<any>>({
    queryKey: ['service-slots-picker', resourceUuid ?? doctorUuid, date, serviceUuids, durations, clinicUuid, excludeAppointmentUuid],
    queryFn: () => api.get(
      resourceUuid
        ? `/api/v1/resource/${resourceUuid}/service-slots?date=${date}` + servicesQs + durationsQs
        : `/api/v1/appointment-service-slots?doctor_uuid=${doctorUuid}&date=${date}&management=1`
          + servicesQs
          + durationsQs
          + (clinicUuid ? `&clinic_uuid=${encodeURIComponent(clinicUuid)}` : '')
          + (excludeAppointmentUuid ? `&exclude_appointment_uuid=${encodeURIComponent(excludeAppointmentUuid)}` : ''),
    ),
    enabled: (!!resourceUuid || !!doctorUuid) && !!date && serviceUuids.length > 0,
  });
  const startTimes: ServiceSlot[] = (slotsQ.data?.data as any)?.start_times ?? [];
  const totalMinutes = (slotsQ.data?.data as any)?.total_duration_minutes as number | undefined;

  const label = { fontSize: 12.5, color: 'var(--text-3)', display: 'block' } as const;

  const toggle = (s: BookingService) =>
    setSelected(prev => prev.some(p => p.uuid === s.uuid)
      ? prev.filter(p => p.uuid !== s.uuid)
      : [...prev, { uuid: s.uuid, name: s.name, section: s.service_section.name, duration: s.duration_minutes ?? 0 }]);
  const remove = (uuid: string) => setSelected(prev => prev.filter(p => p.uuid !== uuid));
  const setDuration = (uuid: string, minutes: number) =>
    setSelected(prev => prev.map(p => p.uuid === uuid ? { ...p, duration: minutes } : p));

  if (services.length === 0) {
    return (
      <div style={{ fontSize: 12.5, color: 'var(--danger)', margin: '6px 0' }}>
        {resourceUuid
          ? 'برای این منبع سرویسی تعریف نشده است — از تب «سرویس‌ها»ی همین منبع اضافه کنید.'
          : 'سرویسی با «نمایش در نوبت‌دهی آنلاین» برای این پزشک تعریف نشده است.'}
      </div>
    );
  }

  return (
    <div>
      {/* انتخاب بخش */}
      <label style={label} htmlFor="service-mode-section-select">بخش</label>
      <div style={{ margin: '6px 0 10px', maxWidth: 400 }}>
        <SearchableSelect
          inputId="service-mode-section-select"
          options={sections.map(s => ({ value: s.uuid, label: s.name }))}
          value={sectionUuid || null}
          onChange={v => setSectionUuid(v ? String(v) : '')}
          placeholder="ابتدا بخش را انتخاب کنید"
          isClearable
          height={44}
        />
      </div>

      {/* سرویس‌های بخشِ انتخاب‌شده — چند انتخابی */}
      {sectionUuid && (
        <>
          <label style={label}>سرویس‌های این بخش (یک یا چند)</label>
          {sectionServices.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' }}>
              {sectionServices.map(s => {
                const active = selected.some(p => p.uuid === s.uuid);
                return (
                  <button key={s.uuid} type="button" onClick={() => toggle(s)}
                    role="checkbox" aria-checked={active}
                    style={{
                      display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8,
                      minHeight: 40, 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={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
                      <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>
                      {s.name}
                    </span>
                    {s.duration_minutes ? <span style={{ color: 'var(--text-3)', fontSize: 12 }}>{s.duration_minutes} دقیقه</span> : null}
                  </button>
                );
              })}
            </div>
          )}
        </>
      )}

      {/* لیستِ انباشتهٔ سرویس‌های انتخاب‌شده (از هر بخش) — «بخش → سرویس» + مدت قابل‌ویرایش + حذف */}
      {selected.length > 0 && (
        <div style={{ margin: '4px 0 12px' }}>
          <label style={label}>سرویس‌های انتخاب‌شده ({selected.length})</label>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 6 }}>
            {selected.map(s => (
              <div key={s.uuid} style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '8px 10px', borderRadius: 'var(--r-sm)', fontSize: 13,
                background: 'var(--primary-soft)', border: '1px solid var(--primary)',
              }}>
                <span style={{
                  flex: 1, minWidth: 0, color: 'var(--primary-700)', fontWeight: 600,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>
                  <span style={{ color: 'var(--text-3)', fontWeight: 400 }}>{s.section}</span>
                  {' ← '}{s.name}
                </span>
                {editableDuration ? (
                  <span style={{
                    display: 'inline-flex', alignItems: 'center', gap: 4, flexShrink: 0,
                    height: 36, padding: '0 8px', borderRadius: 'var(--r-sm)',
                    background: 'var(--surface)', border: '1px solid var(--border-2)',
                  }}>
                    <DigitInput
                      aria-label={`مدت ${s.name}`}
                      value={String(s.duration || '')}
                      onChange={v => setDuration(s.uuid, Number(v) || 0)}
                      maxDigits={3}
                      style={{ width: 34, border: 'none', outline: 'none', background: 'transparent', textAlign: 'center', fontFamily: 'inherit', fontSize: 13, color: 'var(--text)' }}
                    />
                    <span style={{ color: 'var(--text-3)', fontSize: 11.5 }}>دقیقه</span>
                  </span>
                ) : (
                  <span style={{ flexShrink: 0, color: 'var(--text-3)', fontSize: 12 }}>{s.duration} دقیقه</span>
                )}
                {/* هدف کلیک ۳۲px است نه ۱۸px — این دکمه انتخابِ کاربر را پاک می‌کند و
                    خطا زدنش روی موبایل یعنی حذف ناخواستهٔ سرویس. */}
                <button type="button" className="mini-btn" aria-label={`حذف ${s.name}`} onClick={() => remove(s.uuid)}
                  style={{ flexShrink: 0, color: 'var(--primary-700)' }}>
                  <XMarkIcon style={{ width: 16, height: 16 }} />
                </button>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* زمان‌های خالی پیشنهادی */}
      {selected.length > 0 && (
        <>
          <label style={label}>زمان‌های خالی پیشنهادی{totalMinutes != null ? ` (مدت کل: ${totalMinutes} دقیقه)` : ''}</label>
          {slotsQ.isLoading ? (
            <div style={{ fontSize: 12.5, color: 'var(--text-3)', margin: '6px 0' }}>در حال محاسبه...</div>
          ) : slotsQ.isError ? (
            /* بدون این شاخه، خطای سرور به «زمان خالی نیست» ترجمه می‌شد — یعنی کاربر
               روز درست را کنار می‌گذاشت، چون پاسخ دروغ بود. */
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '6px 0' }}>
              <span style={{ fontSize: 12.5, color: 'var(--danger)' }}>خواندن زمان‌های خالی ناموفق بود.</span>
              <button type="button" className="btn ghost sm" onClick={() => slotsQ.refetch()}>تلاش دوباره</button>
            </div>
          ) : startTimes.length === 0 ? (
            <div style={{ fontSize: 12.5, color: 'var(--danger)', margin: '6px 0' }}>
              برای این سرویس در این روز زمان خالی کافی نیست؛ روز دیگری انتخاب کنید.
            </div>
          ) : (
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, margin: '6px 0 4px' }}>
              {startTimes.map(s => {
                const active = pickedSlot?.start === s.start;
                return (
                  <button key={s.start} type="button" dir="ltr"
                    aria-pressed={active}
                    onClick={() => setPickedSlot({ start: s.start, end: s.end, start_time: s.start_time })}
                    style={{
                      fontSize: 13, minHeight: 36, padding: '6px 12px', borderRadius: 'var(--r-sm)', cursor: 'pointer', fontFamily: 'inherit',
                      border: active ? '1px solid var(--primary)' : '1px solid var(--border)',
                      background: active ? 'var(--primary)' : 'var(--surface)', color: active ? 'var(--on-primary)' : 'var(--text)',
                    }}>
                    {s.start_time}
                  </button>
                );
              })}
            </div>
          )}
        </>
      )}
    </div>
  );
}
