'use client';

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '@/lib/api';
import type {
  Absence,
  VacationBalance,
  AbsenceQueryParams,
  CreateAbsenceDto,
  AbsenceCalendarEntry,
} from '@/types/hr';

// =============================================================================
// QUERY KEY FACTORY
// =============================================================================

export const absenceKeys = {
  all: ['absences'] as const,
  lists: () => [...absenceKeys.all, 'list'] as const,
  list: (params?: AbsenceQueryParams) => [...absenceKeys.lists(), params] as const,
  pending: (departmentId?: string) =>
    [...absenceKeys.all, 'pending', departmentId] as const,
  detail: (id: string) => [...absenceKeys.all, 'detail', id] as const,
  balance: (employeeId: string, year: number) =>
    [...absenceKeys.all, 'balance', employeeId, year] as const,
  calendar: (year: number, month: number, departmentId?: string) =>
    [...absenceKeys.all, 'calendar', year, month, departmentId] as const,
  myRequests: () => [...absenceKeys.all, 'my-requests'] as const,
};

// =============================================================================
// API FUNCTIONS
// =============================================================================

async function fetchAbsences(params?: AbsenceQueryParams): Promise<Absence[]> {
  return api.get('/hr/absences', {
    params: params as Record<string, string | number | boolean | undefined>,
  });
}

async function fetchPendingRequests(departmentId?: string): Promise<Absence[]> {
  return api.get('/hr/absences/pending', {
    params: departmentId ? { departmentId } : undefined,
  });
}

async function fetchAbsenceById(id: string): Promise<Absence> {
  return api.get(`/hr/absences/${id}`);
}

async function fetchVacationBalance(
  employeeId: string,
  year: number
): Promise<VacationBalance> {
  return api.get(`/hr/absences/balance/${employeeId}`, { params: { year } });
}

async function fetchCalendarEntries(
  year: number,
  month: number,
  departmentId?: string
): Promise<AbsenceCalendarEntry[]> {
  return api.get('/hr/absences/calendar', {
    params: { year, month, departmentId } as Record<string, string | number | boolean | undefined>,
  });
}

async function createAbsenceRequest(dto: CreateAbsenceDto): Promise<Absence> {
  return api.post('/hr/absences', dto);
}

async function approveAbsence(id: string): Promise<Absence> {
  return api.post(`/hr/absences/${id}/approve`);
}

async function rejectAbsence(id: string, reason: string): Promise<Absence> {
  return api.post(`/hr/absences/${id}/reject`, { reason });
}

async function cancelAbsence(id: string): Promise<Absence> {
  return api.delete(`/hr/absences/${id}`);
}

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

/**
 * Fetch absences with optional filters
 */
export function useAbsences(params?: AbsenceQueryParams) {
  return useQuery({
    queryKey: absenceKeys.list(params),
    queryFn: () => fetchAbsences(params),
    staleTime: 30 * 1000,
  });
}

/**
 * Fetch my own absence requests
 */
export function useMyAbsenceRequests() {
  return useQuery({
    queryKey: absenceKeys.myRequests(),
    queryFn: () => fetchAbsences({ employeeId: 'current' }),
    staleTime: 30 * 1000,
  });
}

/**
 * Fetch pending requests for approval (managers)
 */
export function usePendingAbsenceRequests(departmentId?: string) {
  return useQuery({
    queryKey: absenceKeys.pending(departmentId),
    queryFn: () => fetchPendingRequests(departmentId),
    staleTime: 30 * 1000,
  });
}

/**
 * Fetch single absence by ID
 */
export function useAbsence(id: string) {
  return useQuery({
    queryKey: absenceKeys.detail(id),
    queryFn: () => fetchAbsenceById(id),
    enabled: !!id,
    staleTime: 30 * 1000,
  });
}

/**
 * Fetch vacation balance for an employee
 */
export function useVacationBalance(employeeId: string, year: number) {
  return useQuery({
    queryKey: absenceKeys.balance(employeeId, year),
    queryFn: () => fetchVacationBalance(employeeId, year),
    enabled: !!employeeId,
    staleTime: 60 * 1000,
  });
}

/**
 * Fetch calendar entries for absence overview
 */
export function useAbsenceCalendar(year: number, month: number, departmentId?: string) {
  return useQuery({
    queryKey: absenceKeys.calendar(year, month, departmentId),
    queryFn: () => fetchCalendarEntries(year, month, departmentId),
    staleTime: 60 * 1000,
  });
}

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

/**
 * Create a new absence request
 */
export function useCreateAbsenceRequest() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: createAbsenceRequest,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: absenceKeys.lists() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.myRequests() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.pending() });
    },
  });
}

/**
 * Approve an absence request
 */
export function useApproveAbsence() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: approveAbsence,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: absenceKeys.lists() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.pending() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.all });
    },
  });
}

/**
 * Reject an absence request
 */
export function useRejectAbsence() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, reason }: { id: string; reason: string }) =>
      rejectAbsence(id, reason),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: absenceKeys.lists() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.pending() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.all });
    },
  });
}

/**
 * Cancel own absence request
 */
export function useCancelAbsence() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: cancelAbsence,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: absenceKeys.lists() });
      queryClient.invalidateQueries({ queryKey: absenceKeys.myRequests() });
    },
  });
}
