import { useEffect, useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import {
  ChevronLeftIcon, ChevronRightIcon, ClipboardDocumentListIcon,
  CpuChipIcon, MagnifyingGlassIcon, XMarkIcon,
} from '@heroicons/react/24/outline';
import { api } from '../../lib/api';
import type { ApiResponse } from '../../lib/api';
import StatusBadge from '../ui/StatusBadge';
import Pagination from '../ui/Pagination';
import NewAppointmentModal from '../appointments/NewAppointmentModal';
import { useResourceBookingServices } from '../../hooks/useResourceBookingServices';
import { useClinicContext } from '../../hooks/useClinicContext';
import { useUrlState } from '../../hooks/useUrlState';
import { formatDate, formatDateTime, formatNumber } from '../../lib/utils';
import type { TreatmentCaseSummary, SessionAreaRecord } from '../../types';

interface PlanSession {
  uuid: string;
  session_number: number;
  total_sessions: number;
  status: string;
  planned_at: number | null;
  is_estimate: boolean;
  appointment: { uuid: string; slot_start: number } | null;
  performed_by: { uuid: string; name: string } | null;
  areas?: SessionAreaRecord[];
}

interface PlanResponse {
  case: TreatmentCaseSummary & { patient_national_code: string | null };
  resource: { uuid: string; name: string } | null;
  sessions: PlanSession[];
}

const CASE_STATUS_LABEL: Record<TreatmentCaseSummary['status'], string> = {
  active:    'در جریان',
  completed: 'تمام شده',
  abandoned: 'رها شده',
};

const SESSION_STATUS_TEXT: Record<string, string> = {
  planned:     'برنامه‌ریزی شده',
  booked:      'زمان‌بندی شده',
  in_progress: 'در حال انجام',
  done:        'انجام شد',
  cancelled:   'لغو شده',
  no_show:     'غیبت',
};

const SETTLED = ['done', 'cancelled', 'no_show'];
const PAGE_SIZE = 8;

/** `planned_at` (ثانیه) → `YYYY-MM-DD` میلادی، همان چیزی که مودال می‌خواهد. */
function isoDay(ts: number): string {
  const d = new Date(ts * 1000);

  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}

/** جستجو روی همان چیزهایی که در کارت دیده می‌شوند، نه فیلدهای پنهان. */
function matches(s: PlanSession, serviceName: string, term: string): boolean {
  if (term === '') return true;

  return [
    serviceName,
    s.performed_by?.name ?? '',
    SESSION_STATUS_TEXT[s.status] ?? s.status,
    String(s.session_number),
    formatNumber(s.session_number),
    ...(s.areas ?? []).map((a) => a.area.name),
  ].join(' ').includes(term);
}

/**
 * دوره‌های درمانِ همین بیمار.
 *
 * دو نما دارد و نه یکی: فهرستِ کارتِ دوره‌ها، و با کلیک، جزئیاتِ همان دوره. یک دورهٔ
 * شصت‌جلسه‌ای بازشده کنار بقیه، صفحه را غیرقابل‌خواندن می‌کرد.
 *
 * انتخاب در URL می‌نشیند تا «بازگشت» مرورگر همان دوره را برگرداند.
 */
export default function PatientTreatmentTab({ recordUuid }: { recordUuid: string }) {
  const [urlState, setUrlState] = useUrlState({ case: '', view: 'sessions' });

  const { data, isLoading, isError, refetch } = useQuery({
    queryKey: ['patient-treatment-cases', recordUuid],
    queryFn: () => api.get<ApiResponse<TreatmentCaseSummary[]>>(
      `/api/v1/treatment-cases?record=${encodeURIComponent(recordUuid)}`,
    ),
    enabled: recordUuid !== '',
    staleTime: 30_000,
  });

  const cases    = data?.data ?? [];
  const selected = cases.find((c) => c.uuid === urlState.case) ?? null;

  if (isLoading) {
    return (
      <div style={{ display: 'grid', gap: 12, padding: '16px 0' }}>
        {[0, 1].map((i) => <div key={i} className="card" style={{ height: 108 }} />)}
      </div>
    );
  }

  if (isError) {
    return (
      <div className="card card-pad" style={{ display: 'grid', gap: 10, justifyItems: 'center', padding: 32 }}>
        <span style={{ fontSize: 13.5, color: 'var(--danger)' }}>خواندن دوره‌های این بیمار ناموفق بود.</span>
        <button type="button" className="btn secondary sm" onClick={() => refetch()}>تلاش دوباره</button>
      </div>
    );
  }

  if (cases.length === 0) {
    return (
      <div className="card card-pad" style={{ display: 'grid', gap: 8, justifyItems: 'center', padding: 40 }}>
        <ClipboardDocumentListIcon style={{ width: 40, height: 40, color: 'var(--text-3)' }} />
        <span style={{ fontSize: 13.5, color: 'var(--text-2)', textAlign: 'center', lineHeight: 1.9 }}>
          این بیمار دورهٔ درمان ندارد.
          <br />
          دوره وقتی ساخته می‌شود که نوبتِ سرویسی با «طول درمان» قطعی شود.
        </span>
      </div>
    );
  }

  if (selected !== null) {
    return (
      <CaseDetail
        summary={selected}
        view={urlState.view === 'upcoming' ? 'upcoming' : 'sessions'}
        onView={(v) => setUrlState({ view: v })}
        onBack={() => setUrlState({ case: '', view: 'sessions' })}
      />
    );
  }

  return (
    <div style={{
      display: 'grid', gap: 12, padding: '16px 0',
      gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
    }}>
      {cases.map((c) => (
        <CaseCard key={c.uuid} summary={c} onOpen={() => setUrlState({ case: c.uuid, view: 'sessions' })} />
      ))}
    </div>
  );
}

/** کارتِ خلاصهٔ یک دوره — کل کارت دکمه است، نه لینکی در گوشه‌اش. */
function CaseCard({ summary: c, onOpen }: { summary: TreatmentCaseSummary; onOpen: () => void }) {
  const percent = c.total_sessions > 0
    ? Math.round((c.completed_sessions / c.total_sessions) * 100)
    : 0;

  const operator = c.performed_by.length > 0
    ? c.performed_by.map((s) => s.name).join('، ')
    : c.assigned_staff.map((s) => s.name).join('، ');

  return (
    <button
      type="button"
      onClick={onOpen}
      className="card card-pad"
      style={{
        display: 'grid', gap: 10, textAlign: 'start', cursor: 'pointer',
        font: 'inherit', color: 'var(--text)', width: '100%',
      }}
    >
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        <strong style={{ fontSize: 14 }}>{c.service.name}</strong>
        <span className={`badge ${c.status === 'active' ? 'blue' : c.status === 'completed' ? 'green' : 'gray'}`}>
          <span className="bdot" />{CASE_STATUS_LABEL[c.status]}
        </span>
        <ChevronLeftIcon style={{ width: 16, height: 16, marginInlineStart: 'auto', color: 'var(--text-3)' }} />
      </div>

      <div style={{ display: 'grid', gap: 4, fontSize: 12.5, color: 'var(--text-2)' }}>
        <span>{formatNumber(c.completed_sessions)} از {formatNumber(c.total_sessions)} جلسه انجام شده</span>
        <span>شروع: {formatDate(c.opened_at)}</span>
        {c.supervisor && <span>پزشک ناظر: {c.supervisor.name}</span>}
        {operator !== '' && <span>پرسنل: {operator}</span>}
      </div>

      <div
        role="progressbar"
        aria-valuenow={c.completed_sessions}
        aria-valuemin={0}
        aria-valuemax={c.total_sessions}
        aria-label={`پیشرفت دوره: ${c.completed_sessions} از ${c.total_sessions}`}
        style={{ height: 6, borderRadius: 999, background: 'var(--surface-3)', overflow: 'hidden' }}
      >
        <div style={{
          width: `${percent}%`, height: '100%', borderRadius: 999,
          background: c.status === 'completed' ? 'var(--success)' : 'var(--primary)',
        }} />
      </div>
    </button>
  );
}

function CaseDetail({ summary, view, onView, onBack }: {
  summary: TreatmentCaseSummary;
  view: 'sessions' | 'upcoming';
  onView: (v: 'sessions' | 'upcoming') => void;
  onBack: () => void;
}) {
  const [term, setTerm] = useState('');
  const [page, setPage] = useState(1);
  useEffect(() => setPage(1), [term, view]);

  const { data, isLoading, isError, refetch } = useQuery({
    queryKey: ['treatment-case-plan', summary.uuid],
    queryFn: () => api.get<ApiResponse<PlanResponse>>(`/api/v1/treatment-case/${summary.uuid}/plan`),
    staleTime: 30_000,
  });

  const all      = data?.data?.sessions ?? [];
  const scoped   = view === 'upcoming' ? all.filter((s) => !SETTLED.includes(s.status)) : all;
  const sessions = scoped.filter((s) => matches(s, summary.service.name, term.trim()));
  const paged    = sessions.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

  const upcomingCount = all.filter((s) => !SETTLED.includes(s.status)).length;

  return (
    <div style={{ display: 'grid', gap: 14, padding: '16px 0' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
        <button type="button" className="btn secondary sm" onClick={onBack}>
          <ChevronRightIcon style={{ width: 15, height: 15 }} />
          همهٔ دوره‌ها
        </button>
        <strong style={{ fontSize: 14 }}>{summary.service.name}</strong>
        <span className={`badge ${summary.status === 'active' ? 'blue' : summary.status === 'completed' ? 'green' : 'gray'}`}>
          <span className="bdot" />{CASE_STATUS_LABEL[summary.status]}
        </span>
        <span style={{ fontSize: 12.5, color: 'var(--text-3)' }}>
          {formatNumber(summary.completed_sessions)} از {formatNumber(summary.total_sessions)} جلسه
        </span>
      </div>

      <div className="seg" style={{ alignSelf: 'start' }}>
        {([['sessions', 'جزئیات دوره'], ['upcoming', `نوبت‌های آینده (${formatNumber(upcomingCount)})`]] as const).map(
          ([v, label]) => (
            <button
              key={v}
              type="button"
              className={view === v ? 'on' : ''}
              aria-pressed={view === v}
              onClick={() => onView(v)}
            >
              {label}
            </button>
          ),
        )}
      </div>

      <div className="field" style={{ maxWidth: 420 }}>
        <MagnifyingGlassIcon style={{ width: 16, height: 16, flexShrink: 0, color: 'var(--text-3)' }} />
        <input
          value={term}
          onChange={(e) => setTerm(e.target.value)}
          placeholder="پرسنل، وضعیت، ناحیه یا شمارهٔ جلسه"
          aria-label="جستجوی جلسات"
        />
        {term !== '' && (
          <button type="button" className="mini-btn" aria-label="پاک کردن جستجو" onClick={() => setTerm('')}>
            <XMarkIcon style={{ width: 15, height: 15 }} />
          </button>
        )}
      </div>

      {isLoading ? (
        <div style={{ display: 'grid', gap: 10 }}>
          {[0, 1].map((i) => <div key={i} className="card" style={{ height: 72 }} />)}
        </div>
      ) : isError ? (
        <div className="card card-pad" style={{ display: 'grid', gap: 10, justifyItems: 'start' }}>
          <span style={{ fontSize: 13, color: 'var(--danger)' }}>خواندن تقویم این دوره ناموفق بود.</span>
          <button type="button" className="btn secondary sm" onClick={() => refetch()}>تلاش دوباره</button>
        </div>
      ) : sessions.length === 0 ? (
        <div className="card card-pad" style={{ fontSize: 13, color: 'var(--text-3)' }}>
          {term !== ''
            ? `جلسه‌ای با «${term}» پیدا نشد.`
            : view === 'upcoming'
              ? 'جلسهٔ باقی‌مانده‌ای در این دوره نیست.'
              : 'این دوره جلسه‌ای ندارد.'}
        </div>
      ) : (
        <div style={{ display: 'grid', gap: 10 }}>
          {paged.map((s) => (
            <SessionCard
              key={s.uuid}
              session={s}
              summary={summary}
              resource={data?.data?.resource ?? null}
              nationalCode={data?.data?.case.patient_national_code ?? null}
            />
          ))}
          <Pagination page={page} total={sessions.length} limit={PAGE_SIZE} onPageChange={setPage} />
        </div>
      )}
    </div>
  );
}

function SessionCard({ session: s, summary, resource, nationalCode }: {
  session: PlanSession;
  summary: TreatmentCaseSummary;
  resource: { uuid: string; name: string } | null;
  nationalCode: string | null;
}) {
  const [booking, setBooking] = useState(false);
  const qc = useQueryClient();
  const clinicUuid = useClinicContext();

  const supervisor = summary.supervisor;
  // سرویس‌ها از تقویم منبع می‌آیند نه از برنامهٔ پزشک — دورهٔ لیزر روی دستگاه رزرو
  // می‌شود و برنامهٔ پزشکِ ناظر سرویسی برای انتخاب ندارد.
  const { services } = useResourceBookingServices(booking ? resource?.uuid : null);

  const bookable = !SETTLED.includes(s.status) && s.appointment === null && summary.status === 'active';
  const areas    = s.areas ?? [];

  return (
    <div className="card card-pad" style={{ display: 'grid', gap: 8 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
        <strong style={{ fontSize: 13.5 }}>
          جلسهٔ {formatNumber(s.session_number)} از {formatNumber(s.total_sessions)}
        </strong>
        <StatusBadge type="treatment-session" value={s.status} />
        <span style={{ fontSize: 12.5, color: 'var(--text-2)' }}>
          {s.planned_at === null ? '—' : formatDateTime(s.planned_at)}
        </span>
        {/* تخمین با واقعیت یکی نیست و باید در خودِ کارت معلوم باشد. */}
        {s.is_estimate && <span className="badge gray" style={{ fontSize: 11 }}>تخمینی</span>}
        {s.performed_by && (
          <span style={{ fontSize: 12.5, color: 'var(--text-3)' }}>پرسنل: {s.performed_by.name}</span>
        )}
      </div>

      {/* آنچه واقعاً انجام شد: ناحیه، دستگاه و خوانده‌هایش. */}
      {areas.length > 0 && (
        <div style={{ display: 'grid', gap: 6 }}>
          {areas.map((a) => (
            <div key={a.uuid} style={{ display: 'flex', gap: 10, flexWrap: 'wrap', fontSize: 12.5 }}>
              <span style={{ fontWeight: 600 }}>{a.area.name}</span>
              <StatusBadge type="treatment-area" value={a.status} />
              {a.resource && (
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, color: 'var(--text-3)' }}>
                  <CpuChipIcon style={{ width: 13, height: 13 }} />
                  {a.resource.name}
                </span>
              )}
              {a.parameters && Object.entries(a.parameters).map(([k, v]) => (
                <span key={k} style={{ color: 'var(--text-3)' }}>
                  {k}: <b style={{ color: 'var(--text-2)' }}>{String(v)}</b>
                </span>
              ))}
              {a.note && <span style={{ color: 'var(--text-3)' }}>یادداشت: {a.note}</span>}
            </div>
          ))}
        </div>
      )}

      {bookable && (
        /* بدون دستگاه، فرم سرویسی برای انتخاب ندارد؛ دکمهٔ خاموشِ بی‌توضیح بدتر از
           نبودنش است، پس دلیلش نوشته می‌شود. */
        resource === null ? (
          <span style={{ fontSize: 12.5, color: 'var(--warning)' }}>
            هنوز هیچ جلسه‌ای از این دوره روی دستگاهی انجام نشده — نوبت را از صفحهٔ نوبت‌ها ثبت کنید.
          </span>
        ) : (
          <button
            type="button"
            className="btn primary sm"
            style={{ justifySelf: 'start' }}
            onClick={() => setBooking(true)}
          >
            ثبت نوبت این جلسه
          </button>
        )
      )}

      {booking && resource && (
        <NewAppointmentModal
          slot={{
            start: 0, end: 0, start_time: '', end_time: '',
            doctor_uuid: supervisor?.uuid ?? '', doctor_name: supervisor?.name ?? '',
          }}
          resource={resource}
          services={services}
          date={s.planned_at === null ? undefined : isoDay(s.planned_at)}
          clinicUuid={clinicUuid}
          treatmentSessionUuid={s.uuid}
          patient={{
            name: summary.patient.name,
            mobile: summary.patient.mobile,
            national_code: nationalCode,
          }}
          onClose={() => setBooking(false)}
          onSuccess={() => {
            qc.invalidateQueries({ queryKey: ['treatment-case-plan', summary.uuid] });
            qc.invalidateQueries({ queryKey: ['patient-treatment-cases'] });
            qc.invalidateQueries({ queryKey: ['patient-appointments'] });
          }}
        />
      )}
    </div>
  );
}
