import { useMutation, useQuery, UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
import { useInject } from '@/lib/di/hooks/useInject';
import { LEAGUE_SERVICE_TOKEN } from '@/lib/di/tokens';
import { ApiError } from '@/lib/api/base/ApiError';
import type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';
import type { LeagueRosterJoinRequestDTO } from '@/lib/types/generated/LeagueRosterJoinRequestDTO';

interface UpdateMemberRoleInput {
  leagueId: string;
  driverId: string;
  newRole: 'owner' | 'admin' | 'steward' | 'member';
}

interface RemoveMemberInput {
  leagueId: string;
  driverId: string;
}

interface JoinRequestActionInput {
  leagueId: string;
  requestId: string;
}

export function useLeagueRosterAdmin(leagueId: string, options?: UseQueryOptions<LeagueRosterMemberDTO[], ApiError>) {
  const leagueService = useInject(LEAGUE_SERVICE_TOKEN);

  return useQuery<LeagueRosterMemberDTO[], ApiError>({
    queryKey: ['league-roster-admin', leagueId],
    queryFn: async () => {
      const result = await leagueService.getAdminRosterMembers(leagueId);
      if (result.isErr()) {
        throw new ApiError(result.getError().message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });
      }
      return result.unwrap();
    },
    ...options,
  });
}

export function useLeagueJoinRequests(leagueId: string, options?: UseQueryOptions<LeagueRosterJoinRequestDTO[], ApiError>) {
  const leagueService = useInject(LEAGUE_SERVICE_TOKEN);

  return useQuery<LeagueRosterJoinRequestDTO[], ApiError>({
    queryKey: ['league-join-requests', leagueId],
    queryFn: async () => {
      const result = await leagueService.getAdminRosterJoinRequests(leagueId);
      if (result.isErr()) {
        throw new ApiError(result.getError().message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });
      }
      return result.unwrap();
    },
    ...options,
  });
}

export function useUpdateMemberRole(
  options?: Omit<UseMutationOptions<{ success: boolean }, ApiError, UpdateMemberRoleInput>, 'mutationFn'>
) {
  const leagueService = useInject(LEAGUE_SERVICE_TOKEN);

  return useMutation<{ success: boolean }, ApiError, UpdateMemberRoleInput>({
    mutationFn: async (input) => {
      const result = await leagueService.updateMemberRole(input.leagueId, input.driverId, input.newRole);
      if (result.isErr()) {
        throw new ApiError(result.getError().message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });
      }
      return result.unwrap();
    },
    ...options,
  });
}

export function useRemoveMember(
  options?: Omit<UseMutationOptions<{ success: boolean }, ApiError, RemoveMemberInput>, 'mutationFn'>
) {
  const leagueService = useInject(LEAGUE_SERVICE_TOKEN);

  return useMutation<{ success: boolean }, ApiError, RemoveMemberInput>({
    mutationFn: async (input) => {
      const result = await leagueService.removeMember(input.leagueId, input.driverId);
      if (result.isErr()) {
        throw new ApiError(result.getError().message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });
      }
      return result.unwrap();
    },
    ...options,
  });
}

export function useApproveJoinRequest(
  options?: Omit<UseMutationOptions<{ success: boolean }, ApiError, JoinRequestActionInput>, 'mutationFn'>
) {
  const leagueService = useInject(LEAGUE_SERVICE_TOKEN);

  return useMutation<{ success: boolean }, ApiError, JoinRequestActionInput>({
    mutationFn: async (input) => {
      const result = await leagueService.approveJoinRequest(input.leagueId, input.requestId);
      if (result.isErr()) {
        throw new ApiError(result.getError().message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });
      }
      return result.unwrap();
    },
    ...options,
  });
}

export function useRejectJoinRequest(
  options?: Omit<UseMutationOptions<{ success: boolean }, ApiError, JoinRequestActionInput>, 'mutationFn'>
) {
  const leagueService = useInject(LEAGUE_SERVICE_TOKEN);

  return useMutation<{ success: boolean }, ApiError, JoinRequestActionInput>({
    mutationFn: async (input) => {
      const result = await leagueService.rejectJoinRequest(input.leagueId, input.requestId);
      if (result.isErr()) {
        throw new ApiError(result.getError().message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });
      }
      return result.unwrap();
    },
    ...options,
  });
}
