import { ref } from 'vue'
import { useToast } from './useToast'
import { useApi, type ApiResponse } from './useApi'
import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations'
import { extractCollection } from '~/shared/utils/apiHelpers'

export interface Machine {
  id: string
  name?: string
  siteId?: string | null
  componentLinks?: unknown[]
  pieceLinks?: unknown[]
  [key: string]: unknown
}

const machines = ref<Machine[]>([])
const loading = ref(false)
const loaded = ref(false)

const resolveLinkCollection = (source: Record<string, unknown>, keys: string[]): unknown[] | undefined => {
  if (!source || typeof source !== 'object') {
    return undefined
  }

  for (const key of keys) {
    const value = source[key]
    if (Array.isArray(value)) {
      return value
    }
  }

  return undefined
}

const normalizeMachineResponse = (payload: unknown): Machine | null => {
  if (!payload || typeof payload !== 'object') {
    return null
  }

  const raw = payload as Record<string, unknown>
  const container = raw.machine && typeof raw.machine === 'object'
    ? raw.machine as Record<string, unknown>
    : raw

  const normalized: Record<string, unknown> = { ...container }

  if (!normalized.siteId) {
    const siteId = extractRelationId(container.site)
    if (siteId) {
      normalized.siteId = siteId
    }
  }

  const componentLinks = resolveLinkCollection(raw, ['componentLinks', 'machineComponentLinks']) ??
    resolveLinkCollection(container, ['componentLinks', 'machineComponentLinks']) ??
    []
  const pieceLinks = resolveLinkCollection(raw, ['pieceLinks', 'machinePieceLinks']) ??
    resolveLinkCollection(container, ['pieceLinks', 'machinePieceLinks']) ??
    []

  normalized.componentLinks = componentLinks
  normalized.pieceLinks = pieceLinks

  return normalized as Machine
}

export function useMachines() {
  const { showSuccess, showError } = useToast()
  const { get, post, patch, delete: del } = useApi()

  const loadMachines = async (options: { force?: boolean } = {}): Promise<void> => {
    if (!options.force && loaded.value) return
    loading.value = true
    try {
      const result = await get('/machines')
      if (result.success) {
        const machineList = extractCollection(result.data)
        const normalized = machineList
          .map((item) => normalizeMachineResponse(item))
          .filter((item): item is Machine => item !== null)
        machines.value = normalized
        loaded.value = true
      }
    } catch (error) {
      console.error('Erreur lors du chargement des machines:', error)
    } finally {
      loading.value = false
    }
  }

  const createMachine = async (machineData: Partial<Machine>): Promise<ApiResponse> => {
    loading.value = true
    try {
      const normalizedPayload = normalizeRelationIds(machineData as Record<string, unknown>)
      const result = await post('/machines', normalizedPayload)
      if (result.success) {
        const createdMachine = normalizeMachineResponse(result.data) ||
          normalizeMachineResponse((result.data as Record<string, unknown>)?.machine) ||
          null
        if (createdMachine) {
          machines.value.push(createdMachine)
        }
        const displayName = createdMachine?.name || machineData?.name || ''
        showSuccess(`Machine "${displayName}" créée avec succès`)
      }
      return result
    } catch (error) {
      console.error('Erreur lors de la création de la machine:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const updateMachineData = async (id: string, machineData: Partial<Machine>): Promise<ApiResponse> => {
    loading.value = true
    try {
      const normalizedPayload = normalizeRelationIds(machineData as Record<string, unknown>)
      const result = await patch(`/machines/${id}`, normalizedPayload)
      if (result.success) {
        const updatedMachine = normalizeMachineResponse(result.data) ||
          normalizeMachineResponse((result.data as Record<string, unknown>)?.machine) ||
          null
        const index = machines.value.findIndex((machine) => machine.id === id)
        if (index !== -1 && updatedMachine) {
          machines.value[index] = {
            ...machines.value[index],
            ...updatedMachine,
          }
        }
        showSuccess(`Machine "${updatedMachine?.name || machineData.name || ''}" mise à jour avec succès`)
      }
      return result
    } catch (error) {
      console.error('Erreur lors de la mise à jour de la machine:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const updateStructure = async (machineId: string, payload: unknown): Promise<ApiResponse> => {
    if (!machineId) {
      return { success: false, error: 'Identifiant de machine manquant' }
    }

    loading.value = true
    try {
      const result = await patch(`/machines/${machineId}/structure`, payload)
      if (result.success) {
        const index = machines.value.findIndex((machine) => machine.id === machineId)
        if (index !== -1) {
          const updatedMachine = normalizeMachineResponse(result.data) ||
            normalizeMachineResponse((result.data as Record<string, unknown>)?.machine) ||
            machines.value[index]
          machines.value[index] = {
            ...machines.value[index],
            ...updatedMachine,
          } as Machine
        }
        showSuccess('Structure de la machine mise à jour avec succès')
      }
      return result
    } catch (error) {
      console.error('Erreur lors de la mise à jour de la structure de la machine:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const cloneMachine = async (sourceId: string, data: { name: string; siteId: string; reference?: string; mode?: 'full' | 'structure' }): Promise<ApiResponse> => {
    loading.value = true
    try {
      const result = await post(`/machines/${sourceId}/clone`, data)
      if (result.success) {
        const clonedMachine = normalizeMachineResponse(result.data) ||
          normalizeMachineResponse((result.data as Record<string, unknown>)?.machine) ||
          null
        if (clonedMachine) {
          machines.value.push(clonedMachine)
        }
        showSuccess(`Machine "${clonedMachine?.name || data.name}" clonée avec succès`)
      }
      return result
    } catch (error) {
      console.error('Erreur lors du clonage de la machine:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const addMissingCustomFields = async (machineId: string, { showToast: shouldShowToast = true } = {}): Promise<ApiResponse> => {
    if (!machineId) {
      const error = 'Identifiant de machine manquant'
      if (shouldShowToast) {
        showError(error)
      }
      return { success: false, error }
    }

    try {
      const result = await post(`/machines/${machineId}/add-custom-fields`)
      if (result.success) {
        if (shouldShowToast) {
          showSuccess('Champs personnalisés complétés avec succès')
        }
      } else if (shouldShowToast && result.error) {
        showError(result.error)
      }
      return result
    } catch (error) {
      console.error('Erreur lors de l\'ajout des champs personnalisés manquants:', error)
      if (shouldShowToast) {
        showError('Erreur lors de la complétion des champs personnalisés')
      }
      return { success: false, error: (error as Error).message }
    }
  }

  const deleteMachine = async (id: string): Promise<ApiResponse> => {
    loading.value = true
    try {
      const result = await del(`/machines/${id}`)
      if (result.success) {
        const deletedMachine = machines.value.find((machine) => machine.id === id)
        machines.value = machines.value.filter((machine) => machine.id !== id)
        showSuccess(`Machine "${deletedMachine?.name || 'inconnu'}" supprimée avec succès`)
      }
      return result
    } catch (error) {
      console.error('Erreur lors de la suppression de la machine:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const getMachineById = (id: string): Machine | undefined => {
    return machines.value.find((machine) => machine.id === id)
  }

  const getMachinesBySite = (siteId: string): Machine[] => {
    return machines.value.filter((machine) => machine.siteId === siteId)
  }

  const getMachines = (): Machine[] => machines.value
  const isLoading = (): boolean => loading.value

  return {
    machines,
    loading,
    loadMachines,
    createMachine,
    updateMachine: updateMachineData,
    updateStructure,
    cloneMachine,
    deleteMachine,
    getMachineById,
    getMachinesBySite,
    getMachines,
    isLoading,
    addMissingCustomFields,
  }
}
