/**
 * React Query Hooks - Appointments
 * Hooks para gerenciamento de consultas com cache inteligente
 * @version 1.0
 */

import {
  useQuery,
  useMutation,
  useQueryClient,
  UseQueryOptions,
} from "@tanstack/react-query";
import { appointmentService } from "../services";
import type {
  Appointment,
  CreateAppointmentInput,
  UpdateAppointmentInput,
  AppointmentFilters,
} from "../services/appointments/types";
import toast from "react-hot-toast";

// ============================================================================
// QUERY KEYS
// ============================================================================

export const appointmentKeys = {
  all: ["appointments"] as const,
  lists: () => [...appointmentKeys.all, "list"] as const,
  list: (filters?: AppointmentFilters) =>
    [...appointmentKeys.lists(), filters] as const,
  details: () => [...appointmentKeys.all, "detail"] as const,
  detail: (id: string) => [...appointmentKeys.details(), id] as const,
  byDoctor: (doctorId: string) =>
    [...appointmentKeys.all, "doctor", doctorId] as const,
  byPatient: (patientId: string) =>
    [...appointmentKeys.all, "patient", patientId] as const,
  waitingRoom: (doctorId: string) =>
    [...appointmentKeys.all, "waitingRoom", doctorId] as const,
};

// ============================================================================
// QUERY HOOKS
// ============================================================================

/**
 * Hook para buscar lista de consultas
 * @param filters - Filtros de busca
 * @param options - Opções adicionais do useQuery
 */
export function useAppointments(
  filters?: AppointmentFilters,
  options?: Omit<UseQueryOptions<Appointment[]>, "queryKey" | "queryFn">
) {
  return useQuery({
    queryKey: appointmentKeys.list(filters),
    queryFn: async () => {
      return await appointmentService.list(filters);
    },
    ...options,
  });
}

/**
 * Hook para buscar uma consulta específica
 * @param id - ID da consulta
 */
export function useAppointment(id: string | undefined) {
  return useQuery({
    queryKey: appointmentKeys.detail(id!),
    queryFn: async () => {
      if (!id) throw new Error("ID é obrigatório");
      return await appointmentService.getById(id);
    },
    enabled: !!id,
  });
}

/**
 * Hook para buscar consultas de um médico
 * @param doctorId - ID do médico
 */
export function useAppointmentsByDoctor(doctorId: string | undefined) {
  return useAppointments({ doctor_id: doctorId }, { enabled: !!doctorId });
}

/**
 * Hook para buscar consultas de um paciente
 * @param patientId - ID do paciente
 */
export function useAppointmentsByPatient(patientId: string | undefined) {
  return useAppointments({ patient_id: patientId }, { enabled: !!patientId });
}

// ============================================================================
// MUTATION HOOKS
// ============================================================================

/**
 * Hook para criar nova consulta
 */
export function useCreateAppointment() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (data: CreateAppointmentInput) => {
      return await appointmentService.create(data);
    },
    onSuccess: (data) => {
      // Invalidar todas as listas de consultas
      queryClient.invalidateQueries({ queryKey: appointmentKeys.lists() });

      // Invalidar consultas do médico e paciente específicos
      if (data?.doctor_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byDoctor(data.doctor_id),
        });
      }
      if (data?.patient_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byPatient(data.patient_id),
        });
      }

      toast.success("Consulta agendada com sucesso!");
    },
    onError: (error: Error) => {
      toast.error(`Erro ao agendar: ${error.message}`);
    },
  });
}

/**
 * Hook para atualizar consulta
 */
export function useUpdateAppointment() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (data: UpdateAppointmentInput & { id: string }) => {
      return await appointmentService.update(data.id, data);
    },
    onMutate: async (variables) => {
      // Optimistic update
      await queryClient.cancelQueries({
        queryKey: appointmentKeys.detail(variables.id),
      });

      const previousAppointment = queryClient.getQueryData<Appointment>(
        appointmentKeys.detail(variables.id)
      );

      return { previousAppointment };
    },
    onSuccess: (data, variables) => {
      // Invalidar queries relacionadas
      queryClient.invalidateQueries({ queryKey: appointmentKeys.lists() });
      queryClient.invalidateQueries({
        queryKey: appointmentKeys.detail(variables.id),
      });

      if (data?.doctor_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byDoctor(data.doctor_id),
        });
      }
      if (data?.patient_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byPatient(data.patient_id),
        });
      }

      toast.success("Consulta atualizada com sucesso!");
    },
    onError: (error: Error, variables, context) => {
      // Rollback em caso de erro
      if (context?.previousAppointment) {
        queryClient.setQueryData(
          appointmentKeys.detail(variables.id),
          context.previousAppointment
        );
      }
      toast.error(`Erro ao atualizar: ${error.message}`);
    },
  });
}

/**
 * Hook para cancelar consulta
 */
export function useCancelAppointment() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id }: { id: string; reason?: string }) => {
      // Usa update para cancelar
      return await appointmentService.update(id, { status: "cancelled" });
    },
    onSuccess: (data, variables) => {
      queryClient.invalidateQueries({ queryKey: appointmentKeys.lists() });
      queryClient.invalidateQueries({
        queryKey: appointmentKeys.detail(variables.id),
      });

      if (data?.doctor_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byDoctor(data.doctor_id),
        });
      }
      if (data?.patient_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byPatient(data.patient_id),
        });
      }

      toast.success("Consulta cancelada com sucesso");
    },
    onError: (error: Error) => {
      toast.error(`Erro ao cancelar: ${error.message}`);
    },
  });
}

/**
 * Hook para check-in de paciente
 */
export function useCheckInAppointment() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (appointmentId: string) => {
      return await appointmentService.update(appointmentId, {
        status: "checked_in",
      });
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: appointmentKeys.lists() });

      if (data?.doctor_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.waitingRoom(data.doctor_id),
        });
      }

      toast.success("Check-in realizado com sucesso!");
    },
    onError: (error: Error) => {
      toast.error(`Erro no check-in: ${error.message}`);
    },
  });
}

/**
 * Hook para confirmação 1-clique de consulta
 * Atualiza status para confirmed e envia notificação automática
 */
export function useConfirmAppointment() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({
      appointmentId,
      patientPhone,
      patientName,
      scheduledAt,
    }: {
      appointmentId: string;
      patientPhone?: string;
      patientName?: string;
      scheduledAt?: string;
    }) => {
      // 1. Atualizar status para confirmed
      const updated = await appointmentService.update(appointmentId, {
        status: "confirmed",
      });

      // 2. Enviar notificação automática (se houver telefone)
      if (patientPhone && patientName && scheduledAt) {
        try {
          // Importa notificationService dinamicamente para evitar circular dependency
          const { notificationService } = await import("../services");
          await notificationService.sendAppointmentReminder(
            appointmentId,
            patientPhone,
            patientName,
            scheduledAt
          );
        } catch (error) {
          console.warn(
            "Erro ao enviar notificação (não bloqueia confirmação):",
            error
          );
        }
      }

      return updated;
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: appointmentKeys.lists() });

      if (data?.doctor_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byDoctor(data.doctor_id),
        });
      }
      if (data?.patient_id) {
        queryClient.invalidateQueries({
          queryKey: appointmentKeys.byPatient(data.patient_id),
        });
      }

      toast.success("✅ Consulta confirmada! Notificação enviada ao paciente.");
    },
    onError: (error: Error) => {
      toast.error(`Erro ao confirmar: ${error.message}`);
    },
  });
}

// ============================================================================
// UTILITY HOOKS
// ============================================================================

/**
 * Hook para prefetch de consultas (otimização)
 */
export function usePrefetchAppointments() {
  const queryClient = useQueryClient();

  return (filters?: AppointmentFilters) => {
    queryClient.prefetchQuery({
      queryKey: appointmentKeys.list(filters),
      queryFn: async () => {
        return await appointmentService.list(filters);
      },
    });
  };
}
