import http from './http'
import type {
  Warehouse, WarehouseArea, Storage, Container, Material, MaterialType,
  ContainerLocation, ContainerMaterial, ContainerLocationHistory, ContainerMaterialHistory,
  InventoryMaterialRow, StockEvent,
  MasterDataPayload, AreaPayload, StoragePayload, ContainerPayload, MaterialPayload, MaterialTypePayload,
  ContainerLocationPayload, BindMaterialPayload, GenerateBinsPayload,
  WmsTransportRule, WmsTransportTask, TransportRulePayload, TransportRequestQuery, TransportCandidatePreview
} from '@/types/wms'

function q<T extends object>(params?: T) {
  return { params }
}

export async function listWarehouses(keyword?: string) {
  const { data } = await http.get<Warehouse[]>('/wms/warehouses', q({ q: keyword }))
  return data
}
export async function saveWarehouse(payload: MasterDataPayload) {
  const { data } = payload.id
    ? await http.put<Warehouse>(`/wms/warehouses/${payload.id}`, payload)
    : await http.post<Warehouse>('/wms/warehouses', payload)
  return data
}
export async function deleteWarehouse(id: string, version?: number) {
  await http.delete(`/wms/warehouses/${id}`, q({ version }))
}

export async function listAreas(keyword?: string, warehouseId?: string) {
  const { data } = await http.get<WarehouseArea[]>('/wms/areas', q({ q: keyword, warehouseId }))
  return data
}
export async function saveArea(payload: AreaPayload) {
  const { data } = payload.id
    ? await http.put<WarehouseArea>(`/wms/areas/${payload.id}`, payload)
    : await http.post<WarehouseArea>('/wms/areas', payload)
  return data
}
export async function deleteArea(id: string, version?: number) {
  await http.delete(`/wms/areas/${id}`, q({ version }))
}

export async function listStorages(keyword?: string, areaId?: string, locationKind?: string) {
  const { data } = await http.get<Storage[]>('/wms/storages', q({ q: keyword, areaId, locationKind }))
  return data
}
export async function saveStorage(payload: StoragePayload) {
  const { data } = payload.id
    ? await http.put<Storage>(`/wms/storages/${payload.id}`, payload)
    : await http.post<Storage>('/wms/storages', payload)
  return data
}
export async function deleteStorage(id: string, version?: number) {
  await http.delete(`/wms/storages/${id}`, q({ version }))
}
export async function generateBins(areaId: string, payload: GenerateBinsPayload) {
  const { data } = await http.post<{ created: number }>(`/wms/areas/${areaId}/generate-bins`, payload)
  return data
}
export async function lockStorage(id: string, version?: number) {
  const { data } = await http.post<Storage>(`/wms/storages/${id}/lock`, null, q({ version }))
  return data
}
export async function unlockStorage(id: string, version?: number) {
  const { data } = await http.post<Storage>(`/wms/storages/${id}/unlock`, null, q({ version }))
  return data
}
export async function enableStorage(id: string, version?: number) {
  const { data } = await http.post<Storage>(`/wms/storages/${id}/enable`, null, q({ version }))
  return data
}
export async function disableStorage(id: string, version?: number) {
  const { data } = await http.post<Storage>(`/wms/storages/${id}/disable`, null, q({ version }))
  return data
}

export async function listContainers(keyword?: string) {
  const { data } = await http.get<Container[]>('/wms/containers', q({ q: keyword }))
  return data
}
export async function saveContainer(payload: ContainerPayload) {
  const { data } = payload.id
    ? await http.put<Container>(`/wms/containers/${payload.id}`, payload)
    : await http.post<Container>('/wms/containers', payload)
  return data
}
export async function deleteContainer(id: string, version?: number) {
  await http.delete(`/wms/containers/${id}`, q({ version }))
}

export async function listMaterialTypes(keyword?: string) {
  const { data } = await http.get<MaterialType[]>('/wms/material-types', q({ q: keyword }))
  return data
}
export async function saveMaterialType(payload: MaterialTypePayload) {
  const { data } = payload.id
    ? await http.put<MaterialType>(`/wms/material-types/${payload.id}`, payload)
    : await http.post<MaterialType>('/wms/material-types', payload)
  return data
}
export async function deleteMaterialType(id: string, version?: number) {
  await http.delete(`/wms/material-types/${id}`, q({ version }))
}

export async function listMaterials(params?: { q?: string; lifecycle?: string; onlyUnbound?: boolean; onlyBound?: boolean }) {
  const { data } = await http.get<Material[]>('/wms/materials', q(params))
  return data
}
export async function saveMaterial(payload: MaterialPayload) {
  const { data } = payload.id
    ? await http.put<Material>(`/wms/materials/${payload.id}`, payload)
    : await http.post<Material>('/wms/materials', payload)
  return data
}
export async function deleteMaterial(id: string, version?: number) {
  await http.delete(`/wms/materials/${id}`, q({ version }))
}
export async function archiveMaterial(id: string, version?: number) {
  const { data } = await http.post<Material>(`/wms/materials/${id}/archive`, null, q({ version }))
  return data
}
export async function purgeArchivedMaterials(take = 200) {
  await http.post('/wms/materials/purge-archived', null, q({ take }))
}

export async function listContainerLocations(params?: { locationType?: string; q?: string }) {
  const { data } = await http.get<ContainerLocation[]>('/wms/container-locations', q(params))
  return data
}
export async function saveContainerLocation(payload: ContainerLocationPayload) {
  const { data } = await http.post<ContainerLocation>('/wms/container-locations', payload)
  return data
}
export async function deleteContainerLocation(containerId: string, reason?: string) {
  await http.delete(`/wms/container-locations/${containerId}`, q({ reason }))
}

export async function listContainerMaterials(params?: { q?: string; containerId?: string }) {
  const { data } = await http.get<ContainerMaterial[]>('/wms/container-materials', q(params))
  return data
}
export async function bindMaterial(payload: BindMaterialPayload) {
  const { data } = await http.post<ContainerMaterial>('/wms/container-materials/bind', payload)
  return data
}
/** @deprecated 使用 bindMaterial */
export async function saveContainerMaterial(payload: BindMaterialPayload) {
  return bindMaterial(payload)
}
export async function deleteContainerMaterial(id: string, reason?: string, archive = false) {
  await http.delete(`/wms/container-materials/${id}`, q({ reason, archive }))
}

export async function listInventoryMaterials(params?: { areaId?: string; storageId?: string; q?: string }) {
  const { data } = await http.get<InventoryMaterialRow[]>('/wms/inventory/materials', q(params))
  return data
}
export async function listStockEvents(params?: { eventType?: string; materialId?: string; containerId?: string }) {
  const { data } = await http.get<StockEvent[]>('/wms/stock-events', q(params))
  return data
}

export async function listContainerLocationHistory(containerId?: string) {
  const { data } = await http.get<ContainerLocationHistory[]>('/wms/container-location-history', q({ containerId }))
  return data
}
export async function listContainerMaterialHistory(containerId?: string, materialId?: string) {
  const { data } = await http.get<ContainerMaterialHistory[]>('/wms/container-material-history', q({ containerId, materialId }))
  return data
}

export async function listTransportRules(params?: { triggerType?: string; q?: string }) {
  const { data } = await http.get<WmsTransportRule[]>('/wms/transport-rules', q(params))
  return data
}
export async function saveTransportRule(payload: TransportRulePayload) {
  const { data } = payload.id
    ? await http.put<WmsTransportRule>(`/wms/transport-rules/${payload.id}`, payload)
    : await http.post<WmsTransportRule>('/wms/transport-rules', payload)
  return data
}
export async function deleteTransportRule(id: string, version?: number) {
  await http.delete(`/wms/transport-rules/${id}`, q({ version }))
}

export async function previewTransportCandidates(params: TransportRequestQuery) {
  const { data } = await http.get<TransportCandidatePreview>('/wms/transport-candidates', q(params))
  return data
}
export async function generateTransportTask(params: TransportRequestQuery) {
  const { data } = await http.post<WmsTransportTask>('/wms/transport-tasks/generate', params)
  return data
}
export async function listTransportTasks(params?: { status?: string; triggerType?: string }) {
  const { data } = await http.get<WmsTransportTask[]>('/wms/transport-tasks', q(params))
  return data
}
export async function reserveTransportTask(id: string, reason?: string) {
  const { data } = await http.post<WmsTransportTask>(`/wms/transport-tasks/${id}/reserve`, null, q({ reason }))
  return data
}
export async function cancelTransportTask(id: string, reason?: string) {
  const { data } = await http.post<WmsTransportTask>(`/wms/transport-tasks/${id}/cancel`, null, q({ reason }))
  return data
}
export async function completeTransportTask(id: string, reason?: string) {
  const { data } = await http.post<WmsTransportTask>(`/wms/transport-tasks/${id}/complete`, null, q({ reason }))
  return data
}
export async function dispatchTransportTask(id: string) {
  const { data } = await http.post<WmsTransportTask>(`/wms/transport-tasks/${id}/dispatch`)
  return data
}
