import { useEffect, useRef, useState } from 'react';
import { UserIcon, PhoneIcon, DocumentTextIcon, PlusIcon, ShieldCheckIcon } from '@heroicons/react/24/outline';
import type { Appointment } from '../../types';
import { useAppointmentInsurance } from '../../hooks/useAppointmentInsurance';
import AppointmentStatusDropdown from '../ui/AppointmentStatusDropdown';
import AppointmentActionsMenu from '../AppointmentActions';
import ConfirmAppointmentModal from './ConfirmAppointmentModal';
import { turnStatusConfig, EMPTY_SLOT_CONFIG } from './turnStatus';
import type { TimelineSlot } from './types';

/**
 * نمای زمانبندی (زمانبندی) — بازسازیِ `Timeline.jsx` طرح tauri:
 * هر ردیف: «ریل مارکر» بیرونی (نقطهٔ رنگی + ساعت شروع + خط‌چین) سمت راست + «کارت
 * نوبت» چپِ آن. داخل کارت: مارکر زمانِ داخلی (نقطهٔ حلقه‌ای شروع/پایان)، اطلاعات
 * بیمار (نام/تلفن/سرویس) و در سمت چپ وضعیت + عملیات. اسلات خالی → «افزودن نوبت».
 * ردیف‌ها با max-width وسط‌چین می‌شوند. رنگ‌ها عیناً از طرح مبدأ.
 */

const ROW_MAX = 760;

// نقطهٔ حلقه‌ای (حلقهٔ بیرونی + نقطهٔ داخلی) — مثل TimelineElement طرح tauri.
function RingDot({ color }: { color: string }) {
  return (
    <span style={{ position: 'relative', width: 17, height: 17, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
      <span style={{ position: 'absolute', width: 16, height: 16, borderRadius: '50%', border: `2px solid ${color}` }} />
      <span style={{ width: 7, height: 7, borderRadius: '50%', background: color }} />
    </span>
  );
}

// مارکر زمانِ داخلِ کارت (ساعت شروع بالا، ساعت پایان پایین + خط‌چین بین آن‌ها).
function InnerTimes({ start, end, color }: { start: string; end: string; color: string }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', justifyContent: 'center', gap: 4, minWidth: 62, alignSelf: 'stretch' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
        <RingDot color={color} />
        <span style={{ fontSize: 12, color: 'var(--text-2)', minWidth: 38, textAlign: 'center' }}>{start}</span>
      </div>
      <div style={{ width: 2, height: 14, marginInlineEnd: 6, backgroundImage: `repeating-linear-gradient(to bottom, ${color} 0, ${color} 3px, transparent 3px, transparent 6px)` }} />
      <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
        <RingDot color={color} />
        <span style={{ fontSize: 12, color: 'var(--text-2)', minWidth: 38, textAlign: 'center' }}>{end}</span>
      </div>
    </div>
  );
}

// ریل مارکر بیرونی (سمت راستِ ردیف): نقطهٔ رنگی + ساعت + خط‌چین عمودی.
function OuterMarker({ color, time, showLine }: { color: string; time: string; showLine: boolean }) {
  return (
    <div style={{ width: 55, position: 'relative', display: 'flex', alignItems: 'flex-start', justifyContent: 'flex-start' }}>
      {showLine && (
        <div style={{
          position: 'absolute', right: 5, top: 18, height: 'calc(100% + 16px)', width: 2,
          backgroundImage: 'repeating-linear-gradient(to bottom, var(--border-2) 0, var(--border-2) 4px, transparent 4px, transparent 8px)',
          zIndex: 0,
        }} />
      )}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, position: 'relative', zIndex: 1 }}>
        <span style={{ width: 12, height: 12, borderRadius: '50%', background: color, border: '2px solid var(--surface)', boxShadow: '0 0 0 1px var(--border)', flexShrink: 0 }} />
        <span style={{ fontSize: 12, color: 'var(--text-2)', minWidth: 42 }}>{time}</span>
      </div>
    </div>
  );
}

function EmptyCard({ slot, onBook }: { slot: TimelineSlot; onBook: (s: TimelineSlot) => void }) {
  const cfg = EMPTY_SLOT_CONFIG;
  const isPast = slot.start < Math.floor(Date.now() / 1000);
  return (
    <div
      onClick={() => !isPast && onBook(slot)}
      style={{
        background: isPast ? 'var(--surface-2)' : cfg.bgColor,
        border: `1px dashed ${isPast ? 'var(--border-2)' : cfg.borderColor}`,
        borderRadius: 8, padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 14,
        cursor: isPast ? 'not-allowed' : 'pointer', opacity: isPast ? 0.7 : 1, minHeight: 76,
      }}
    >
      <InnerTimes start={slot.start_time} end={slot.end_time} color={isPast ? 'var(--text-3)' : cfg.dotColor} />
      <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}>
        <span style={{ fontSize: 13.5, color: isPast ? 'var(--text-3)' : cfg.textColor, fontWeight: 500 }}>
          {isPast ? 'گذشته' : 'افزودن نوبت سریع'}
        </span>
        {!isPast && <PlusIcon style={{ width: 18, height: 18, color: cfg.textColor }} />}
      </div>
      {/* برچسب «نوبت جدید» سمت چپ (مطابق طرح) */}
      {!isPast && (
        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 10px', borderRadius: 99,
          fontSize: 12, fontWeight: 700, color: cfg.textColor, background: `color-mix(in srgb, ${cfg.dotColor} 8%, transparent)`,
          border: `1.5px solid color-mix(in srgb, ${cfg.dotColor} 19%, transparent)`, whiteSpace: 'nowrap', alignSelf: 'flex-start',
        }}>
          <span style={{ width: 7, height: 7, borderRadius: '50%', background: cfg.dotColor }} />
          نوبت جدید
        </span>
      )}
    </div>
  );
}

function OccupiedCard({
  appointment: a, queryKey, onView,
}: {
  appointment: Appointment; queryKey: unknown[]; onView: (a: Appointment) => void;
}) {
  const cfg = turnStatusConfig(a.status);
  const [confirmOpen, setConfirmOpen] = useState(false);
  // نام بیمه فقط با نگاشت از قراردادهای کش‌شده به دست می‌آید؛ payload نوبت نامی ندارد
  // تا لیست‌های نوبت به N+1 نیفتند.
  const insurance = useAppointmentInsurance(!!a.insurance_base_id, a.doctor_uuid ?? null);
  const insuranceChip = [
    a.insurance_service_category_label,
    insurance.insuranceNameOf(a.insurance_base_id),
  ].filter(Boolean).join(' · ');
  return (
    <div
      onClick={() => onView(a)}
      style={{
        background: cfg.bgColor, border: `1px solid ${cfg.borderColor}`, borderRadius: 8,
        padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 14, cursor: 'pointer', minHeight: 88,
      }}
    >
      <InnerTimes start={a.appointment_time} end={a.end_time} color={cfg.dotColor} />

      {/* اطلاعات بیمار */}
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 7 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
          <UserIcon style={{ width: 16, height: 16, color: 'var(--text-3)', flexShrink: 0 }} />
          <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {a.patient_name || '—'}
          </span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
          <PhoneIcon style={{ width: 14, height: 14, color: 'var(--text-3)', flexShrink: 0 }} />
          <span style={{ fontSize: 12.5, color: 'var(--text-2)', direction: 'ltr' }}>{a.patient_mobile}</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
          <DocumentTextIcon style={{ width: 14, height: 14, color: 'var(--text-3)', flexShrink: 0 }} />
          <span style={{ fontSize: 11.5, color: 'var(--text-3)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            سرویس: {a.service_item?.name || '—'}
          </span>
        </div>
        {insuranceChip !== '' && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
            <ShieldCheckIcon style={{ width: 14, height: 14, color: 'var(--primary)', flexShrink: 0 }} />
            <span style={{
              fontSize: 11, fontWeight: 600, padding: '2px 8px', borderRadius: 'var(--r-pill)',
              background: 'var(--primary-soft)', color: 'var(--primary)',
              whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            }}>
              {insuranceChip}
            </span>
          </div>
        )}
      </div>

      {/* وضعیت + عملیات (کلیک روی این ناحیه نباید کارت را باز کند) */}
      <div onClick={(e) => e.stopPropagation()} style={{ display: 'flex', alignItems: 'center', gap: 8, alignSelf: 'flex-start', flexShrink: 0 }}>
        {a.status === 'pending' && (
          <>
            <button type="button" className="btn primary sm" onClick={() => setConfirmOpen(true)}>
              قطعی کردن نوبت
            </button>
            <ConfirmAppointmentModal
              open={confirmOpen}
              appointmentUuid={a.uuid}
              appointment={a}
              onClose={() => setConfirmOpen(false)}
              queryKey={queryKey}
            />
          </>
        )}
        <AppointmentStatusDropdown uuid={a.uuid} currentStatus={a.status} version={a.version} queryKey={queryKey} />
        <AppointmentActionsMenu appointment={a} queryKey={queryKey} />
      </div>
    </div>
  );
}

/**
 * چرا این روز اسلاتی ندارد — از `empty_reason` پاسخ appointment-slots.
 * خالی‌بودن لزوماً تعطیلی نیست.
 */
const EMPTY_REASON_TEXT: Record<string, { title: string; hint: string }> = {
  no_schedule:    { title: 'برنامهٔ نوبت‌دهی ثبت نشده',   hint: 'برای این محل هنوز برنامهٔ کاری تعریف نشده است' },
  holiday:        { title: 'این روز تعطیل است',           hint: 'در تقویم تعطیلات، این روز برای پزشک تعطیل ثبت شده' },
  day_off:        { title: 'این روز شیفت کاری ندارد',     hint: 'در برنامهٔ هفتگی، برای این روز شیفتی تعریف نشده است' },
  outside_window: { title: 'خارج از بازهٔ نوبت‌دهی',      hint: 'این تاریخ از بازهٔ مجاز رزرو گذشته یا نوبت‌دهی آنلاین خاموش است' },
  // دلایلِ تقویمِ منبع — `resource/{uuid}/day-slots`.
  no_shift:          { title: 'این روز شیفت کاری ندارد',   hint: 'در تقویم این منبع، برای این روز شیفتی تعریف نشده است' },
  national_holiday:  { title: 'تعطیل رسمی',                hint: 'این روز در تقویم رسمی تعطیل است' },
  tenant_holiday:    { title: 'این روز تعطیل است',         hint: 'در تقویم تعطیلات مجموعه، این روز تعطیل ثبت شده' },
  exception:         { title: 'استثنای تقویم',             hint: 'کل ساعت کاری این روز با استثنای منبع پوشیده شده است' },
  resource_inactive: { title: 'این منبع غیرفعال است',      hint: 'برای نوبت‌دهی، منبع را از صفحهٔ «منابع» فعال کنید' },
};

export default function TurnsTimeline({
  slots, loading, queryKey, onView, onBook, emptyReason, errorMessage,
}: {
  slots: TimelineSlot[];
  emptyReason?: string | null;
  errorMessage?: string | null;
  loading: boolean;
  queryKey: unknown[];
  onView: (a: Appointment) => void;
  onBook: (s: TimelineSlot) => void;
}) {
  const activeRef = useRef<HTMLDivElement | null>(null);
  const now = Math.floor(Date.now() / 1000);
  const activeIndex = slots.findIndex(s => s.appointment && s.end >= now);

  useEffect(() => {
    if (!activeRef.current) return;
    const el = activeRef.current;
    const top = el.getBoundingClientRect().top + window.scrollY - window.innerHeight * 0.4;
    window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
  }, [activeIndex]);

  if (loading) return <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-3)' }}>در حال بارگذاری...</div>;
  if (errorMessage) {
    return (
      <div style={{ padding: 40, textAlign: 'center' }}>
        <div style={{ fontWeight: 700, fontSize: 15, color: 'var(--danger)' }}>خطا در دریافت برنامهٔ این روز</div>
        <div style={{ fontSize: 12, color: 'var(--text-3)', marginTop: 4 }}>{errorMessage}</div>
      </div>
    );
  }
  if (!slots.length) {
    // «شیفت کاری ندارد» فقط وقتی که backend صریحاً day_off گفته باشد؛
    // دلیل ناشناخته/غایب نباید به تعطیلی تفسیر شود.
    const reason = EMPTY_REASON_TEXT[emptyReason ?? '']
      ?? { title: 'برنامهٔ این روز در دسترس نیست', hint: 'اطلاعات برنامهٔ کاری برای این روز دریافت نشد' };
    return (
      <div style={{ padding: 40, textAlign: 'center' }}>
        <div style={{ fontWeight: 700, fontSize: 15, color: 'var(--text)' }}>{reason.title}</div>
        <div style={{ fontSize: 12, color: 'var(--text-3)', marginTop: 4 }}>{reason.hint}</div>
      </div>
    );
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center', padding: '4px 0' }}>
      {slots.map((slot, i) => {
        const color = slot.appointment ? turnStatusConfig(slot.appointment.status).dotColor : EMPTY_SLOT_CONFIG.dotColor;
        return (
          <div
            key={`${slot.start}-${i}`}
            ref={i === activeIndex ? activeRef : null}
            style={{ display: 'flex', flexDirection: 'row-reverse', gap: 16, position: 'relative', width: '100%', maxWidth: ROW_MAX }}
          >
            <OuterMarker color={color} time={slot.start_time} showLine={i < slots.length - 1} />
            <div style={{ flex: 1, minWidth: 0 }}>
              {slot.appointment
                ? <OccupiedCard appointment={slot.appointment} queryKey={queryKey} onView={onView} />
                : <EmptyCard slot={slot} onBook={onBook} />}
            </div>
          </div>
        );
      })}
    </div>
  );
}
