import { useMutation, useQuery } from '@tanstack/react-query';
import { toast } from 'sonner';
import { api, ApiError, type ApiResponse } from '../lib/api';

/**
 * جستجوی وقت، رزرو موقت و ثبت نهایی در حالت منبع‌محور.
 *
 * سه عمل جدا هستند و باید جدا بمانند: بین «دیدن وقت» و «گرفتنش» صندلی هنوز آزاد است،
 * و بین «گرفتن» و «ثبت» یک مهلت وجود دارد که اگر نگذرد، ظرفیت برای همیشه قفل می‌ماند.
 */
export interface ResourceRef {
  uuid: string;
  name: string;
}

export type SlotAssignment = Record<string, ResourceRef[]>;

export interface AvailableSlot {
  start: number;
  end: number;
  assignment: SlotAssignment;
}

export interface PlanSegment {
  sequence: number;
  name: string;
  offset_minutes: number;
  duration_minutes: number;
  patient_present: boolean;
  requirements: { role: string; role_name: string; count: number }[];
}

export interface AvailabilityResult {
  plan: { total_minutes: number; segments: PlanSegment[] };
  slots: AvailableSlot[];
  /** خالی بودن فهرست خطا نیست؛ این می‌گوید چرا خالی است. */
  reason: string | null;
}

export interface HoldResult {
  hold_uuid: string;
  starts_at: number;
  ends_at: number;
  expires_at: number;
  confirmed: boolean;
  assignment: SlotAssignment;
}

export const REASON_LABELS: Record<string, string> = {
  no_capacity_in_range: 'در این بازه هیچ ظرفیتی نیست — بازه را بزرگ‌تر کنید یا شعبهٔ دیگری را امتحان کنید.',
  no_working_hours: 'شعبه در این بازه ساعت کاری ندارد.',
  no_eligible_resource: 'هیچ منبعی شرایط بخش‌های این خدمت را ندارد.',
};

function fail(e: unknown, fallback: string) {
  toast.error(e instanceof ApiError ? e.message : fallback);
}

export function useAvailabilitySearch(
  params: { serviceUuid: string; branchUuid: string; from: number; to: number; stepMinutes?: number },
  enabled: boolean,
) {
  const query = useQuery({
    queryKey: ['resource-availability', params],
    queryFn: () =>
      api.post<ApiResponse<AvailabilityResult>>('/api/v1/appointment-availability', {
        service_uuid: params.serviceUuid,
        branch_uuid: params.branchUuid,
        from: params.from,
        to: params.to,
        ...(params.stepMinutes ? { step_minutes: params.stepMinutes } : {}),
      }),
    enabled: enabled && !!params.serviceUuid && !!params.branchUuid,
    retry: false,
  });

  return {
    result: query.data?.data,
    loading: query.isFetching,
    error: query.error,
    refetch: query.refetch,
  };
}

export function useHold() {
  const create = useMutation({
    mutationFn: (body: {
      service_uuid: string;
      branch_uuid: string;
      start: number;
      assignment: Record<string, string[]>;
      item_uuids?: string[];
      patient_gender?: string;
    }) => api.post<ApiResponse<HoldResult>>('/api/v1/appointment-hold', body),
    // ۴۰۹ یعنی همین لحظه کس دیگری گرفت — پیام سرور دقیقاً همین را می‌گوید.
    onError: (e) => fail(e, 'گرفتن این زمان ناموفق بود'),
  });

  const release = useMutation({
    mutationFn: (uuid: string) => api.delete<ApiResponse<null>>(`/api/v1/appointment-hold/${uuid}`),
    onSuccess: () => toast.success('رزرو موقت آزاد شد'),
    onError: (e) => fail(e, 'آزادسازی ناموفق بود'),
  });

  const confirm = useMutation({
    mutationFn: (body: { hold_uuid: string; doctor_uuid: string; patient_uuid?: string }) =>
      api.post<ApiResponse<{ uuid: string }>>('/api/v1/appointment-confirm', body),
    onSuccess: () => toast.success('نوبت ثبت شد'),
    onError: (e) => fail(e, 'ثبت نهایی ناموفق بود'),
  });

  /**
   * جابه‌جایی: رزرو موقتِ زمان تازه از قبل گرفته شده و اینجا فقط تأیید می‌شود.
   *
   * عمداً از `confirm` جداست — سرور در همین یک درخواست زمان قدیم را هم آزاد می‌کند، پس
   * لغو دستی پیش از رزرو یعنی پنجره‌ای که در آن بیمار اصلاً نوبت ندارد.
   */
  const rebook = useMutation({
    mutationFn: ({ appointmentUuid, holdUuid }: { appointmentUuid: string; holdUuid: string }) =>
      api.post<ApiResponse<{ appointment_uuid: string; starts_at: number }>>(
        `/api/v1/appointment/${appointmentUuid}/rebook`,
        { hold_uuid: holdUuid },
      ),
    onSuccess: () => toast.success('نوبت جابه‌جا شد'),
    onError: (e) => fail(e, 'جابه‌جایی نوبت ناموفق بود'),
  });

  return { create, release, confirm, rebook };
}

export interface AppointmentSegmentRow {
  sequence: number;
  name: string;
  starts_at: number;
  ends_at: number;
  duration_minutes: number;
  patient_present: boolean;
}

/** فهرست خالی یعنی نوبت اسلاتی است، نه اینکه چیزی خراب باشد. */
export function useAppointmentSegments(uuid: string | undefined) {
  const query = useQuery({
    queryKey: ['appointment-segments', uuid],
    queryFn: () =>
      api.get<ApiResponse<AppointmentSegmentRow[]>>(`/api/v1/appointment/${uuid}/segments`),
    enabled: !!uuid,
  });

  const rows = query.data?.data;

  return { segments: Array.isArray(rows) ? rows : [], loading: query.isLoading };
}
