import { useState, useCallback } from 'react';
import type {
  StockDTO,
  StockBatchDTO,
  AddStockBatchRequest,
  CreateStockRequest,
  UpdateStockRequest,
  StockFilter,
  ReserveStockRequest,
} from '@effigenix/api-client';
import { client } from '../utils/api-client.js';

interface StocksState {
  stocks: StockDTO[];
  stock: StockDTO | null;
  loading: boolean;
  error: string | null;
}

function errorMessage(err: unknown): string {
  return err instanceof Error ? err.message : 'Unbekannter Fehler';
}

export function useStocks() {
  const [state, setState] = useState<StocksState>({
    stocks: [],
    stock: null,
    loading: false,
    error: null,
  });

  const fetchStocks = useCallback(async (filter?: StockFilter) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      const stocks = await client.stocks.list(filter);
      setState((s) => ({ ...s, stocks, loading: false, error: null }));
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
    }
  }, []);

  const fetchStock = useCallback(async (id: string) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      const stock = await client.stocks.getById(id);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
    }
  }, []);

  const createStock = useCallback(async (request: CreateStockRequest) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      const result = await client.stocks.create(request);
      setState((s) => ({ ...s, loading: false, error: null }));
      return result;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return null;
    }
  }, []);

  const updateStock = useCallback(async (id: string, request: UpdateStockRequest) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      const stock = await client.stocks.update(id, request);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return stock;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return null;
    }
  }, []);

  const addBatch = useCallback(async (stockId: string, request: AddStockBatchRequest): Promise<StockBatchDTO | null> => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      const batch = await client.stocks.addBatch(stockId, request);
      setState((s) => ({ ...s, loading: false, error: null }));
      return batch;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return null;
    }
  }, []);

  const removeBatch = useCallback(async (stockId: string, batchId: string, quantityAmount: string, quantityUnit: string) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      await client.stocks.removeBatch(stockId, batchId, { quantityAmount, quantityUnit });
      const stock = await client.stocks.getById(stockId);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return true;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return false;
    }
  }, []);

  const blockBatch = useCallback(async (stockId: string, batchId: string, reason: string) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      await client.stocks.blockBatch(stockId, batchId, { reason });
      const stock = await client.stocks.getById(stockId);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return true;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return false;
    }
  }, []);

  const unblockBatch = useCallback(async (stockId: string, batchId: string) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      await client.stocks.unblockBatch(stockId, batchId);
      const stock = await client.stocks.getById(stockId);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return true;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return false;
    }
  }, []);

  const reserveStock = useCallback(async (stockId: string, request: ReserveStockRequest) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      const reservation = await client.stocks.reserveStock(stockId, request);
      const stock = await client.stocks.getById(stockId);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return reservation;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return null;
    }
  }, []);

  const confirmReservation = useCallback(async (stockId: string, reservationId: string) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      await client.stocks.confirmReservation(stockId, reservationId);
      const stock = await client.stocks.getById(stockId);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return true;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return false;
    }
  }, []);

  const releaseReservation = useCallback(async (stockId: string, reservationId: string) => {
    setState((s) => ({ ...s, loading: true, error: null }));
    try {
      await client.stocks.releaseReservation(stockId, reservationId);
      const stock = await client.stocks.getById(stockId);
      setState((s) => ({ ...s, stock, loading: false, error: null }));
      return true;
    } catch (err) {
      setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
      return false;
    }
  }, []);

  const clearError = useCallback(() => {
    setState((s) => ({ ...s, error: null }));
  }, []);

  return {
    ...state,
    fetchStocks,
    fetchStock,
    createStock,
    updateStock,
    addBatch,
    removeBatch,
    blockBatch,
    unblockBatch,
    reserveStock,
    releaseReservation,
    confirmReservation,
    clearError,
  };
}
