import { ref } from 'vue' import { useToast } from './useToast' import { useApi } from './useApi' import { buildConstructeurRequestPayload, uniqueConstructeurIds } from '~/shared/constructeurUtils' import { useConstructeurs, type Constructeur } from './useConstructeurs' import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations' import { extractCollection } from '~/shared/utils/apiHelpers' export interface Piece { id: string name: string reference?: string | null typePieceId?: string | null typePiece?: { id: string; name?: string } | null productId?: string | null productIds?: string[] product?: { id: string; name?: string } | null constructeurs?: Constructeur[] constructeurIds?: string[] documents?: unknown[] createdAt?: string | null updatedAt?: string | null [key: string]: unknown } interface PieceListResult { success: boolean data?: { items: Piece[]; total: number; page: number; itemsPerPage: number } error?: string } interface PieceSingleResult { success: boolean data?: Piece error?: string } interface LoadPiecesOptions { search?: string page?: number itemsPerPage?: number orderBy?: string orderDir?: 'asc' | 'desc' force?: boolean } const pieces = ref([]) const total = ref(0) const loading = ref(false) const loaded = ref(false) const extractTotal = (payload: unknown, fallbackLength: number): number => { const p = payload as Record | null if (typeof p?.totalItems === 'number') { return p.totalItems } if (typeof p?.['hydra:totalItems'] === 'number') { return p['hydra:totalItems'] } return fallbackLength } export function usePieces() { const { showSuccess } = useToast() const { get, post, patch, delete: del } = useApi() const { ensureConstructeurs } = useConstructeurs() const withResolvedConstructeurs = async (piece: Piece): Promise => { if (!piece || typeof piece !== 'object') { return piece } if (!piece.typePieceId) { const typePieceId = extractRelationId(piece.typePiece) if (typePieceId) { piece.typePieceId = typePieceId } } if (!piece.productId) { const productId = extractRelationId(piece.product) if (productId) { piece.productId = productId } } const productIds = Array.isArray(piece.productIds) ? piece.productIds.filter(Boolean) : [] if (productIds.length === 0 && piece.productId) { piece.productIds = [piece.productId] } else if (productIds.length > 0) { piece.productIds = productIds.map((id) => String(id)) if (!piece.productId) { piece.productId = piece.productIds[0] || null } } const ids = uniqueConstructeurIds( piece.constructeurIds, piece.constructeurs, ) const hasResolvedConstructeurs = Array.isArray(piece.constructeurs) && piece.constructeurs.length > 0 && piece.constructeurs.every((item) => item && typeof item === 'object') if (ids.length && !hasResolvedConstructeurs) { const resolved = await ensureConstructeurs(ids) if (resolved.length) { piece.constructeurs = resolved piece.constructeurIds = ids } } return piece } const loadPieces = async (options: LoadPiecesOptions = {}): Promise => { const { search = '', page = 1, itemsPerPage = 30, orderBy = 'name', orderDir = 'asc', force = false, } = options if (!force && loaded.value && !search && page === 1) { return { success: true, data: { items: pieces.value, total: total.value, page, itemsPerPage }, } } if (loading.value) { return { success: true, data: { items: pieces.value, total: total.value, page, itemsPerPage }, } } loading.value = true try { const params = new URLSearchParams() params.set('itemsPerPage', String(itemsPerPage)) params.set('page', String(page)) if (search && search.trim()) { params.set('name', search.trim()) } params.set(`order[${orderBy}]`, orderDir) const result = await get(`/pieces?${params.toString()}`) if (result.success) { const items = extractCollection(result.data) const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item))) pieces.value = enrichedItems total.value = extractTotal(result.data, items.length) loaded.value = true return { success: true, data: { items: enrichedItems, total: total.value, page, itemsPerPage, }, } } return result as PieceListResult } catch (error) { console.error('Erreur lors du chargement des pièces:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const createPiece = async (pieceData: Partial): Promise => { loading.value = true try { const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(pieceData)) const result = await post('/pieces', normalizedPayload) if (result.success && result.data) { const enriched = await withResolvedConstructeurs(result.data as Piece) pieces.value.unshift(enriched) total.value += 1 const definition = (pieceData as Record)?.definition as Record | undefined const displayName = (result.data as Piece)?.name || (definition?.name as string | undefined) || pieceData?.name || 'Pièce' showSuccess(`Pièce "${displayName}" créée avec succès`) return { success: true, data: enriched } } return { success: false, error: result.error } } catch (error) { console.error('Erreur lors de la création de la pièce:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const updatePieceData = async (id: string, pieceData: Partial): Promise => { loading.value = true try { const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(pieceData)) const result = await patch(`/pieces/${id}`, normalizedPayload) if (result.success && result.data) { const updated = await withResolvedConstructeurs(result.data as Piece) const index = pieces.value.findIndex((piece) => piece.id === id) if (index !== -1) { pieces.value[index] = updated } showSuccess(`Pièce "${updated?.name || pieceData.name || ''}" mise à jour avec succès`) return { success: true, data: updated } } return { success: false, error: result.error } } catch (error) { console.error('Erreur lors de la mise à jour de la pièce:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const deletePiece = async (id: string): Promise => { loading.value = true try { const result = await del(`/pieces/${id}`) if (result.success) { const deletedPiece = pieces.value.find((piece) => piece.id === id) pieces.value = pieces.value.filter((piece) => piece.id !== id) total.value = Math.max(0, total.value - 1) showSuccess(`Pièce "${deletedPiece?.name || 'inconnu'}" supprimée avec succès`) return { success: true } } return { success: false, error: result.error } } catch (error) { console.error('Erreur lors de la suppression de la pièce:', error) return { success: false, error: (error as Error).message } } finally { loading.value = false } } const getPieces = () => pieces.value const isLoading = () => loading.value const clearPiecesCache = () => { pieces.value = [] total.value = 0 loaded.value = false } return { pieces, total, loading, loaded, loadPieces, createPiece, updatePiece: updatePieceData, deletePiece, getPieces, isLoading, clearPiecesCache, } }