/**
 * Tenant React Query hooks
 */
import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
import { tenantService } from '../services/tenant';
import {
  BakeryRegistration,
  TenantResponse,
  TenantAccessResponse,
  TenantUpdate,
  TenantMemberResponse,
  TenantStatistics,
  TenantSearchParams,
  TenantNearbyParams,
  AddMemberWithUserCreate,
  BakeryRegistrationWithSubscription,
} from '../types/tenant';
import { ApiError } from '../client';

// Query Keys
export const tenantKeys = {
  all: ['tenant'] as const,
  lists: () => [...tenantKeys.all, 'list'] as const,
  list: (filters: string) => [...tenantKeys.lists(), { filters }] as const,
  details: () => [...tenantKeys.all, 'detail'] as const,
  detail: (id: string) => [...tenantKeys.details(), id] as const,
  subdomain: (subdomain: string) => [...tenantKeys.all, 'subdomain', subdomain] as const,
  userTenants: (userId: string) => [...tenantKeys.all, 'user', userId] as const,
  userOwnedTenants: (userId: string) => [...tenantKeys.all, 'user-owned', userId] as const,
  access: (tenantId: string, userId: string) => [...tenantKeys.all, 'access', tenantId, userId] as const,
  search: (params: TenantSearchParams) => [...tenantKeys.lists(), 'search', params] as const,
  nearby: (params: TenantNearbyParams) => [...tenantKeys.lists(), 'nearby', params] as const,
  members: (tenantId: string) => [...tenantKeys.all, 'members', tenantId] as const,
  statistics: () => [...tenantKeys.all, 'statistics'] as const,
} as const;

// Queries
export const useTenant = (
  tenantId: string,
  options?: Omit<UseQueryOptions<TenantResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantResponse, ApiError>({
    queryKey: tenantKeys.detail(tenantId),
    queryFn: () => tenantService.getTenant(tenantId),
    enabled: !!tenantId,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useTenantBySubdomain = (
  subdomain: string,
  options?: Omit<UseQueryOptions<TenantResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantResponse, ApiError>({
    queryKey: tenantKeys.subdomain(subdomain),
    queryFn: () => tenantService.getTenantBySubdomain(subdomain),
    enabled: !!subdomain,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useUserTenants = (
  userId: string,
  options?: Omit<UseQueryOptions<TenantResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantResponse[], ApiError>({
    queryKey: tenantKeys.userTenants(userId),
    queryFn: () => tenantService.getUserTenants(userId),
    enabled: !!userId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

export const useUserOwnedTenants = (
  userId: string,
  options?: Omit<UseQueryOptions<TenantResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantResponse[], ApiError>({
    queryKey: tenantKeys.userOwnedTenants(userId),
    queryFn: () => tenantService.getUserOwnedTenants(userId),
    enabled: !!userId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

export const useTenantAccess = (
  tenantId: string,
  userId: string,
  options?: Omit<UseQueryOptions<TenantAccessResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantAccessResponse, ApiError>({
    queryKey: tenantKeys.access(tenantId, userId),
    queryFn: () => tenantService.verifyTenantAccess(tenantId, userId),
    enabled: !!tenantId && !!userId,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useSearchTenants = (
  params: TenantSearchParams,
  options?: Omit<UseQueryOptions<TenantResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantResponse[], ApiError>({
    queryKey: tenantKeys.search(params),
    queryFn: () => tenantService.searchTenants(params),
    enabled: !!params.search_term,
    staleTime: 30 * 1000, // 30 seconds for search results
    ...options,
  });
};

export const useNearbyTenants = (
  params: TenantNearbyParams,
  options?: Omit<UseQueryOptions<TenantResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantResponse[], ApiError>({
    queryKey: tenantKeys.nearby(params),
    queryFn: () => tenantService.getNearbyTenants(params),
    enabled: !!(params.latitude && params.longitude),
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useTeamMembers = (
  tenantId: string,
  activeOnly: boolean = true,
  options?: Omit<UseQueryOptions<TenantMemberResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantMemberResponse[], ApiError>({
    queryKey: tenantKeys.members(tenantId),
    queryFn: () => tenantService.getTeamMembers(tenantId, activeOnly),
    enabled: !!tenantId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

export const useTenantStatistics = (
  options?: Omit<UseQueryOptions<TenantStatistics, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TenantStatistics, ApiError>({
    queryKey: tenantKeys.statistics(),
    queryFn: () => tenantService.getTenantStatistics(),
    staleTime: 10 * 60 * 1000, // 10 minutes
    ...options,
  });
};

// Mutations
export const useRegisterBakery = (
  options?: UseMutationOptions<TenantResponse, ApiError, BakeryRegistration>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<TenantResponse, ApiError, BakeryRegistration>({
    mutationFn: (bakeryData: BakeryRegistration) => tenantService.registerBakery(bakeryData),
    onSuccess: (data, variables) => {
      // Invalidate user tenants to include the new one
      queryClient.invalidateQueries({ queryKey: tenantKeys.userTenants('') });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userOwnedTenants('') });
      // Set the tenant data in cache
      queryClient.setQueryData(tenantKeys.detail(data.id), data);
    },
    ...options,
  });
};

export const useRegisterBakeryWithSubscription = (
  options?: UseMutationOptions<TenantResponse, ApiError, BakeryRegistrationWithSubscription>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<TenantResponse, ApiError, BakeryRegistrationWithSubscription>({
    mutationFn: (bakeryData: BakeryRegistrationWithSubscription) => tenantService.registerBakeryWithSubscription(bakeryData),
    onSuccess: (data, variables) => {
      // Invalidate user tenants to include the new one
      queryClient.invalidateQueries({ queryKey: tenantKeys.userTenants('') });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userOwnedTenants('') });
      // Set the tenant data in cache
      queryClient.setQueryData(tenantKeys.detail(data.id), data);
    },
    ...options,
  });
};

export const useUpdateTenant = (
  options?: UseMutationOptions<TenantResponse, ApiError, { tenantId: string; updateData: TenantUpdate }>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<TenantResponse, ApiError, { tenantId: string; updateData: TenantUpdate }>({
    mutationFn: ({ tenantId, updateData }) => tenantService.updateTenant(tenantId, updateData),
    onSuccess: (data, { tenantId }) => {
      // Update the tenant cache
      queryClient.setQueryData(tenantKeys.detail(tenantId), data);
      // Invalidate related queries
      queryClient.invalidateQueries({ queryKey: tenantKeys.userTenants('') });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userOwnedTenants('') });
    },
    ...options,
  });
};

export const useDeactivateTenant = (
  options?: UseMutationOptions<{ success: boolean; message: string }, ApiError, string>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<{ success: boolean; message: string }, ApiError, string>({
    mutationFn: (tenantId: string) => tenantService.deactivateTenant(tenantId),
    onSuccess: (data, tenantId) => {
      // Invalidate tenant-related queries
      queryClient.invalidateQueries({ queryKey: tenantKeys.detail(tenantId) });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userTenants('') });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userOwnedTenants('') });
    },
    ...options,
  });
};

export const useActivateTenant = (
  options?: UseMutationOptions<{ success: boolean; message: string }, ApiError, string>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<{ success: boolean; message: string }, ApiError, string>({
    mutationFn: (tenantId: string) => tenantService.activateTenant(tenantId),
    onSuccess: (data, tenantId) => {
      // Invalidate tenant-related queries
      queryClient.invalidateQueries({ queryKey: tenantKeys.detail(tenantId) });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userTenants('') });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userOwnedTenants('') });
    },
    ...options,
  });
};

export const useUpdateModelStatus = (
  options?: UseMutationOptions<
    TenantResponse, 
    ApiError, 
    { tenantId: string; modelTrained: boolean; lastTrainingDate?: string }
  >
) => {
  const queryClient = useQueryClient();
  
  return useMutation<
    TenantResponse, 
    ApiError, 
    { tenantId: string; modelTrained: boolean; lastTrainingDate?: string }
  >({
    mutationFn: ({ tenantId, modelTrained, lastTrainingDate }) => 
      tenantService.updateModelStatus(tenantId, modelTrained, lastTrainingDate),
    onSuccess: (data, { tenantId }) => {
      // Update the tenant cache
      queryClient.setQueryData(tenantKeys.detail(tenantId), data);
    },
    ...options,
  });
};

export const useAddTeamMember = (
  options?: UseMutationOptions<
    TenantMemberResponse,
    ApiError,
    { tenantId: string; userId: string; role: string }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    TenantMemberResponse,
    ApiError,
    { tenantId: string; userId: string; role: string }
  >({
    mutationFn: ({ tenantId, userId, role }) => tenantService.addTeamMember(tenantId, userId, role),
    onSuccess: (data, { tenantId }) => {
      // Invalidate team members query
      queryClient.invalidateQueries({ queryKey: tenantKeys.members(tenantId) });
    },
    ...options,
  });
};

export const useAddTeamMemberWithUserCreation = (
  options?: UseMutationOptions<
    TenantMemberResponse,
    ApiError,
    { tenantId: string; memberData: AddMemberWithUserCreate }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    TenantMemberResponse,
    ApiError,
    { tenantId: string; memberData: AddMemberWithUserCreate }
  >({
    mutationFn: ({ tenantId, memberData }) =>
      tenantService.addTeamMemberWithUserCreation(tenantId, memberData),
    onSuccess: (data, { tenantId }) => {
      // Invalidate team members query
      queryClient.invalidateQueries({ queryKey: tenantKeys.members(tenantId) });
    },
    ...options,
  });
};

export const useUpdateMemberRole = (
  options?: UseMutationOptions<
    TenantMemberResponse, 
    ApiError, 
    { tenantId: string; memberUserId: string; newRole: string }
  >
) => {
  const queryClient = useQueryClient();
  
  return useMutation<
    TenantMemberResponse, 
    ApiError, 
    { tenantId: string; memberUserId: string; newRole: string }
  >({
    mutationFn: ({ tenantId, memberUserId, newRole }) => 
      tenantService.updateMemberRole(tenantId, memberUserId, newRole),
    onSuccess: (data, { tenantId }) => {
      // Invalidate team members query
      queryClient.invalidateQueries({ queryKey: tenantKeys.members(tenantId) });
    },
    ...options,
  });
};

export const useRemoveTeamMember = (
  options?: UseMutationOptions<
    { success: boolean; message: string },
    ApiError,
    { tenantId: string; memberUserId: string }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    { success: boolean; message: string },
    ApiError,
    { tenantId: string; memberUserId: string }
  >({
    mutationFn: ({ tenantId, memberUserId }) => tenantService.removeTeamMember(tenantId, memberUserId),
    onSuccess: (data, { tenantId }) => {
      // Invalidate team members query
      queryClient.invalidateQueries({ queryKey: tenantKeys.members(tenantId) });
    },
    ...options,
  });
};

/**
 * Hook to transfer tenant ownership to another admin
 * This is a critical operation that changes the tenant owner
 */
export const useTransferOwnership = (
  options?: UseMutationOptions<
    TenantResponse,
    ApiError,
    { tenantId: string; newOwnerId: string }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    TenantResponse,
    ApiError,
    { tenantId: string; newOwnerId: string }
  >({
    mutationFn: ({ tenantId, newOwnerId }) => tenantService.transferOwnership(tenantId, newOwnerId),
    onSuccess: (data, { tenantId }) => {
      // Invalidate all tenant-related queries since ownership changed
      queryClient.invalidateQueries({ queryKey: tenantKeys.detail(tenantId) });
      queryClient.invalidateQueries({ queryKey: tenantKeys.members(tenantId) });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userTenants('') });
      queryClient.invalidateQueries({ queryKey: tenantKeys.userOwnedTenants('') });
      // Invalidate access queries for all users since roles changed
      queryClient.invalidateQueries({ queryKey: tenantKeys.access(tenantId, '') });
    },
    ...options,
  });
};