import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  getQuotes, fetchQuotes, getQuoteHistory, getDailyMinMax, getDailyQuotes,
  getPeriodicExpenses, createPeriodicExpense as createPeriodicExpenseApi,
  updatePeriodicExpense as updatePeriodicExpenseApi,
  deletePeriodicExpense as deletePeriodicExpenseApi,
  generateMonthlyExpense as generateMonthlyExpenseApi,
  getExpenses, createNonPeriodicExpense as createNonPeriodicExpenseApi,
  payExpense as payExpenseApi,
  getMonthlyPayedTotal,
  getMonthlyTotals,
  getTotalPending,
  importPeriodicExpenses,
  importExpenses,
  type CreatePeriodicExpenseInput, type CreateNonPeriodicExpenseInput, type PayExpenseInput,
} from "./api";

export const quoteKeys = {
  all: ["quotes"] as const,
  history: (type: string, startDate: string, endDate: string) =>
    ["quotes", type, "history", startDate, endDate] as const,
  minMax: (type: string, startDate: string, endDate: string) =>
    ["quotes", type, "minMax", startDate, endDate] as const,
  daily: (type: string, startDate: string, endDate: string) =>
    ["quotes", type, "daily", startDate, endDate] as const,
};

export function useQuotes() {
  return useQuery({
    queryKey: quoteKeys.all,
    queryFn: getQuotes,
    staleTime: 30_000,
    refetchInterval: 60_000,
  });
}

export function useFetchQuotes() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: fetchQuotes,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: quoteKeys.all });
    },
  });
}

export function useQuoteHistory(type: string, startDate: string, endDate: string) {
  return useQuery({
    queryKey: quoteKeys.history(type, startDate, endDate),
    queryFn: () => getQuoteHistory(type, startDate, endDate),
    staleTime: 30_000,
    refetchInterval: 60_000,
  });
}

export function useDailyMinMax(type: string, startDate: string, endDate: string) {
  return useQuery({
    queryKey: quoteKeys.minMax(type, startDate, endDate),
    queryFn: () => getDailyMinMax(type, startDate, endDate),
    staleTime: 30_000,
    refetchInterval: 60_000,
  });
}

export function useDailyQuotes(type: string, startDate: string, endDate: string) {
  return useQuery({
    queryKey: quoteKeys.daily(type, startDate, endDate),
    queryFn: () => getDailyQuotes(type, startDate, endDate),
    staleTime: 30_000,
    refetchInterval: 60_000,
  });
}

// Expenses

export const expenseKeys = {
  periodic: ["periodic-expenses"] as const,
  all: ["expenses"] as const,
  byFilters: (status: string, page: number, pageSize: number, periodicExpenseId?: number, search?: string) =>
    ["expenses", status, page, pageSize, periodicExpenseId, search] as const,
  monthlyTotal: (year: number, month: number) => ["expenses", "monthly-total", year, month] as const,
  monthlyTotals: (year: number, month: number) => ["expenses", "totals", year, month] as const,
  totalPending: ["expenses", "pending-total"] as const,
};

export function usePeriodicExpenses() {
  return useQuery({
    queryKey: expenseKeys.periodic,
    queryFn: getPeriodicExpenses,
  });
}

export function useCreatePeriodicExpense() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreatePeriodicExpenseInput) => createPeriodicExpenseApi(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.periodic });
    },
  });
}

export function useUpdatePeriodicExpense() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: CreatePeriodicExpenseInput }) =>
      updatePeriodicExpenseApi(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.periodic });
    },
  });
}

export function useDeletePeriodicExpense() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => deletePeriodicExpenseApi(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.periodic });
    },
  });
}

export function useGenerateMonthlyExpense() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => generateMonthlyExpenseApi(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.all });
    },
  });
}

export function useExpenses(status: string, page: number = 1, pageSize: number = 10, periodicExpenseId?: number, search?: string) {
  return useQuery({
    queryKey: expenseKeys.byFilters(status, page, pageSize, periodicExpenseId, search),
    queryFn: () => getExpenses(
      status === "all" ? undefined : status,
      page,
      pageSize,
      periodicExpenseId,
      search,
    ),
  });
}

export function useMonthlyTotals(year: number, month: number) {
  return useQuery({
    queryKey: expenseKeys.monthlyTotals(year, month),
    queryFn: () => getMonthlyTotals(year, month),
  });
}

export function useTotalPending() {
  return useQuery({
    queryKey: expenseKeys.totalPending,
    queryFn: getTotalPending,
  });
}

export function useMonthlyPayedTotal(year: number, month: number) {
  return useQuery({
    queryKey: expenseKeys.monthlyTotal(year, month),
    queryFn: () => getMonthlyPayedTotal(year, month),
  });
}

export function useCreateNonPeriodicExpense() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateNonPeriodicExpenseInput) => createNonPeriodicExpenseApi(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.all });
    },
  });
}

export function useImportExpenses() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (file: File) => importExpenses(file),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.all });
    },
  });
}

export function useImportPeriodicExpenses() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (file: File) => importPeriodicExpenses(file),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.periodic });
    },
  });
}

export function usePayExpense() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: PayExpenseInput }) =>
      payExpenseApi(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: expenseKeys.all });
    },
  });
}
