import { createContext, useContext, useState, ReactNode } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  ArticleDto,
  WarehouseLocationDto,
  CreateArticleDto,
  UpdateArticleDto,
  CreateWarehouseDto,
  UpdateWarehouseDto,
  CreateCategoryDto,
  UpdateCategoryDto,
  CreateMovementDto,
  CreateTransferDto,
  CreateBatchDto,
  CreateSerialDto,
  CreateSerialsBulkDto,
  CreateInventoryCountDto,
  ArticleFilterDto,
  MovementFilterDto,
  StockLevelFilterDto,
  BatchStatus,
  SerialStatus,
  InventoryStatus,
} from "../types";
import {
  articleService,
  warehouseLocationService,
  categoryService,
  movementService,
  batchService,
  serialService,
  stockService,
  inventoryService,
} from "../services/warehouseService";

// Query keys for React Query
export const warehouseQueryKeys = {
  articles: ["warehouse", "articles"] as const,
  article: (id: number) => ["warehouse", "articles", id] as const,
  articleStock: (id: number) => ["warehouse", "articles", id, "stock"] as const,
  locations: ["warehouse", "locations"] as const,
  location: (id: number) => ["warehouse", "locations", id] as const,
  categories: ["warehouse", "categories"] as const,
  categoryTree: ["warehouse", "categories", "tree"] as const,
  movements: ["warehouse", "movements"] as const,
  movement: (id: number) => ["warehouse", "movements", id] as const,
  batches: ["warehouse", "batches"] as const,
  batch: (id: number) => ["warehouse", "batches", id] as const,
  serials: ["warehouse", "serials"] as const,
  serial: (id: number) => ["warehouse", "serials", id] as const,
  stockLevels: ["warehouse", "stock-levels"] as const,
  inventories: ["warehouse", "inventories"] as const,
  inventory: (id: number) => ["warehouse", "inventories", id] as const,
};

// Context state interface
interface WarehouseContextState {
  selectedArticle: ArticleDto | null;
  selectedWarehouse: WarehouseLocationDto | null;
  setSelectedArticle: (article: ArticleDto | null) => void;
  setSelectedWarehouse: (warehouse: WarehouseLocationDto | null) => void;
}

const WarehouseContext = createContext<WarehouseContextState | undefined>(
  undefined,
);

export function WarehouseProvider({ children }: { children: ReactNode }) {
  const [selectedArticle, setSelectedArticle] = useState<ArticleDto | null>(
    null,
  );
  const [selectedWarehouse, setSelectedWarehouse] =
    useState<WarehouseLocationDto | null>(null);

  const value: WarehouseContextState = {
    selectedArticle,
    selectedWarehouse,
    setSelectedArticle,
    setSelectedWarehouse,
  };

  return (
    <WarehouseContext.Provider value={value}>
      {children}
    </WarehouseContext.Provider>
  );
}

export function useWarehouseContext() {
  const context = useContext(WarehouseContext);
  if (!context) {
    throw new Error(
      "useWarehouseContext must be used within a WarehouseProvider",
    );
  }
  return context;
}

// ============================================
// ARTICLES HOOKS
// ============================================

export function useArticles(filter?: ArticleFilterDto) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.articles, filter],
    queryFn: () => articleService.getAll(filter),
  });
}

export function useArticle(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.article(id!),
    queryFn: () => articleService.getById(id!),
    enabled: !!id,
  });
}

export function useArticleStock(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.articleStock(id!),
    queryFn: () => articleService.getStock(id!),
    enabled: !!id,
  });
}

export function useCreateArticle() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateArticleDto) => articleService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.articles });
    },
  });
}

export function useUpdateArticle() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: UpdateArticleDto }) =>
      articleService.update(id, data),
    onSuccess: (_, { id }) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.articles });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.article(id),
      });
    },
  });
}

export function useDeleteArticle() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => articleService.delete(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.articles });
    },
  });
}

export function useUploadArticleImage() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, file }: { id: number; file: File }) =>
      articleService.uploadImage(id, file),
    onSuccess: (_, { id }) => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.article(id),
      });
    },
  });
}

// ============================================
// WAREHOUSE LOCATIONS HOOKS
// ============================================

export function useWarehouses(params?: { active?: boolean }) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.locations, params],
    queryFn: () => warehouseLocationService.getAll(params?.active),
  });
}

export function useWarehouse(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.location(id!),
    queryFn: () => warehouseLocationService.getById(id!),
    enabled: !!id,
  });
}

export function useCreateWarehouse() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateWarehouseDto) =>
      warehouseLocationService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.locations });
    },
  });
}

export function useUpdateWarehouse() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: UpdateWarehouseDto }) =>
      warehouseLocationService.update(id, data),
    onSuccess: (_, { id }) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.locations });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.location(id),
      });
    },
  });
}

export function useDeleteWarehouse() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => warehouseLocationService.delete(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.locations });
    },
  });
}

export function useSetDefaultWarehouse() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => warehouseLocationService.setDefault(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.locations });
    },
  });
}

// ============================================
// CATEGORIES HOOKS
// ============================================

export function useCategories() {
  return useQuery({
    queryKey: warehouseQueryKeys.categories,
    queryFn: () => categoryService.getAll(),
  });
}

export function useCategoryTree() {
  return useQuery({
    queryKey: warehouseQueryKeys.categoryTree,
    queryFn: () => categoryService.getTree(),
  });
}

export function useCreateCategory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateCategoryDto) => categoryService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.categories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.categoryTree,
      });
    },
  });
}

export function useUpdateCategory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: UpdateCategoryDto }) =>
      categoryService.update(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.categories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.categoryTree,
      });
    },
  });
}

export function useDeleteCategory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => categoryService.delete(id),
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.categories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.categoryTree,
      });
    },
  });
}

// ============================================
// STOCK MOVEMENTS HOOKS
// ============================================

export function useMovements(filter?: MovementFilterDto) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.movements, filter],
    queryFn: () => movementService.getAll(filter),
  });
}

export function useMovement(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.movement(id!),
    queryFn: () => movementService.getById(id!),
    enabled: !!id,
  });
}

export function useCreateInboundMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateMovementDto) =>
      movementService.createInbound(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
    },
  });
}

export function useCreateOutboundMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateMovementDto) =>
      movementService.createOutbound(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
    },
  });
}

export function useCreateTransferMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateTransferDto) =>
      movementService.createTransfer(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
    },
  });
}

export function useCreateAdjustmentMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateMovementDto) =>
      movementService.createAdjustment(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
    },
  });
}

export function useConfirmMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => movementService.confirm(id),
    onSuccess: (_, id) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.movement(id),
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.batches });
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.serials });
    },
  });
}

export function useCancelMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => movementService.cancel(id),
    onSuccess: (_, id) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.movement(id),
      });
    },
  });
}

export function useDeleteMovement() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => movementService.delete(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
    },
  });
}

// ============================================
// BATCHES HOOKS
// ============================================

export function useBatches(articleId?: number, status?: BatchStatus) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.batches, articleId, status],
    queryFn: () => batchService.getAll(articleId, status),
  });
}

export function useBatch(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.batch(id!),
    queryFn: () => batchService.getById(id!),
    enabled: !!id,
  });
}

export function useArticleBatches(articleId: number | undefined) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.batches, "article", articleId],
    queryFn: () => batchService.getAll(articleId),
    enabled: !!articleId,
  });
}

export function useExpiringBatches(days: number = 30) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.batches, "expiring", days],
    queryFn: () => batchService.getExpiring(days),
  });
}

export function useCreateBatch() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateBatchDto) => batchService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.batches });
    },
  });
}

export function useUpdateBatchStatus() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ id, status }: { id: number; status: BatchStatus }) =>
      batchService.updateStatus(id, status),
    onSuccess: (_, { id }) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.batches });
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.batch(id) });
    },
  });
}

// ============================================
// SERIALS HOOKS
// ============================================

export function useSerials(articleId?: number, status?: SerialStatus) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.serials, articleId, status],
    queryFn: () => serialService.getAll(articleId, status),
  });
}

export function useSerial(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.serial(id!),
    queryFn: () => serialService.getById(id!),
    enabled: !!id,
  });
}

export function useArticleSerials(articleId: number | undefined) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.serials, "article", articleId],
    queryFn: () => serialService.getAll(articleId),
    enabled: !!articleId,
  });
}

export function useCreateSerial() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateSerialDto) => serialService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.serials });
    },
  });
}

export function useCreateSerialsBulk() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateSerialsBulkDto) => serialService.createBulk(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.serials });
    },
  });
}

export function useRegisterSerialSale() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({
      id,
      customerId,
      saleReference,
    }: {
      id: number;
      customerId?: number;
      saleReference?: string;
    }) => serialService.registerSale(id, customerId, saleReference),
    onSuccess: (_, { id }) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.serials });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.serial(id),
      });
    },
  });
}

export function useRegisterSerialReturn() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({
      id,
      warehouseId,
      isDefective,
    }: {
      id: number;
      warehouseId: number;
      isDefective: boolean;
    }) => serialService.registerReturn(id, warehouseId, isDefective),
    onSuccess: (_, { id }) => {
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.serials });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.serial(id),
      });
    },
  });
}

// ============================================
// STOCK LEVELS HOOKS
// ============================================

export function useStockLevels(filter?: StockLevelFilterDto) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.stockLevels, filter],
    queryFn: () => stockService.getAll(filter),
  });
}

export function useArticleStockLevels(articleId: number | undefined) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.stockLevels, "article", articleId],
    queryFn: () => stockService.getAll({ articleId }),
    enabled: !!articleId,
  });
}

export function useWarehouseStockLevels(warehouseId: number | undefined) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.stockLevels, "warehouse", warehouseId],
    queryFn: () => stockService.getAll({ warehouseId }),
    enabled: !!warehouseId,
  });
}

export function useStockValuation(warehouseId?: number) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.stockLevels, "valuation", warehouseId],
    queryFn: () => stockService.getValuation(warehouseId || 0),
  });
}

export function useClosePeriod() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (period: number) => stockService.closePeriod(period),
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
    },
  });
}

// ============================================
// INVENTORY HOOKS
// ============================================

export function useInventories(status?: InventoryStatus) {
  return useQuery({
    queryKey: [...warehouseQueryKeys.inventories, status],
    queryFn: () => inventoryService.getAll(status),
  });
}

export function useInventory(id: number | undefined) {
  return useQuery({
    queryKey: warehouseQueryKeys.inventory(id!),
    queryFn: () => inventoryService.getById(id!),
    enabled: !!id,
  });
}

export function useCreateInventory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateInventoryCountDto) =>
      inventoryService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventories,
      });
    },
  });
}

export function useStartInventory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => inventoryService.start(id),
    onSuccess: (_, id) => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventory(id),
      });
    },
  });
}

export function useUpdateInventoryLine() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({
      inventoryId: _inventoryId,
      lineId,
      countedQty,
    }: {
      inventoryId: number;
      lineId: number;
      countedQty: number;
    }) => inventoryService.updateLine(lineId, countedQty),
    onSuccess: (_, { inventoryId: invId }) => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventory(invId),
      });
    },
  });
}

export function useCompleteInventory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => inventoryService.complete(id),
    onSuccess: (_, id) => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventory(id),
      });
    },
  });
}

export function useConfirmInventory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => inventoryService.confirm(id),
    onSuccess: (_, id) => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventory(id),
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.stockLevels,
      });
      queryClient.invalidateQueries({ queryKey: warehouseQueryKeys.movements });
    },
  });
}

export function useCancelInventory() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => inventoryService.cancel(id),
    onSuccess: (_, id) => {
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventories,
      });
      queryClient.invalidateQueries({
        queryKey: warehouseQueryKeys.inventory(id),
      });
    },
  });
}
