/**
 * Time Block Management Hooks
 *
 * Provides hooks for managing time blocks and holidays.
 * Time blocks allow businesses to block off time for closures, holidays,
 * resource unavailability, and recurring patterns.
 */

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import apiClient from '../api/client';
import {
  TimeBlock,
  TimeBlockListItem,
  BlockedDate,
  Holiday,
  TimeBlockConflictCheck,
  MyBlocksResponse,
  BlockType,
  RecurrenceType,
  RecurrencePattern,
} from '../types';

// =============================================================================
// Interfaces
// =============================================================================

export interface TimeBlockFilters {
  level?: 'business' | 'resource';
  resource_id?: string;
  block_type?: BlockType;
  recurrence_type?: RecurrenceType;
  is_active?: boolean;
}

export interface BlockedDatesParams {
  start_date: string;
  end_date: string;
  resource_id?: string;
  include_business?: boolean;
}

export interface CreateTimeBlockData {
  title: string;
  description?: string;
  resource?: string | null;
  block_type: BlockType;
  recurrence_type: RecurrenceType;
  start_date?: string;
  end_date?: string;
  all_day?: boolean;
  start_time?: string;
  end_time?: string;
  recurrence_pattern?: RecurrencePattern;
  recurrence_start?: string;
  recurrence_end?: string;
}

export interface CheckConflictsData {
  recurrence_type: RecurrenceType;
  recurrence_pattern?: RecurrencePattern;
  start_date?: string;
  end_date?: string;
  resource_id?: string | null;
  all_day?: boolean;
  start_time?: string;
  end_time?: string;
}

// =============================================================================
// Time Block Hooks
// =============================================================================

/**
 * Hook to fetch time blocks with optional filters
 */
export const useTimeBlocks = (filters?: TimeBlockFilters) => {
  return useQuery<TimeBlockListItem[]>({
    queryKey: ['time-blocks', filters],
    queryFn: async () => {
      const params = new URLSearchParams();
      if (filters?.level) params.append('level', filters.level);
      if (filters?.resource_id) params.append('resource_id', filters.resource_id);
      if (filters?.block_type) params.append('block_type', filters.block_type);
      if (filters?.recurrence_type) params.append('recurrence_type', filters.recurrence_type);
      if (filters?.is_active !== undefined) params.append('is_active', String(filters.is_active));

      const { data } = await apiClient.get(`/time-blocks/?${params}`);
      return data.map((block: any) => ({
        ...block,
        id: String(block.id),
        resource: block.resource ? String(block.resource) : null,
      }));
    },
  });
};

/**
 * Hook to get a single time block
 */
export const useTimeBlock = (id: string) => {
  return useQuery<TimeBlock>({
    queryKey: ['time-blocks', id],
    queryFn: async () => {
      const { data } = await apiClient.get(`/time-blocks/${id}/`);
      return {
        ...data,
        id: String(data.id),
        resource: data.resource ? String(data.resource) : null,
      };
    },
    enabled: !!id,
  });
};

/**
 * Hook to get blocked dates for calendar visualization
 */
export const useBlockedDates = (params: BlockedDatesParams) => {
  return useQuery<BlockedDate[]>({
    queryKey: ['blocked-dates', params],
    queryFn: async () => {
      const queryParams = new URLSearchParams({
        start_date: params.start_date,
        end_date: params.end_date,
      });
      if (params.resource_id) queryParams.append('resource_id', params.resource_id);
      if (params.include_business !== undefined) {
        queryParams.append('include_business', String(params.include_business));
      }

      const url = `/time-blocks/blocked_dates/?${queryParams}`;
      const { data } = await apiClient.get(url);

      return data.blocked_dates.map((block: any) => ({
        ...block,
        resource_id: block.resource_id ? String(block.resource_id) : null,
        time_block_id: String(block.time_block_id),
      }));
    },
    enabled: !!params.start_date && !!params.end_date,
  });
};

/**
 * Hook to get time blocks for the current staff member
 */
export const useMyBlocks = () => {
  return useQuery<MyBlocksResponse>({
    queryKey: ['my-blocks'],
    queryFn: async () => {
      const { data } = await apiClient.get('/time-blocks/my_blocks/');
      return {
        business_blocks: data.business_blocks.map((b: any) => ({
          ...b,
          id: String(b.id),
          resource: b.resource ? String(b.resource) : null,
        })),
        my_blocks: data.my_blocks.map((b: any) => ({
          ...b,
          id: String(b.id),
          resource: b.resource ? String(b.resource) : null,
        })),
        resource_id: data.resource_id ? String(data.resource_id) : null,
        resource_name: data.resource_name,
        can_self_approve: data.can_self_approve,
      };
    },
  });
};

/**
 * Hook to create a time block
 */
export const useCreateTimeBlock = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (blockData: CreateTimeBlockData) => {
      const payload = {
        ...blockData,
        resource: blockData.resource ? parseInt(blockData.resource) : null,
      };
      const { data } = await apiClient.post('/time-blocks/', payload);
      return data;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['time-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['blocked-dates'] });
      queryClient.invalidateQueries({ queryKey: ['my-blocks'] });
    },
  });
};

/**
 * Hook to update a time block
 */
export const useUpdateTimeBlock = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, updates }: { id: string; updates: Partial<CreateTimeBlockData> }) => {
      const payload: any = { ...updates };
      if (updates.resource !== undefined) {
        payload.resource = updates.resource ? parseInt(updates.resource) : null;
      }
      const { data } = await apiClient.patch(`/time-blocks/${id}/`, payload);
      return data;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['time-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['blocked-dates'] });
      queryClient.invalidateQueries({ queryKey: ['my-blocks'] });
    },
  });
};

/**
 * Hook to delete a time block
 */
export const useDeleteTimeBlock = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (id: string) => {
      await apiClient.delete(`/time-blocks/${id}/`);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['time-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['blocked-dates'] });
      queryClient.invalidateQueries({ queryKey: ['my-blocks'] });
    },
  });
};

/**
 * Hook to toggle a time block's active status
 */
export const useToggleTimeBlock = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (id: string) => {
      const { data } = await apiClient.post(`/time-blocks/${id}/toggle/`);
      return data;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['time-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['blocked-dates'] });
      queryClient.invalidateQueries({ queryKey: ['my-blocks'] });
    },
  });
};

// =============================================================================
// Time Block Approval Hooks
// =============================================================================

export interface PendingReviewsResponse {
  count: number;
  pending_blocks: TimeBlockListItem[];
}

/**
 * Hook to fetch pending time block reviews (for managers/owners)
 */
export const usePendingReviews = () => {
  return useQuery<PendingReviewsResponse>({
    queryKey: ['time-block-pending-reviews'],
    queryFn: async () => {
      const { data } = await apiClient.get('/time-blocks/pending_reviews/');
      return {
        count: data.count,
        pending_blocks: data.pending_blocks.map((b: any) => ({
          ...b,
          id: String(b.id),
          resource: b.resource ? String(b.resource) : null,
        })),
      };
    },
  });
};

/**
 * Hook to approve a time block
 */
export const useApproveTimeBlock = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, notes }: { id: string; notes?: string }) => {
      const { data } = await apiClient.post(`/time-blocks/${id}/approve/`, { notes });
      return data;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['time-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['blocked-dates'] });
      queryClient.invalidateQueries({ queryKey: ['my-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['time-block-pending-reviews'] });
    },
  });
};

/**
 * Hook to deny a time block
 */
export const useDenyTimeBlock = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, notes }: { id: string; notes?: string }) => {
      const { data } = await apiClient.post(`/time-blocks/${id}/deny/`, { notes });
      return data;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['time-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['blocked-dates'] });
      queryClient.invalidateQueries({ queryKey: ['my-blocks'] });
      queryClient.invalidateQueries({ queryKey: ['time-block-pending-reviews'] });
    },
  });
};

/**
 * Hook to check for conflicts before creating a time block
 */
export const useCheckConflicts = () => {
  return useMutation<TimeBlockConflictCheck, Error, CheckConflictsData>({
    mutationFn: async (checkData) => {
      const payload = {
        ...checkData,
        resource_id: checkData.resource_id ? parseInt(checkData.resource_id) : null,
      };
      const { data } = await apiClient.post('/time-blocks/check_conflicts/', payload);
      return data;
    },
  });
};

// =============================================================================
// Holiday Hooks
// =============================================================================

/**
 * Hook to fetch holidays
 */
export const useHolidays = (country?: string) => {
  return useQuery<Holiday[]>({
    queryKey: ['holidays', country],
    queryFn: async () => {
      const params = new URLSearchParams();
      if (country) params.append('country', country);

      const { data } = await apiClient.get(`/holidays/?${params}`);
      return data;
    },
  });
};

/**
 * Hook to get a single holiday by code
 */
export const useHoliday = (code: string) => {
  return useQuery<Holiday>({
    queryKey: ['holidays', code],
    queryFn: async () => {
      const { data } = await apiClient.get(`/holidays/${code}/`);
      return data;
    },
    enabled: !!code,
  });
};

/**
 * Hook to get holiday dates for a specific year
 */
export const useHolidayDates = (year?: number, country?: string) => {
  return useQuery<{ year: number; holidays: { code: string; name: string; date: string }[] }>({
    queryKey: ['holiday-dates', year, country],
    queryFn: async () => {
      const params = new URLSearchParams();
      if (year) params.append('year', String(year));
      if (country) params.append('country', country);

      const { data } = await apiClient.get(`/holidays/dates/?${params}`);
      return data;
    },
  });
};
