import api from "../../../services/api";
import {
  ArticleDto,
  ArticleFilterDto,
  ArticleStockDto,
  ArticleValuationDto,
  BatchDto,
  BatchStatus,
  CategoryDto,
  CategoryTreeDto,
  CreateArticleDto,
  CreateBatchDto,
  CreateCategoryDto,
  CreateInventoryCountDto,
  CreateMovementDto,
  CreateSerialDto,
  CreateSerialsBulkDto,
  CreateTransferDto,
  CreateAdjustmentDto,
  CreateWarehouseDto,
  InventoryCountDetailDto,
  InventoryCountDto,
  InventoryCountLineDto,
  InventoryStatus,
  MovementDetailDto,
  MovementDto,
  MovementFilterDto,
  MovementReasonDto,
  MovementType,
  PeriodValuationDto,
  QualityStatus,
  SerialDto,
  SerialStatus,
  StockLevelDto,
  StockLevelFilterDto,
  StockSummaryDto,
  UpdateArticleDto,
  UpdateBatchDto,
  UpdateCategoryDto,
  UpdateWarehouseDto,
  ValuationMethod,
  WarehouseLocationDto,
} from "../types";

const BASE_URL = "/warehouse";

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

export const warehouseLocationService = {
  getAll: async (includeInactive = false): Promise<WarehouseLocationDto[]> => {
    const response = await api.get(`${BASE_URL}/locations`, {
      params: { includeInactive },
    });
    return response.data;
  },

  getById: async (id: number): Promise<WarehouseLocationDto> => {
    const response = await api.get(`${BASE_URL}/locations/${id}`);
    return response.data;
  },

  getDefault: async (): Promise<WarehouseLocationDto> => {
    const response = await api.get(`${BASE_URL}/locations/default`);
    return response.data;
  },

  create: async (data: CreateWarehouseDto): Promise<WarehouseLocationDto> => {
    const response = await api.post(`${BASE_URL}/locations`, data);
    return response.data;
  },

  update: async (
    id: number,
    data: UpdateWarehouseDto,
  ): Promise<WarehouseLocationDto> => {
    const response = await api.put(`${BASE_URL}/locations/${id}`, data);
    return response.data;
  },

  delete: async (id: number): Promise<void> => {
    await api.delete(`${BASE_URL}/locations/${id}`);
  },

  setDefault: async (id: number): Promise<void> => {
    await api.put(`${BASE_URL}/locations/${id}/set-default`);
  },
};

// ===============================================
// ARTICLE CATEGORIES
// ===============================================

export const categoryService = {
  getAll: async (includeInactive = false): Promise<CategoryDto[]> => {
    const response = await api.get(`${BASE_URL}/categories`, {
      params: { includeInactive },
    });
    return response.data;
  },

  getTree: async (): Promise<CategoryTreeDto[]> => {
    const response = await api.get(`${BASE_URL}/categories/tree`);
    return response.data;
  },

  getById: async (id: number): Promise<CategoryDto> => {
    const response = await api.get(`${BASE_URL}/categories/${id}`);
    return response.data;
  },

  create: async (data: CreateCategoryDto): Promise<CategoryDto> => {
    const response = await api.post(`${BASE_URL}/categories`, data);
    return response.data;
  },

  update: async (id: number, data: UpdateCategoryDto): Promise<CategoryDto> => {
    const response = await api.put(`${BASE_URL}/categories/${id}`, data);
    return response.data;
  },

  delete: async (id: number): Promise<void> => {
    await api.delete(`${BASE_URL}/categories/${id}`);
  },
};

// ===============================================
// ARTICLES
// ===============================================

export const articleService = {
  getAll: async (filter?: ArticleFilterDto): Promise<ArticleDto[]> => {
    const response = await api.get(`${BASE_URL}/articles`, { params: filter });
    return response.data;
  },

  getById: async (id: number): Promise<ArticleDto> => {
    const response = await api.get(`${BASE_URL}/articles/${id}`);
    return response.data;
  },

  getByCode: async (code: string): Promise<ArticleDto> => {
    const response = await api.get(`${BASE_URL}/articles/by-code/${code}`);
    return response.data;
  },

  getByBarcode: async (barcode: string): Promise<ArticleDto> => {
    const response = await api.get(
      `${BASE_URL}/articles/by-barcode/${barcode}`,
    );
    return response.data;
  },

  create: async (data: CreateArticleDto): Promise<ArticleDto> => {
    const response = await api.post(`${BASE_URL}/articles`, data);
    return response.data;
  },

  update: async (id: number, data: UpdateArticleDto): Promise<ArticleDto> => {
    const response = await api.put(`${BASE_URL}/articles/${id}`, data);
    return response.data;
  },

  delete: async (id: number): Promise<void> => {
    await api.delete(`${BASE_URL}/articles/${id}`);
  },

  uploadImage: async (id: number, file: File): Promise<void> => {
    const formData = new FormData();
    formData.append("file", file);
    await api.post(`${BASE_URL}/articles/${id}/image`, formData, {
      headers: { "Content-Type": "multipart/form-data" },
    });
  },

  getImageUrl: (id: number): string => {
    return `${api.defaults.baseURL}${BASE_URL}/articles/${id}/image`;
  },

  getStock: async (id: number): Promise<ArticleStockDto> => {
    const response = await api.get(`${BASE_URL}/articles/${id}/stock`);
    return response.data;
  },
};

// ===============================================
// BATCHES
// ===============================================

export const batchService = {
  getAll: async (
    articleId?: number,
    status?: BatchStatus,
  ): Promise<BatchDto[]> => {
    const response = await api.get(`${BASE_URL}/batches`, {
      params: { articleId, status },
    });
    return response.data;
  },

  getById: async (id: number): Promise<BatchDto> => {
    const response = await api.get(`${BASE_URL}/batches/${id}`);
    return response.data;
  },

  getByNumber: async (
    articleId: number,
    batchNumber: string,
  ): Promise<BatchDto> => {
    const response = await api.get(
      `${BASE_URL}/batches/by-number/${articleId}/${batchNumber}`,
    );
    return response.data;
  },

  create: async (data: CreateBatchDto): Promise<BatchDto> => {
    const response = await api.post(`${BASE_URL}/batches`, data);
    return response.data;
  },

  update: async (id: number, data: UpdateBatchDto): Promise<BatchDto> => {
    const response = await api.put(`${BASE_URL}/batches/${id}`, data);
    return response.data;
  },

  updateStatus: async (id: number, status: BatchStatus): Promise<void> => {
    await api.put(`${BASE_URL}/batches/${id}/status`, { status });
  },

  getExpiring: async (daysThreshold = 30): Promise<BatchDto[]> => {
    const response = await api.get(`${BASE_URL}/batches/expiring`, {
      params: { daysThreshold },
    });
    return response.data;
  },

  recordQualityCheck: async (
    id: number,
    qualityStatus: QualityStatus,
    notes?: string,
  ): Promise<BatchDto> => {
    const response = await api.post(`${BASE_URL}/batches/${id}/quality-check`, {
      qualityStatus,
      notes,
    });
    return response.data;
  },
};

// ===============================================
// SERIALS
// ===============================================

export const serialService = {
  getAll: async (
    articleId?: number,
    status?: SerialStatus,
  ): Promise<SerialDto[]> => {
    const response = await api.get(`${BASE_URL}/serials`, {
      params: { articleId, status },
    });
    return response.data;
  },

  getById: async (id: number): Promise<SerialDto> => {
    const response = await api.get(`${BASE_URL}/serials/${id}`);
    return response.data;
  },

  getByNumber: async (
    articleId: number,
    serialNumber: string,
  ): Promise<SerialDto> => {
    const response = await api.get(
      `${BASE_URL}/serials/by-number/${articleId}/${serialNumber}`,
    );
    return response.data;
  },

  create: async (data: CreateSerialDto): Promise<SerialDto> => {
    const response = await api.post(`${BASE_URL}/serials`, data);
    return response.data;
  },

  createBulk: async (data: CreateSerialsBulkDto): Promise<SerialDto[]> => {
    const response = await api.post(`${BASE_URL}/serials/bulk`, data);
    return response.data;
  },

  updateStatus: async (id: number, status: SerialStatus): Promise<void> => {
    await api.put(`${BASE_URL}/serials/${id}/status`, { status });
  },

  registerSale: async (
    id: number,
    customerId?: number,
    salesReference?: string,
  ): Promise<SerialDto> => {
    const response = await api.post(`${BASE_URL}/serials/${id}/sell`, {
      customerId,
      salesReference,
    });
    return response.data;
  },

  registerReturn: async (
    id: number,
    warehouseId: number,
    isDefective: boolean,
  ): Promise<SerialDto> => {
    const response = await api.post(`${BASE_URL}/serials/${id}/return`, {
      warehouseId,
      isDefective,
    });
    return response.data;
  },
};

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

export const stockService = {
  getAll: async (filter?: StockLevelFilterDto): Promise<StockLevelDto[]> => {
    const response = await api.get(`${BASE_URL}/stock`, { params: filter });
    return response.data;
  },

  get: async (
    articleId: number,
    warehouseId: number,
    batchId?: number,
  ): Promise<StockLevelDto> => {
    const response = await api.get(
      `${BASE_URL}/stock/${articleId}/${warehouseId}`,
      {
        params: { batchId },
      },
    );
    return response.data;
  },

  getLowStock: async (): Promise<StockLevelDto[]> => {
    const response = await api.get(`${BASE_URL}/stock/low-stock`);
    return response.data;
  },

  getSummary: async (articleId: number): Promise<StockSummaryDto> => {
    const response = await api.get(`${BASE_URL}/stock/summary/${articleId}`);
    return response.data;
  },

  getValuation: async (
    articleId: number,
    method?: ValuationMethod,
  ): Promise<ArticleValuationDto> => {
    const response = await api.get(`${BASE_URL}/stock/valuation/${articleId}`, {
      params: { method },
    });
    return response.data;
  },

  getPeriodValuation: async (
    period: number,
    warehouseId?: number,
  ): Promise<PeriodValuationDto[]> => {
    const response = await api.get(
      `${BASE_URL}/stock/valuation/period/${period}`,
      {
        params: { warehouseId },
      },
    );
    return response.data;
  },

  calculatePeriodValuation: async (
    articleId: number,
    period: number,
    warehouseId?: number,
  ): Promise<PeriodValuationDto> => {
    const response = await api.post(`${BASE_URL}/stock/valuation/calculate`, {
      articleId,
      period,
      warehouseId,
    });
    return response.data;
  },

  closePeriod: async (period: number): Promise<void> => {
    await api.post(`${BASE_URL}/stock/valuation/close-period/${period}`);
  },

  recalculateAverageCost: async (
    articleId: number,
  ): Promise<{ articleId: number; weightedAverageCost: number }> => {
    const response = await api.post(
      `${BASE_URL}/stock/recalculate-average/${articleId}`,
    );
    return response.data;
  },
};

// ===============================================
// MOVEMENTS
// ===============================================

export const movementService = {
  getAll: async (filter?: MovementFilterDto): Promise<MovementDto[]> => {
    const response = await api.get(`${BASE_URL}/movements`, { params: filter });
    return response.data;
  },

  getById: async (id: number): Promise<MovementDetailDto> => {
    const response = await api.get(`${BASE_URL}/movements/${id}`);
    return response.data;
  },

  getByDocumentNumber: async (
    documentNumber: string,
  ): Promise<MovementDetailDto> => {
    const response = await api.get(
      `${BASE_URL}/movements/by-document/${documentNumber}`,
    );
    return response.data;
  },

  createInbound: async (
    data: CreateMovementDto,
  ): Promise<MovementDetailDto> => {
    const response = await api.post(`${BASE_URL}/movements/inbound`, data);
    return response.data;
  },

  createOutbound: async (
    data: CreateMovementDto,
  ): Promise<MovementDetailDto> => {
    const response = await api.post(`${BASE_URL}/movements/outbound`, data);
    return response.data;
  },

  createTransfer: async (
    data: CreateTransferDto,
  ): Promise<MovementDetailDto> => {
    const response = await api.post(`${BASE_URL}/movements/transfer`, data);
    return response.data;
  },

  createAdjustment: async (
    data: CreateAdjustmentDto,
  ): Promise<MovementDetailDto> => {
    const response = await api.post(`${BASE_URL}/movements/adjustment`, data);
    return response.data;
  },

  confirm: async (id: number): Promise<MovementDetailDto> => {
    const response = await api.post(`${BASE_URL}/movements/${id}/confirm`);
    return response.data;
  },

  cancel: async (id: number): Promise<MovementDetailDto> => {
    const response = await api.post(`${BASE_URL}/movements/${id}/cancel`);
    return response.data;
  },

  delete: async (id: number): Promise<void> => {
    await api.delete(`${BASE_URL}/movements/${id}`);
  },

  generateDocumentNumber: async (type: MovementType): Promise<string> => {
    const response = await api.get(
      `${BASE_URL}/movements/generate-number/${type}`,
    );
    return response.data.documentNumber;
  },

  getReasons: async (
    type?: MovementType,
    includeInactive = false,
  ): Promise<MovementReasonDto[]> => {
    const response = await api.get(`${BASE_URL}/movements/reasons`, {
      params: { type, includeInactive },
    });
    return response.data;
  },
};

// ===============================================
// INVENTORY
// ===============================================

export const inventoryService = {
  getAll: async (status?: InventoryStatus): Promise<InventoryCountDto[]> => {
    const response = await api.get(`${BASE_URL}/inventory`, {
      params: { status },
    });
    return response.data;
  },

  getById: async (id: number): Promise<InventoryCountDetailDto> => {
    const response = await api.get(`${BASE_URL}/inventory/${id}`);
    return response.data;
  },

  create: async (data: CreateInventoryCountDto): Promise<InventoryCountDto> => {
    const response = await api.post(`${BASE_URL}/inventory`, data);
    return response.data;
  },

  start: async (id: number): Promise<InventoryCountDetailDto> => {
    const response = await api.post(`${BASE_URL}/inventory/${id}/start`);
    return response.data;
  },

  complete: async (id: number): Promise<InventoryCountDetailDto> => {
    const response = await api.post(`${BASE_URL}/inventory/${id}/complete`);
    return response.data;
  },

  confirm: async (id: number): Promise<InventoryCountDetailDto> => {
    const response = await api.post(`${BASE_URL}/inventory/${id}/confirm`);
    return response.data;
  },

  cancel: async (id: number): Promise<InventoryCountDto> => {
    const response = await api.post(`${BASE_URL}/inventory/${id}/cancel`);
    return response.data;
  },

  updateLine: async (
    lineId: number,
    countedQuantity: number,
    countedBy?: string,
  ): Promise<InventoryCountLineDto> => {
    const response = await api.put(
      `${BASE_URL}/inventory/lines/${lineId}/count`,
      {
        countedQuantity,
        countedBy,
      },
    );
    return response.data;
  },

  updateLinesBatch: async (
    inventoryId: number,
    lines: { lineId: number; countedQuantity: number }[],
    countedBy?: string,
  ): Promise<InventoryCountLineDto[]> => {
    const response = await api.put(
      `${BASE_URL}/inventory/${inventoryId}/count-batch`,
      {
        countedBy,
        lines,
      },
    );
    return response.data;
  },
};

// Export all services
export default {
  locations: warehouseLocationService,
  categories: categoryService,
  articles: articleService,
  batches: batchService,
  serials: serialService,
  stock: stockService,
  movements: movementService,
  inventory: inventoryService,
};
