/**
 * Machine detail page — update/mutation methods.
 *
 * Extracted from useMachineDetailData.ts to keep the orchestrator under 500 lines.
 */

import type { Ref } from 'vue'
import { uniqueConstructeurIds, constructeurIdsFromLinks } from '~/shared/constructeurUtils'
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'

type AnyRecord = Record<string, unknown>

export interface UseMachineDetailUpdatesDeps {
  machine: Ref<AnyRecord | null>
  machineName: Ref<string>
  machineReference: Ref<string>
  machineSiteId: Ref<string>
  machineConstructeurIds: Ref<string[]>
  constructeurLinks: Ref<ConstructeurLinkEntry[]>
  originalConstructeurLinks: Ref<ConstructeurLinkEntry[]>
  machineDocumentsLoaded: Ref<boolean>
  machineComponentLinks: Ref<AnyRecord[]>
  machinePieceLinks: Ref<AnyRecord[]>
  machineProductLinks: Ref<AnyRecord[]>
  applyMachineLinks: (data: AnyRecord) => boolean
  refreshMachineDocuments: () => Promise<void>
  transformComponentCustomFields: (items: AnyRecord[]) => AnyRecord[]
  transformCustomFields: (items: AnyRecord[]) => AnyRecord[]
  loadProductDocuments: () => Promise<void>
  upsertCustomFieldValue: (
    fieldId: string,
    entityType: string,
    entityId: string,
    value: unknown,
  ) => Promise<unknown>
  updateMachineApi: (id: string, data: any) => Promise<unknown>
  updateComposantApi: (id: string, data: any) => Promise<unknown>
  updatePieceApi: (id: string, data: any) => Promise<unknown>
  apiPatch: (endpoint: string, data?: unknown) => Promise<any>
  toast: { showInfo: (msg: string) => void }
  syncLinks: (
    entityType: 'machine' | 'piece' | 'composant' | 'product',
    entityId: string,
    originalLinks: ConstructeurLinkEntry[],
    formLinks: ConstructeurLinkEntry[],
  ) => Promise<void>
}

export function useMachineDetailUpdates(deps: UseMachineDetailUpdatesDeps) {
  const {
    machine,
    machineName,
    machineReference,
    machineSiteId,
    machineConstructeurIds,
    constructeurLinks,
    originalConstructeurLinks,
    machineComponentLinks,
    machinePieceLinks,
    applyMachineLinks,
    loadProductDocuments,
    transformComponentCustomFields,
    transformCustomFields,
    upsertCustomFieldValue,
    updateMachineApi,
    updateComposantApi,
    updatePieceApi,
    apiPatch,
    toast,
    syncLinks,
  } = deps

  const updateMachineInfo = async () => {
    if (!machine.value) return
    try {
      const payload: Record<string, unknown> = {}
      if (machineName.value !== machine.value.name) payload.name = machineName.value
      if (machineReference.value !== machine.value.reference) payload.reference = machineReference.value
      if ((machineSiteId.value || undefined) !== ((machine.value.siteId as string) || (machine.value.site as any)?.id || undefined)) payload.siteId = machineSiteId.value || undefined
      const result: any = await updateMachineApi(machine.value.id as string, payload as any)
      if (result.success) {
        const machinePayload =
          result.data?.machine && typeof result.data.machine === 'object'
            ? result.data.machine
            : result.data
        if (machinePayload && typeof machinePayload === 'object') {
          machine.value = {
            ...machine.value,
            ...machinePayload,
            documents: machinePayload.documents || machine.value.documents || [],
            customFieldValues: machinePayload.customFieldValues || machine.value.customFieldValues || [],
          }
          const linksApplied = applyMachineLinks(result.data)
          if (linksApplied && machine.value) {
            machine.value.componentLinks = machineComponentLinks.value
            machine.value.pieceLinks = machinePieceLinks.value
          }
          loadProductDocuments().catch(() => {})
        }
      }
      // Sync constructeur links after entity save
      await syncLinks('machine', machine.value!.id as string, originalConstructeurLinks.value, constructeurLinks.value)
      originalConstructeurLinks.value = constructeurLinks.value.map(l => ({ ...l }))
    } catch (error) {
      console.error('Erreur lors de la mise à jour de la machine:', error)
    }
  }

  const updateComponent = async (updatedComponent: AnyRecord) => {
    try {
      const cIds = uniqueConstructeurIds(
        updatedComponent.constructeurIds,
        updatedComponent.constructeurId,
        updatedComponent.constructeur,
      )
      const productId = updatedComponent.productId
        ? String(updatedComponent.productId)
        : null
      const prixStr =
        updatedComponent.prix !== null &&
        updatedComponent.prix !== undefined &&
        String(updatedComponent.prix).trim() !== ''
          ? String(updatedComponent.prix)
          : null

      const result: any = await updateComposantApi(updatedComponent.id as string, {
        name: updatedComponent.name,
        reference: updatedComponent.reference,
        constructeurIds: cIds,
        prix: prixStr,
        productId,
      } as any)
      if (result.success) {
        const transformed = transformComponentCustomFields([result.data])[0]
        Object.assign(updatedComponent, transformed)
      }
    } catch (error) {
      console.error('Erreur lors de la mise à jour du composant:', error)
    }
  }

  const _buildAndUpdatePiece = async (updatedPiece: AnyRecord) => {
    const cIds = uniqueConstructeurIds(
      updatedPiece.constructeurIds,
      updatedPiece.constructeurId,
      updatedPiece.constructeur,
    )
    const productId = updatedPiece.productId ? String(updatedPiece.productId) : null
    const prixStr =
      updatedPiece.prix !== null &&
      updatedPiece.prix !== undefined &&
      String(updatedPiece.prix).trim() !== ''
        ? String(updatedPiece.prix)
        : null

    const result: any = await updatePieceApi(updatedPiece.id as string, {
      name: updatedPiece.name,
      reference: updatedPiece.reference || null,
      constructeurIds: cIds,
      prix: prixStr,
      productId,
    } as any)
    if (result.success) {
      const transformed = transformCustomFields([result.data])[0]
      Object.assign(updatedPiece, transformed)
    }
    return result
  }

  const updatePieceFromComponent = async (updatedPiece: AnyRecord) => {
    try {
      const result = await _buildAndUpdatePiece(updatedPiece)
      if (result?.success && updatedPiece.customFields) {
        const fieldsToSave = (updatedPiece.customFields as AnyRecord[]).filter(
          (field) => field.value !== undefined,
        )
        if (fieldsToSave.length) {
          await Promise.allSettled(
            fieldsToSave.map((field) =>
              upsertCustomFieldValue(
                field.id as string,
                'piece',
                updatedPiece.id as string,
                field.value,
              ),
            ),
          )
        }
      }

      // Update slot quantity if this is a composant structure piece
      const slotId = updatedPiece.slotId as string | null
      const quantity = typeof updatedPiece.quantity === 'number' ? Math.max(1, updatedPiece.quantity) : null
      if (slotId && quantity !== null) {
        await apiPatch(`/composant-piece-slots/${slotId}`, { quantity })
      }
    } catch (error) {
      console.error('Erreur lors de la mise à jour de la pièce:', error)
    }
  }

  const updatePieceInfo = async (updatedPiece: AnyRecord) => {
    try {
      await _buildAndUpdatePiece(updatedPiece)

      // Update link quantity if this is a direct machine piece
      const linkId = updatedPiece.linkId || updatedPiece.machinePieceLinkId
      const quantity = typeof updatedPiece.quantity === 'number' ? Math.max(1, updatedPiece.quantity) : null
      if (linkId && quantity !== null) {
        await apiPatch(`/machine_piece_links/${linkId}`, { quantity })
      }
    } catch (error) {
      console.error('Erreur lors de la mise à jour de la pièce:', error)
    }
  }

  const handleMachineConstructeurChange = (value: unknown) => {
    const newIds = uniqueConstructeurIds(value)
    machineConstructeurIds.value = newIds
    // Sync constructeurLinks: keep existing entries, add new ones
    const existingMap = new Map(constructeurLinks.value.map(l => [l.constructeurId, l]))
    constructeurLinks.value = newIds.map(id =>
      existingMap.get(id) ?? { constructeurId: id, supplierReference: null },
    )
  }

  const editComponent = () => {
    toast.showInfo('La modification des composants sera bientôt disponible')
  }

  const editPiece = () => {
    toast.showInfo('La modification des pièces sera bientôt disponible')
  }

  return {
    updateMachineInfo,
    updateComponent,
    updatePieceFromComponent,
    updatePieceInfo,
    handleMachineConstructeurChange,
    editComponent,
    editPiece,
  }
}
