import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import PageHeader from '../components/ui/PageHeader';
import DataTable, { type Column } from '../components/ui/DataTable';
import ConfirmDialog from '../components/ui/ConfirmDialog';
import SearchableSelect from '../components/ui/SearchableSelect';
import { formatDate, formatNumber } from '../lib/utils';
import { usePermissions } from '../hooks/usePermissions';
import { useBranches } from '../hooks/useBranches';
import { useNextSlotSuggestion, useTreatmentCourse } from '../hooks/useCourses';
import { useQuery } from '@tanstack/react-query';
import { api, type ApiResponse } from '../lib/api';
import type { CourseSessionRow } from '../types';

const SESSION_STATUS: Record<CourseSessionRow['status'], { label: string; className: string }> = {
  planned: { label: 'برنامه‌ریزی‌شده', className: 'badge' },
  booked: { label: 'رزروشده', className: 'badge amber' },
  completed: { label: 'انجام‌شده', className: 'badge green' },
  skipped: { label: 'رد‌شده', className: 'badge red' },
};

/**
 * یک دورهٔ درمان: پیشرفت، جلسات، و پیشنهاد تاریخ جلسهٔ بعدی.
 *
 * پیشنهاد به شعبه وابسته است (ظرفیت هر شعبه فرق دارد)، پس تا شعبه انتخاب نشود چیزی
 * پرسیده نمی‌شود.
 */
export default function TreatmentCoursePage() {
  const { courseUuid } = useParams<{ courseUuid: string }>();
  const { course, loading, abandon, bookAll } = useTreatmentCourse(courseUuid);
  const { branches } = useBranches();
  const { can } = usePermissions();
  const canManage = can('appointment_settings', 'update');

  const [branchUuid, setBranchUuid] = useState('');
  const [doctorUuid, setDoctorUuid] = useState('');
  const [abandoning, setAbandoning] = useState(false);
  const [reason, setReason] = useState('');

  const { suggestion } = useNextSlotSuggestion(courseUuid, branchUuid || undefined);

  /** همان اندپوینتی که صفحهٔ رزرو منبع‌محور استفاده می‌کند — منشی فقط پزشکان خودش را می‌بیند. */
  const doctorsQuery = useQuery<ApiResponse<{ data: { uuid: string; name: string }[] }>>({
    queryKey: ['booking-doctors'],
    queryFn: () => api.get('/api/v1/my/clinic-doctors'),
    staleTime: 60_000,
  });

  const doctors = doctorsQuery.data?.data?.data ?? [];

  /**
   * دوره‌ای که وسطش لغو شده، بی‌صدا کِش می‌آید: جلسه به «برنامه‌ریزی‌شده» برمی‌گردد و
   * هیچ‌کس خبردار نمی‌شود.
   *
   * هشدارِ پیشنهاد فقط وقتی می‌آید که شعبه انتخاب شده باشد؛ این یکی از خودِ دوره حساب
   * می‌شود، پس بلافاصله دیده می‌شود. مبنا آخرین جلسهٔ **دارای تاریخ** است — همان لنگری
   * که پروتکل با آن فاصله می‌سنجد.
   */
  const overdue = React.useMemo(() => {
    if (!course || course.status !== 'active') return null;

    const sessions  = course.sessions ?? [];
    const dated     = sessions.filter((s) => s.slot_start !== null);
    const remaining = sessions.filter((s) => s.status === 'planned').length;

    if (dated.length === 0 || remaining === 0) return null;

    const last = Math.max(...dated.map((s) => s.slot_start ?? 0));
    const days = Math.floor((Date.now() / 1000 - last) / 86400);

    return days > course.max_days ? days : null;
  }, [course]);

  /**
   * فاصلهٔ **واقعی** با جلسهٔ قبلی، نه فاصلهٔ پروتکل.
   *
   * پروتکل می‌گوید چه باید می‌شد؛ این می‌گوید چه شد. تفاوتشان همان چیزی است که نشان
   * می‌دهد دوره دارد کِش می‌آید — و بدون این ستون، اپراتور باید دو تاریخ را در ذهنش
   * تفریق کند.
   */
  const gapBefore = (session: CourseSessionRow): number | null => {
    const dated = (course?.sessions ?? [])
      .filter((s) => s.slot_start !== null)
      .sort((a, b) => (a.slot_start ?? 0) - (b.slot_start ?? 0));

    const index = dated.findIndex((s) => s.session_number === session.session_number);

    if (index <= 0) return null;

    return Math.round(((dated[index].slot_start ?? 0) - (dated[index - 1].slot_start ?? 0)) / 86400);
  };

  const columns: Column<CourseSessionRow>[] = [
    {
      key: 'session_number',
      header: 'جلسه',
      render: (s) => <span style={{ fontWeight: 600 }}>{s.session_number}</span>,
    },
    {
      key: 'status',
      header: 'وضعیت',
      render: (s) => (
        <span className={SESSION_STATUS[s.status].className}>
          <span className="bdot" />
          {SESSION_STATUS[s.status].label}
        </span>
      ),
    },
    {
      key: 'slot_start',
      header: 'تاریخ نوبت',
      render: (s) => (
        <span style={{ fontSize: 13 }}>{s.slot_start === null ? '—' : formatDate(s.slot_start)}</span>
      ),
    },
    {
      key: 'gap',
      header: 'فاصله با قبلی',
      render: (s) => {
        const gap = gapBefore(s);

        if (gap === null) return <span style={{ color: 'var(--text-3)' }}>—</span>;

        const tooLong = course !== undefined && gap > course.max_days;

        return (
          <span
            style={{ fontSize: 13, color: tooLong ? 'var(--warning)' : undefined }}
            title={tooLong ? `بیش از حداکثر ${formatNumber(course!.max_days)} روزِ پروتکل` : undefined}
          >
            {formatNumber(gap)} روز
          </span>
        );
      },
    },
    {
      key: 'params',
      header: 'پارامتر',
      render: (s) => (
        <span style={{ fontSize: 12, color: 'var(--text-2)' }}>
          {Object.entries(s.params).length === 0
            ? '—'
            : Object.entries(s.params)
                .map(([k, v]) => `${k}: ${v}`)
                .join('، ')}
        </span>
      ),
    },
    {
      key: 'completed_at',
      header: 'انجام‌شده در',
      render: (s) => (
        <span style={{ fontSize: 12, color: 'var(--text-3)' }}>
          {s.completed_at === null ? '—' : formatDate(s.completed_at)}
        </span>
      ),
    },
  ];

  return (
    <div className="fade-in">
      <PageHeader
        title={course ? `دورهٔ ${course.service_name}` : 'دورهٔ درمان'}
        description="پیشرفت دوره، جلسات و پیشنهاد تاریخ جلسهٔ بعدی."
        backTo="/admin/patients"
      />

      {course && (
        <div className="card card-pad" style={{ marginBottom: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
            <span style={{ fontSize: 15 }}>
              جلسهٔ <strong>{course.progress.completed}</strong> از {course.progress.total} انجام شده
            </span>
            <span style={{ fontSize: 13, color: 'var(--text-2)' }}>
              رزروشده: {course.progress.booked} · باقی‌مانده: {course.progress.planned}
            </span>
            <span style={{ fontSize: 12, color: 'var(--text-3)' }}>
              فاصله: حداقل {course.min_days} · ایده‌آل {course.ideal_days} · حداکثر {course.max_days} روز
            </span>
            {course.status !== 'active' && (
              <span className="badge red">
                <span className="bdot" />
                {course.status === 'completed' ? 'تمام‌شده' : 'رهاشده'}
              </span>
            )}
          </div>

          {/* پکیجی که کفاف جلسات باقی‌مانده را نمی‌دهد، دوره را باطل نمی‌کند — بقیه‌اش
              نقدی می‌شود. ولی باید قبل از جلسهٔ ششم دانسته شود، نه سرِ آن. */}
          {(course.package_shortfall ?? 0) > 0 && (
            <span
              style={{
                fontSize: 13,
                lineHeight: 1.8,
                color: 'var(--warning)',
                background: 'var(--warning-bg)',
                borderRadius: 'var(--r-sm)',
                padding: '8px 10px',
              }}
            >
              اعتبار پکیج برای {formatNumber(course.package_shortfall ?? 0)} جلسه کم می‌آید
              (مانده: {formatNumber(course.package_balance ?? 0)}). بقیهٔ جلسات با قیمت
              عادی حساب می‌شوند.
            </span>
          )}

          {overdue !== null && (
            <span
              style={{
                fontSize: 13,
                lineHeight: 1.8,
                color: 'var(--warning)',
                background: 'var(--warning-bg)',
                borderRadius: 'var(--r-sm)',
                padding: '8px 10px',
              }}
            >
              {formatNumber(overdue)} روز از آخرین جلسه گذشته — بیشتر از حداکثر{' '}
              {formatNumber(course.max_days)} روزِ پروتکل. جلسهٔ بعدی را دوباره زمان‌بندی کنید.
            </span>
          )}

          {course.abandon_reason && (
            <span style={{ fontSize: 13, color: 'var(--text-2)' }}>دلیل رهاکردن: {course.abandon_reason}</span>
          )}

          <div style={{ display: 'flex', alignItems: 'flex-end', gap: 10, flexWrap: 'wrap' }}>
            <div className="field-block" style={{ minWidth: 220, margin: 0 }}>
              <label>شعبه برای پیشنهاد وقت</label>
              <SearchableSelect
                value={branchUuid}
                onChange={(v) => setBranchUuid(String(v ?? ''))}
                options={branches.map((b) => ({ value: b.uuid, label: b.name || 'بدون نام' }))}
                placeholder="انتخاب شعبه"
              />
            </div>

            {/* رزرو گروهی پزشک لازم دارد؛ خودِ دوره پزشکی ندارد چون هر جلسه می‌تواند
                با پزشک دیگری باشد. */}
            {canManage && course.status === 'active' && (
              <div className="field-block" style={{ minWidth: 220, margin: 0 }}>
                <label>پزشک برای رزرو گروهی</label>
                <SearchableSelect
                  value={doctorUuid}
                  onChange={(v) => setDoctorUuid(String(v ?? ''))}
                  options={doctors.map((d) => ({ value: d.uuid, label: d.name }))}
                  placeholder="انتخاب پزشک"
                />
              </div>
            )}

            {canManage && course.status === 'active' && (
              <button
                type="button"
                className="btn primary sm"
                disabled={branchUuid === '' || doctorUuid === '' || bookAll.isPending}
                title={
                  branchUuid === '' || doctorUuid === ''
                    ? 'شعبه و پزشک را انتخاب کنید'
                    : 'همهٔ جلسات برنامه‌ریزی‌شده یکجا رزرو می‌شوند — همه یا هیچ'
                }
                onClick={() => bookAll.mutate({ branch_uuid: branchUuid, doctor_uuid: doctorUuid })}
              >
                رزرو همهٔ جلسات
              </button>
            )}

            {canManage && course.status === 'active' && (
              <button type="button" className="btn secondary sm" onClick={() => setAbandoning(true)}>
                رهاکردن دوره
              </button>
            )}
          </div>

          {suggestion && suggestion.session_number !== null && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>
              <span>
                جلسهٔ بعدی: <strong>{suggestion.session_number}</strong>
                {suggestion.ideal_at !== undefined && ` · تاریخ ایده‌آل ${formatDate(suggestion.ideal_at)}`}
              </span>
              {suggestion.range && (
                <span style={{ color: 'var(--text-3)', fontSize: 12 }}>
                  بازهٔ مجاز: {formatDate(suggestion.range.min)} تا {formatDate(suggestion.range.max)}
                </span>
              )}
              {suggestion.suggested_slots.length > 0 && (
                <span style={{ color: 'var(--text-2)' }}>
                  نزدیک‌ترین وقت‌ها:{' '}
                  {suggestion.suggested_slots.map((s) => formatDate(s.start)).join('، ')}
                </span>
              )}
              {/* ترجیح است نه الزام: موتور همان منبع را جلوتر می‌آورد ولی اگر آزاد نباشد
                  منبع دیگری می‌دهد. متن هم همین را می‌گوید تا انتظار اشتباه نسازد. */}
              {course.preferred_resource_name && (
                <span style={{ color: 'var(--text-3)', fontSize: 12 }}>
                  ترجیح دوره: {course.preferred_resource_name} — اگر آزاد نباشد منبع دیگری
                  پیشنهاد می‌شود.
                </span>
              )}
              {suggestion.warning && (
                <span style={{ color: 'var(--warning)' }}>{suggestion.warning}</span>
              )}
            </div>
          )}
        </div>
      )}

      <div style={{ overflowX: 'auto' }}>
        <DataTable
          columns={columns}
          data={course?.sessions ?? []}
          loading={loading}
          emptyMessage="این دوره جلسه‌ای ندارد"
        />
      </div>

      <ConfirmDialog
        open={abandoning}
        title="رهاکردن دوره"
        message="جلسات باقی‌مانده برنامه‌ریزی‌شده می‌مانند و دوره از فهرست فعال خارج می‌شود."
        confirmLabel="رهاکن"
        danger
        loading={abandon.isPending}
        onCancel={() => setAbandoning(false)}
        onConfirm={async () => {
          await abandon.mutateAsync(reason.trim() || 'رهاکردن دوره');
          setAbandoning(false);
        }}
      >
        <div className="field-block">
          <label htmlFor="abandon-reason">دلیل</label>
          <input
            id="abandon-reason"
            className="input"
            value={reason}
            onChange={(e) => setReason(e.target.value)}
            placeholder="مثلاً: انصراف بیمار"
          />
        </div>
      </ConfirmDialog>
    </div>
  );
}
