import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useAuthToken } from "../hooks/use-root-data";
import { useToast } from "../hooks/use-toast";
import { useNavigate } from "@remix-run/react";
import {
  CashOut,
  CashOutGatewayResponse,
  SellerOrderUpdate,
} from "../../src/api/types";
import { useState, useEffect } from "react";
import {
  createShoppingCartApi,
  createOrderManagementApi,
  createApiApi,
} from "~/utils/api-client-factory";

// Order query keys
export const orderKeys = {
  all: ["orders"] as const,
  lists: () => [...orderKeys.all, "list"] as const,
  list: (filters: string) => [...orderKeys.lists(), { filters }] as const,
  details: () => [...orderKeys.all, "detail"] as const,
  detail: (id: string) => [...orderKeys.details(), id] as const,
};

/**
 * Hook for fetching the authenticated user's orders
 * @returns Query result with the user's orders
 */
export function useGetUserOrders() {
  const token = useAuthToken();

  return useQuery({
    queryKey: orderKeys.lists(),
    queryFn: async () => {
      if (!token) {
        throw new Error("Authentication token is required");
      }

      try {
        const orderApi = createApiApi(token);
        return await orderApi.apiOrderV1OrdersList();
      } catch (error) {
        console.error("Error fetching user orders:", error);
        throw error;
      }
    },
    enabled: !!token,
    staleTime: 60 * 1000, // 1 minute cache
    refetchOnWindowFocus: false,
  });
}

export function useCashOutCart(cartId: string) {
  const token = useAuthToken();
  const queryClient = useQueryClient();
  const { toast } = useToast();
  const navigate = useNavigate();

  return useMutation<CashOutGatewayResponse, Error, CashOut>({
    mutationFn: async (payload: CashOut) => {
      try {
        if (!token) {
          throw new Error("Authentication required");
        }
        const shoppingCartApi = createShoppingCartApi(token);
        const response = await shoppingCartApi.apiShoppingcartV1CashOutCreate({
          data: {
            shippingInfoId: payload.shippingInfoId,
          },
        });
        return response;
      } catch (error) {
        console.error(`Error during cash out for cart ${cartId}:`, error);
        throw error; // Re-throw the error to be caught by the hook
      }
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ["carts", "detail", cartId] });
      queryClient.invalidateQueries({ queryKey: ["carts", "list"] });
      queryClient.invalidateQueries({ queryKey: ["carts", "count"] });
      queryClient.invalidateQueries({ queryKey: ["getWalletService"] });

      if (data.redirect) {
        if (data.redirect.startsWith("http")) {
          // External URL - use window.location
          window.location.href = data.redirect;
        } else {
          // Internal route - use navigate
          navigate(data.redirect);
        }
      } else {
        toast({
          title: "Success",
          description: "Order created successfully!",
        });
        // Navigate to orders page if no redirect URL is provided
        navigate("/orders");
      }
    },
    onError: (error) => {
      toast({
        title: "Error",
        description: `Failed to create order: ${error.message}`,
        variant: "destructive",
      });
    },
  });
}

export function useGetInvoiceAndShippingInfo(
  invoiceNumber?: string,
  shippingInfoId?: string
) {
  const token = useAuthToken();

  return useQuery({
    queryKey: ["invoice", invoiceNumber, shippingInfoId],
    queryFn: async () => {
      if (!token) {
        throw new Error("Authentication token is required");
      }

      if (!invoiceNumber || !shippingInfoId) {
        throw new Error("Invoice number and shipping info ID are required");
      }

      try {
        const orderApi = createOrderManagementApi(token);
        return await orderApi.apiOrderV1InfoList({
          invoiceNumber,
          shippingInfoId,
        });
      } catch (error) {
        console.error("Error fetching invoice and shipping info:", error);
        throw error;
      }
    },
    enabled: !!invoiceNumber && !!shippingInfoId && !!token,
    staleTime: 60 * 1000, // 1 minute cache
    refetchOnWindowFocus: false,
  });
}

/**
 * Hook for fetching a specific order's details
 * @param orderId - The order ID to fetch
 * @returns Query result with the order details
 */
export function useGetOrderDetail(orderId: string | null) {
  const token = useAuthToken();

  return useQuery({
    queryKey: [...orderKeys.details(), orderId || "null"],
    queryFn: async () => {
      if (!orderId) return null;
      if (!token) {
        throw new Error("Authentication token is required");
      }

      try {
        const orderApi = createOrderManagementApi(token);
        return await orderApi.apiOrderV1OrderDetailList({ orderId });
      } catch (error) {
        console.error("Error fetching order details:", error);
        throw error;
      }
    },
    enabled: !!orderId && !!token,
    staleTime: 5 * 60 * 1000, // 1 minute cache
    refetchOnWindowFocus: false,
  });
}

/**
 * Hook for fetching the seller's orders
 * @returns Query result with the seller's orders
 */
export function useGetSellerOrders() {
  const token = useAuthToken();

  return useQuery({
    queryKey: [...orderKeys.all, "seller"],
    queryFn: async () => {
      if (!token) {
        throw new Error("Authentication token is required");
      }

      try {
        const orderApi = createOrderManagementApi(token);
        return await orderApi.apiOrderV1SellerordersList();
      } catch (error) {
        console.error("Error fetching seller orders:", error);
        throw error;
      }
    },
    enabled: !!token,
    staleTime: 30 * 60 * 1000, // 30 seconds - balance between freshness and performance
    refetchOnMount: false, // Always refetch when component mounts
    refetchOnWindowFocus: false,
  });
}

/**
 * Hook for fetching a specific order's details for seller
 * @param orderId - The order ID to fetch
 * @returns Query result with the order details for seller
 */
export function useGetSellerOrderDetail(orderId: string | null) {
  const token = useAuthToken();

  return useQuery({
    queryKey: [...orderKeys.all, "seller", "detail", orderId || "null"],
    queryFn: async () => {
      if (!orderId) return null;
      if (!token) {
        throw new Error("Authentication token is required");
      }

      try {
        const orderApi = createOrderManagementApi(token);
        return await orderApi.apiOrderV1SellerordersDetailRead({ id: orderId });
      } catch (error) {
        console.error("Error fetching seller order details:", error);
        throw error;
      }
    },
    enabled: !!orderId && !!token,
    staleTime: 5 * 60 * 1000, // 5 minute cache
    refetchOnWindowFocus: false,
  });
}

/**
 * Hook for updating a seller order (accept/reject order, add tracking code, etc.)
 * @returns Mutation for updating seller order
 */
export function useUpdateSellerOrder() {
  const token = useAuthToken();
  const queryClient = useQueryClient();
  const { toast } = useToast();

  return useMutation<
    void,
    Error,
    { orderId: string; data: SellerOrderUpdate },
    { previousSellerOrders?: unknown; previousOrderDetail?: unknown }
  >({
    mutationFn: async ({ orderId, data }) => {
      if (!token) {
        throw new Error("Authentication required");
      }

      try {
        const orderApi = createOrderManagementApi(token);
        await orderApi.apiOrderV1SellerordersPartialUpdate({
          id: orderId,
          data,
        });
      } catch (error) {
        console.error(`Error updating seller order ${orderId}:`, error);
        throw error;
      }
    },
    // Optimistically update the cache before the mutation
    onMutate: async ({ orderId }) => {
      // Cancel any outgoing refetches to prevent race conditions
      await queryClient.cancelQueries({
        queryKey: [...orderKeys.all, "seller"],
      });
      await queryClient.cancelQueries({
        queryKey: [...orderKeys.all, "seller", "detail", orderId],
      });

      // Snapshot the previous values
      const previousSellerOrders = queryClient.getQueryData([
        ...orderKeys.all,
        "seller",
      ]);
      const previousOrderDetail = queryClient.getQueryData([
        ...orderKeys.all,
        "seller",
        "detail",
        orderId,
      ]);

      return { previousSellerOrders, previousOrderDetail };
    },
    onSuccess: async (_, { orderId }) => {
      // Invalidate and refetch relevant queries to refresh the data
      await queryClient.invalidateQueries({
        queryKey: [...orderKeys.all, "seller"],
      });
      await queryClient.invalidateQueries({
        queryKey: [...orderKeys.all, "seller", "detail", orderId],
      });

      toast({
        title: "موفق",
        description: "سفارش با موفقیت بروزرسانی شد",
      });
    },
    onError: (error, _, context) => {
      // Rollback to previous values on error
      if (context?.previousSellerOrders) {
        queryClient.setQueryData(
          [...orderKeys.all, "seller"],
          context.previousSellerOrders
        );
      }
      if (context?.previousOrderDetail) {
        queryClient.setQueryData(
          [...orderKeys.all, "seller", "detail"],
          context.previousOrderDetail
        );
      }

      console.error("Update seller order error:", error);
      toast({
        title: "خطا",
        description: `خطا در بروزرسانی سفارش: ${error.message}`,
        variant: "destructive",
      });
    },
  });
}

/**
 * Hook for getting seller order count
 * @returns Query result with the seller order count
 */
export function useGetSellerOrderCount(enabled: boolean) {
  const token = useAuthToken();

  return useQuery({
    queryKey: [...orderKeys.all, "seller", "count"],
    queryFn: async () => {
      if (!token) {
        return 0;
      }

      try {
        const orderApi = createOrderManagementApi(token);
        const orders = await orderApi.apiOrderV1SellerordersList();
        return orders.filter((order) => order.status === "pending").length || 0;
      } catch (error) {
        console.error("Error fetching seller order count:", error);
        return 0;
      }
    },
    enabled: !!token && enabled,
    staleTime: 2 * 60 * 1000, // 2 minutes - order count doesn't change frequently
    gcTime: 5 * 60 * 1000, // 5 minutes
    refetchOnWindowFocus: false,
    refetchOnMount: false,
  });
}

/**
 * Convenient hook for getting seller order count with local state management
 * Similar to useCartCount hook
 */
export const useSellerOrderCount = (enabled: boolean) => {
  const [count, setCount] = useState(0);
  const { data: orderCount, isLoading } = useGetSellerOrderCount(enabled);

  // Update local state whenever the query data changes
  useEffect(() => {
    if (!isLoading && orderCount !== undefined) {
      setCount(orderCount);
    }
  }, [orderCount, isLoading]);

  return count;
};
