import React, { useEffect, useRef, useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import {
  PlusIcon, ChevronRightIcon, ChevronLeftIcon, CalendarDaysIcon,
  AdjustmentsHorizontalIcon,
} from '@heroicons/react/24/outline';
import { toast } from 'sonner';
import { api } from '../lib/api';
import type { PaginatedResponse, ApiResponse } from '../lib/api';
import type { Appointment } from '../types';
import { formatDate, toGregorianDate } from '../lib/utils';
import { useAuthStore } from '../stores/authStore';
import Pagination from '../components/ui/Pagination';
import AppointmentFiltersModal, { applyAppointmentFilters, EMPTY_FILTERS } from '../components/AppointmentFiltersModal';
import type { AppointmentFilters } from '../components/AppointmentFiltersModal';
import PersianCalendar from '../components/ui/PersianCalendar';
// اجزای طرح نوبت‌های tauri
import TurnsStatInfo from '../components/appointments/TurnsStatInfo';
import TurnsViewToggle from '../components/appointments/TurnsViewToggle';
import type { TurnsViewMode } from '../components/appointments/TurnsViewToggle';
import DoctorTabs from '../components/appointments/DoctorTabs';
import TurnsTimeline from '../components/appointments/TurnsTimeline';
import TurnsTable from '../components/appointments/TurnsTable';
import { CANCELLED_STATUSES } from '../components/appointments/turnStatus';
import type { TimelineSlot } from '../components/appointments/types';

const EMPTY_ARR: Appointment[] = [];

// ─────────────────────────────────────────────────────────────────────────────
// Date Navigator (طرح tauri — ناوبری روزانه)
// ─────────────────────────────────────────────────────────────────────────────

const WEEK_DAYS_FA = ['یک‌شنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنج‌شنبه', 'جمعه', 'شنبه'];

function getPersianWeekDay(gregorianDate: string): string {
  return WEEK_DAYS_FA[new Date(gregorianDate + 'T12:00:00').getDay()];
}

const navBtnSx: React.CSSProperties = {
  background: 'var(--surface)', border: '1px solid var(--border)',
  borderRadius: 'var(--r-sm)', height: 36, width: 36,
  display: 'flex', alignItems: 'center', justifyContent: 'center',
  cursor: 'pointer', color: 'var(--text-2)',
};

function DateNavigator({ date, onChange }: { date: string; onChange: (d: string) => void }) {
  const [showCal, setShowCal] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  const weekDay = getPersianWeekDay(date);
  const isFriday = new Date(date + 'T12:00:00').getDay() === 5;

  function addDays(n: number) {
    const d = new Date(date + 'T12:00:00');
    d.setDate(d.getDate() + n);
    onChange(toGregorianDate(d));
  }

  return (
    <div ref={ref} style={{ display: 'flex', alignItems: 'center', gap: 2, position: 'relative' }}>
      <button className="btn sm" style={navBtnSx} onClick={() => addDays(1)}>
        <ChevronRightIcon style={{ width: 15, height: 15 }} />
      </button>
      <div style={{
        padding: '0 14px', height: 44,
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
        background: 'var(--surface)', border: '1px solid var(--border)',
        borderRadius: 'var(--r-sm)', minWidth: 130, gap: 1,
      }}>
        <span style={{ fontSize: 13, fontWeight: 700, lineHeight: 1.2, color: isFriday ? '#ef4444' : 'var(--text)' }}>
          {weekDay}
        </span>
        <span style={{ fontSize: 11, color: 'var(--text-2)', lineHeight: 1.2 }}>
          {formatDate(date)}
        </span>
      </div>
      <button className="btn sm" style={navBtnSx} onClick={() => addDays(-1)}>
        <ChevronLeftIcon style={{ width: 15, height: 15 }} />
      </button>
      <button className="btn sm" style={navBtnSx} onClick={() => setShowCal(c => !c)}>
        <CalendarDaysIcon style={{ width: 15, height: 15 }} />
      </button>
      {showCal && (
        <PersianCalendar value={date} onChange={v => { onChange(v); setShowCal(false); }} onClose={() => setShowCal(false)} />
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Quick booking modal (کلیک روی اسلات خالیِ زمانبندی)
// ─────────────────────────────────────────────────────────────────────────────

interface BookingSlot { start: number; end: number; start_time: string; end_time: string; doctor_uuid: string; doctor_name: string; }

function NewAppointmentModal({
  slot, onClose, onSuccess,
}: { slot: BookingSlot; onClose: () => void; onSuccess: () => void }) {
  const [mobile, setMobile] = useState('');
  const [patientName, setPatientName] = useState('');

  const role = useAuthStore(s => s.primaryRole);
  const createEndpoint = role === 'admin' ? '/api/v1/admin/appointment' : '/api/v1/my/appointment';

  const isValid = mobile.length >= 10 && patientName.trim().length >= 2;

  const mutation = useMutation({
    mutationFn: () => api.post(createEndpoint, {
      doctor_uuid: slot.doctor_uuid,
      slot_start: slot.start,
      slot_end: slot.end,
      patient_mobile: mobile,
      patient_name: patientName.trim(),
    }),
    onSuccess: () => {
      toast.success('نوبت با موفقیت ثبت شد');
      onSuccess();
      onClose();
    },
    onError: (e: any) => {
      const msg = e?.response?.data?.errors?.[0]?.message ?? e?.message ?? 'خطا در ثبت نوبت';
      toast.error(msg);
    },
  });

  const inputSx: React.CSSProperties = {
    width: '100%', height: 38, padding: '0 10px', borderRadius: 'var(--r-sm)',
    border: '1px solid var(--border)', background: 'var(--surface)', fontSize: 13,
    boxSizing: 'border-box',
  };
  const labelSx: React.CSSProperties = {
    display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-2)', marginBottom: 6,
  };

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 500,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }} onClick={onClose}>
      <div style={{
        background: 'var(--surface)', borderRadius: 'var(--r)', padding: 24,
        minWidth: 320, maxWidth: 400, width: '90vw', boxShadow: 'var(--shadow-lg)',
      }} onClick={e => e.stopPropagation()}>
        <div style={{ fontWeight: 700, fontSize: 16, marginBottom: 4 }}>ثبت نوبت</div>
        <div style={{ fontSize: 13, color: 'var(--text-2)', marginBottom: 16 }}>
          {slot.start_time} تا {slot.end_time} — {slot.doctor_name}
        </div>

        <div style={{ marginBottom: 12 }}>
          <label style={labelSx}>نام و نام خانوادگی بیمار *</label>
          <input
            type="text"
            value={patientName}
            onChange={e => setPatientName(e.target.value)}
            placeholder="مثال: علی محمدی"
            style={inputSx}
            autoFocus
          />
        </div>

        <div style={{ marginBottom: 16 }}>
          <label style={labelSx}>شماره موبایل بیمار *</label>
          <input
            type="tel"
            value={mobile}
            onChange={e => setMobile(e.target.value)}
            placeholder="مثال: 09123456789"
            style={{ ...inputSx, direction: 'ltr' }}
          />
        </div>

        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <button className="btn sm" onClick={onClose}>انصراف</button>
          <button
            className="btn primary sm"
            onClick={() => mutation.mutate()}
            disabled={!isValid || mutation.isPending}
          >
            {mutation.isPending ? '...' : 'ثبت نوبت'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Main Page — «نوبت‌ ها» (طرح tauri)
// ─────────────────────────────────────────────────────────────────────────────

interface TodayStats { total: number; completed: number; waiting: number; cancelled: number; }

export default function AppointmentsPage() {
  const navigate = useNavigate();
  const primaryRole = useAuthStore(s => s.primaryRole);
  const dbUuid = useAuthStore(s => s.dbUuid);
  const isAdmin = primaryRole === 'admin';
  const isClinic = primaryRole === 'clinic';
  const isDoctor = primaryRole === 'doctor';
  const isRepresentation = primaryRole === 'representation';

  const today = new Date().toISOString().slice(0, 10);
  const [selectedDate, setSelectedDate] = useState(today);
  const [viewMode, setViewMode] = useState<TurnsViewMode>('timeline');
  const [selectedDoctorUuid, setSelectedDoctorUuid] = useState<string>(isDoctor && dbUuid ? dbUuid : '');
  const [bookingSlot, setBookingSlot] = useState<BookingSlot | null>(null);
  const [filtersOpen, setFiltersOpen] = useState(false);
  const [filters, setFilters] = useState<AppointmentFilters>(EMPTY_FILTERS);
  const qc = useQueryClient();

  // ── Today stats
  const statsQuery = useQuery<ApiResponse<TodayStats>>({
    queryKey: ['appt-today-stats', selectedDate, isAdmin],
    queryFn: () => api.get(
      isAdmin
        ? `/api/v1/admin/appointments/today-stats?date=${selectedDate}`
        : `/api/v1/my/appointments/today-stats?date=${selectedDate}`
    ),
  });
  const stats = statsQuery.data?.data ?? { total: 0, completed: 0, waiting: 0, cancelled: 0 };

  // ── Appointments query
  const apptEndpoint = isAdmin
    ? '/api/v1/admin/appointments'
    : isRepresentation
      ? '/api/v1/representation/appointments'
      : '/api/v1/my/appointments';
  const apptQueryKey = ['appointments', apptEndpoint, selectedDate, selectedDoctorUuid];
  const apptParams = new URLSearchParams({ date: selectedDate, limit: '500' });
  if (selectedDoctorUuid) apptParams.set('doctor_uuid', selectedDoctorUuid);

  const apptQuery = useQuery<PaginatedResponse<Appointment>>({
    queryKey: apptQueryKey,
    queryFn: () => api.get(`${apptEndpoint}?${apptParams}`),
  });
  const appointments: Appointment[] = apptQuery.data?.data ?? EMPTY_ARR;
  const filteredAppointments = applyAppointmentFilters(appointments, filters);
  const filtersActive = filters !== EMPTY_FILTERS && JSON.stringify(filters) !== JSON.stringify(EMPTY_FILTERS);

  // Table pagination — client-side (full day stays loaded for timeline + doctor tabs).
  const TABLE_PAGE_SIZE = 20;
  const [tablePage, setTablePage] = useState(1);
  useEffect(() => { setTablePage(1); }, [selectedDate, selectedDoctorUuid, filters]);
  const pagedAppointments = filteredAppointments.slice((tablePage - 1) * TABLE_PAGE_SIZE, tablePage * TABLE_PAGE_SIZE);

  // ── Clinic doctors (authoritative list for tabs)
  const clinicDoctorsQuery = useQuery<ApiResponse<{ data: { uuid: string; name: string }[] }>>({
    queryKey: ['clinic-doctors', dbUuid],
    queryFn: () => api.get(`/api/v1/clinic/doctor-list/${dbUuid}`),
    enabled: isClinic && !!dbUuid,
  });
  const clinicDoctorsList = clinicDoctorsQuery.data?.data?.data ?? [];

  const doctors = React.useMemo(() => {
    const map = new Map<string, string>();
    clinicDoctorsList.forEach(d => map.set(d.uuid, d.name));
    appointments.forEach(a => {
      if (a.doctor_uuid && a.doctor_name && !map.has(a.doctor_uuid)) {
        map.set(a.doctor_uuid, a.doctor_name);
      }
    });
    return Array.from(map.entries()).map(([uuid, name]) => ({ uuid, name }));
  }, [appointments, clinicDoctorsList]);

  // سرویس‌های موجود در نوبت‌های امروز (برای فیلتر «سرویس مورد نظر...»).
  const serviceOptions = React.useMemo(() => {
    const map = new Map<string, string>();
    appointments.forEach(a => {
      if (a.service_item?.uuid && a.service_item?.name) map.set(a.service_item.uuid, a.service_item.name);
    });
    return Array.from(map.entries()).map(([uuid, name]) => ({ uuid, name }));
  }, [appointments]);

  // نوع پروفایل: کلینیک چندپزشکه (تب دکترها + مدیریت چند پزشک) در برابر پزشک مستقل.
  // نقش clinic/admin = چندپزشکه؛ نقش doctor (حتی مهمانِ کلینیک) = مستقل، فقط برنامهٔ خودش.
  const isMultiDoctorClinic = isClinic || isAdmin;
  const showDoctorTabs = isMultiDoctorClinic && doctors.length >= 1;
  const showDoctorCol = isAdmin && !selectedDoctorUuid;

  // در کلینیک، اولین دکتر به‌صورت پیش‌فرض انتخاب می‌شود تا زمانبندی مثل طرح پر باشد.
  useEffect(() => {
    if (isClinic && !selectedDoctorUuid && doctors.length > 0) {
      setSelectedDoctorUuid(doctors[0].uuid);
    }
  }, [isClinic, selectedDoctorUuid, doctors]);

  // ── Slots query (timeline)
  const slotsQueryKey = ['appt-slots', selectedDoctorUuid, selectedDate];
  const slotsQuery = useQuery<ApiResponse<any>>({
    queryKey: slotsQueryKey,
    queryFn: () => api.get(`/api/v1/appointment-slots?doctor_uuid=${selectedDoctorUuid}&date=${selectedDate}`),
    enabled: viewMode === 'timeline' && !!selectedDoctorUuid,
  });

  // ── Merge sessions + appointments → flat timeline slots
  const timelineSlots: TimelineSlot[] = React.useMemo(() => {
    if (viewMode !== 'timeline') return [];
    const rawSessions: any[] = (slotsQuery.data?.data as any)?.sessions ?? [];

    const activeByStart = new Map<number, Appointment>();
    const cancelledByStart = new Map<number, Appointment>();
    appointments.forEach(a => {
      const key = typeof a.slot_start === 'number' ? a.slot_start : parseInt(String(a.slot_start), 10);
      if (CANCELLED_STATUSES.has(a.status)) {
        const existing = cancelledByStart.get(key);
        if (!existing || a.created_at > existing.created_at) cancelledByStart.set(key, a);
      } else {
        activeByStart.set(key, a);
      }
    });

    const out: TimelineSlot[] = [];
    rawSessions.forEach((session: any) => {
      (session.slots as any[]).forEach((s: any) => {
        const slotStart = typeof s.start === 'number' ? s.start : parseInt(String(s.start), 10);
        const slotEnd = typeof s.end === 'number' ? s.end : parseInt(String(s.end), 10);
        out.push({
          start: slotStart,
          end: slotEnd,
          start_time: s.start_time ?? new Date(slotStart * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
          end_time: s.end_time ?? new Date(slotEnd * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }),
          is_available: s.is_available as boolean,
          appointment: activeByStart.get(slotStart) ?? null,
          cancelled_appointment: cancelledByStart.get(slotStart) ?? null,
        });
      });
    });
    return out;
  }, [viewMode, slotsQuery.data, appointments]);

  // ── Slot click → quick booking modal
  function handleSlotClick(slot: TimelineSlot) {
    if (isRepresentation) return;
    const doctorName = doctors.find(d => d.uuid === selectedDoctorUuid)?.name ?? '';
    setBookingSlot({
      start: slot.start,
      end: slot.end,
      start_time: slot.start_time,
      end_time: slot.end_time,
      doctor_uuid: selectedDoctorUuid,
      doctor_name: doctorName,
    });
  }

  function openDetail(a: Appointment) {
    navigate(`/admin/appointments/${a.uuid}`);
  }

  return (
    <div style={{ padding: '20px 24px' }}>
      <div style={{ maxWidth: 1050, margin: '0 auto' }}>
        {/* عنوان */}
        <h1 style={{ fontSize: 20, fontWeight: 700, color: 'var(--text)', marginBottom: 16 }}>نوبت‌ ها</h1>

        {/* نوار آمار */}
        <TurnsStatInfo stats={stats} />

        {/* نوار ابزار (بیرونِ کارت، مطابق طرح) */}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap', marginBottom: 16,
        }}>
          {/* سمت راست: تاریخ + سرویس + سوییچ نما (مطابق طرح) */}
          <DateNavigator date={selectedDate} onChange={setSelectedDate} />

          <ServiceFilterSelect
            value={filters.itemUuid}
            options={serviceOptions}
            onChange={(v) => setFilters(f => ({ ...f, itemUuid: v }))}
          />

          <TurnsViewToggle viewMode={viewMode} onChange={setViewMode} />

          <div style={{ flex: 1 }} />

          {/* سمت چپ: فیلتر + افزودن نوبت */}
          <button
            aria-label="فیلترها"
            className="btn sm"
            onClick={() => setFiltersOpen(true)}
            style={{
              border: `1px solid ${filtersActive ? 'var(--primary)' : 'var(--border)'}`,
              color: filtersActive ? 'var(--primary)' : 'var(--text-2)',
              background: 'var(--surface)',
            }}
          >
            <AdjustmentsHorizontalIcon style={{ width: 16 }} />
          </button>

          {!isRepresentation && (
            <button
              className="btn primary sm"
              onClick={() => {
                const q = selectedDoctorUuid ? `?doctor=${selectedDoctorUuid}&date=${selectedDate}` : `?date=${selectedDate}`;
                navigate(`/admin/appointments/new${q}`);
              }}
              style={{ display: 'flex', alignItems: 'center', gap: 5 }}
            >
              <PlusIcon style={{ width: 15, height: 15 }} />
              افزودن نوبت
            </button>
          )}
        </div>

        {/* کارت اصلی — تب دکترها (هدر) + محتوا */}
        <div style={{
          background: 'var(--surface)', border: '1px solid var(--border)',
          borderRadius: 'var(--r)', overflow: 'hidden',
        }}>
          {showDoctorTabs && (
            <DoctorTabs doctors={doctors} selected={selectedDoctorUuid} onSelect={setSelectedDoctorUuid} showAll={isAdmin} />
          )}
          <div style={{ padding: 16 }}>
            {viewMode === 'table' ? (
              <>
                <TurnsTable
                  items={pagedAppointments}
                  loading={apptQuery.isLoading}
                  queryKey={apptQueryKey}
                  showDoctor={showDoctorCol}
                />
                {filteredAppointments.length > TABLE_PAGE_SIZE && (
                  <div style={{ marginTop: 14 }}>
                    <Pagination page={tablePage} total={filteredAppointments.length} limit={TABLE_PAGE_SIZE} onPageChange={setTablePage} />
                  </div>
                )}
              </>
            ) : (
              <>
                {!selectedDoctorUuid ? (
                  <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-3)' }}>
                    برای نمایش زمانبندی، ابتدا یک پزشک انتخاب کنید
                  </div>
                ) : (
                  <TurnsTimeline
                    slots={timelineSlots}
                    loading={apptQuery.isLoading || slotsQuery.isLoading}
                    queryKey={apptQueryKey}
                    onView={openDetail}
                    onBook={handleSlotClick}
                  />
                )}
              </>
            )}
          </div>
        </div>
      </div>

      {/* مودال ثبت سریع نوبت */}
      {bookingSlot && (
        <NewAppointmentModal
          slot={bookingSlot}
          onClose={() => setBookingSlot(null)}
          onSuccess={() => {
            qc.invalidateQueries({ queryKey: apptQueryKey });
            qc.invalidateQueries({ queryKey: slotsQueryKey });
            qc.invalidateQueries({ queryKey: ['appt-today-stats', selectedDate] });
          }}
        />
      )}

      {/* مودال فیلترها */}
      {filtersOpen && (
        <AppointmentFiltersModal value={filters} onApply={setFilters} onClose={() => setFiltersOpen(false)} />
      )}
    </div>
  );
}

/** فیلتر سرویس نوار ابزار — ردیف‌های بارگذاری‌شدهٔ روز را بر اساس سرویس فیلتر می‌کند. */
function ServiceFilterSelect({ value, options, onChange }: {
  value: string; options: { uuid: string; name: string }[]; onChange: (v: string) => void;
}) {
  return (
    <select aria-label="سرویس" value={value} onChange={e => onChange(e.target.value)}
      style={{ height: 44, borderRadius: 'var(--r-sm)', border: '1px solid var(--border)', background: 'var(--surface)', fontSize: 13, fontFamily: 'inherit', padding: '0 12px', minWidth: 280 }}>
      <option value="">سرویس مورد نظر را انتخاب کنید...</option>
      {options.map(s => <option key={s.uuid} value={s.uuid}>{s.name}</option>)}
    </select>
  );
}
