import type {
  ComponentModelCustomField,
  ComponentModelCustomFieldType,
  ComponentModelPiece,
  ComponentModelProduct,
  ComponentModelStructureNode,
} from '../types/inventory'
// Inline helper to avoid circular dependency with componentStructure.ts
const isPlainObject = (value: unknown): value is Record<string, unknown> => {
  return value !== null && typeof value === 'object' && !Array.isArray(value)
}

export const toStringArray = (input: unknown): string[] | undefined => {
  if (!Array.isArray(input)) {
    return undefined
  }
  const parsed = input
    .map((value) => {
      if (typeof value === 'string') {
        return value.trim()
      }
      if (value === null || value === undefined) {
        return ''
      }
      return String(value).trim()
    })
    .filter((value) => value.length > 0)
  return parsed.length ? parsed : undefined
}

export const extractFieldValueObject = (field: any): Record<string, any> => {
  if (isPlainObject(field?.value)) {
    return field.value as Record<string, any>
  }
  return {}
}

export const sanitizeCustomFields = (fields: any[]): ComponentModelCustomField[] => {
  if (!Array.isArray(fields)) {
    return []
  }

  return fields
    .map((field, index) => {
      const rawName =
        typeof field?.name === 'string'
          ? field.name
          : typeof field?.key === 'string'
            ? field.key
            : ''
      const name = rawName.trim()
      if (!name) {
        return null
      }

      const valueObject = extractFieldValueObject(field)

      const candidateType =
        typeof field?.type === 'string' && field.type
          ? field.type
          : typeof valueObject?.type === 'string'
            ? valueObject.type
            : ''
      const allowedTypes: ComponentModelCustomFieldType[] = ['text', 'number', 'select', 'boolean', 'date']
      const type = allowedTypes.includes(candidateType as ComponentModelCustomFieldType)
        ? (candidateType as ComponentModelCustomFieldType)
        : 'text'

      const required =
        typeof valueObject?.required === 'boolean' ? valueObject.required : !!field?.required

      let options: string[] | undefined
      if (type === 'select') {
        options =
          toStringArray(valueObject?.options) ||
          toStringArray((valueObject as any)?.choices) ||
          toStringArray(field?.options)

        if (!options && typeof field?.optionsText === 'string') {
          const parsedFromText = field.optionsText
            .split(/\r?\n/)
            .map((option: string) => option.trim())
            .filter((option: string) => option.length > 0)
          options = parsedFromText.length ? parsedFromText : undefined
        }
      }

      const machineContextOnly =
        typeof valueObject?.machineContextOnly === 'boolean' ? valueObject.machineContextOnly : !!field?.machineContextOnly

      const result: ComponentModelCustomField = { name, type, required, machineContextOnly }
      if (options) {
        result.options = options
      }
      const defaultCandidate =
        field?.defaultValue ?? valueObject?.defaultValue ?? field?.value ?? field?.default ?? null
      const resolvedDefault = (() => {
        if (defaultCandidate === undefined || defaultCandidate === null) {
          return undefined
        }
        if (typeof defaultCandidate === 'object') {
          if (defaultCandidate === null) {
            return undefined
          }
          if ('defaultValue' in (defaultCandidate as Record<string, any>)) {
            return (defaultCandidate as Record<string, any>).defaultValue
          }
          if ('value' in (defaultCandidate as Record<string, any>)) {
            return (defaultCandidate as Record<string, any>).value
          }
          return undefined
        }
        return defaultCandidate
      })()
      if (resolvedDefault !== undefined && resolvedDefault !== null && resolvedDefault !== '') {
        result.defaultValue = String(resolvedDefault)
      }
      const id = typeof field?.id === 'string' ? field.id : undefined
      if (id) {
        result.id = id
      }
      const customFieldId = typeof field?.customFieldId === 'string' ? field.customFieldId : undefined
      if (customFieldId) {
        result.customFieldId = customFieldId
      }
      const orderIndex = typeof field?.orderIndex === 'number' ? field.orderIndex : index
      result.orderIndex = orderIndex
      return result
    })
    .filter((field): field is ComponentModelCustomField => !!field)
}

export const sanitizePieces = (pieces: any[]): ComponentModelPiece[] => {
  if (!Array.isArray(pieces)) {
    return []
  }

  return pieces
    .map((piece) => {
      const rawTypePieceId = typeof piece?.typePieceId === 'string'
        ? piece.typePieceId.trim()
        : typeof piece?.typePiece?.id === 'string'
          ? piece.typePiece.id.trim()
          : ''
      const typePieceId = rawTypePieceId.length > 0 ? rawTypePieceId : undefined

      const rawTypePieceLabel = typeof piece?.typePieceLabel === 'string'
        ? piece.typePieceLabel.trim()
        : typeof piece?.typePiece?.name === 'string'
          ? piece.typePiece.name.trim()
          : ''
      const typePieceLabel = rawTypePieceLabel.length > 0 ? rawTypePieceLabel : undefined

      const reference = typeof piece?.reference === 'string' && piece.reference.trim().length > 0
        ? piece.reference.trim()
        : undefined

      const rawFamilyCode = typeof piece?.familyCode === 'string'
        ? piece.familyCode.trim()
        : typeof piece?.typePiece?.code === 'string'
          ? piece.typePiece.code.trim()
          : ''
      const familyCode = rawFamilyCode.length > 0 ? rawFamilyCode : undefined

      const rawRole = typeof piece?.role === 'string' ? piece.role.trim() : ''
      const role = rawRole.length > 0 ? rawRole : undefined

      const quantity = typeof piece?.quantity === 'number' && piece.quantity >= 1 ? piece.quantity : undefined

      if (!typePieceId && !typePieceLabel && !reference && !familyCode) {
        return null
      }

      const result: ComponentModelPiece = {}
      if (role) {
        result.role = role
      }
      if (familyCode) {
        result.familyCode = familyCode
      }
      if (reference !== undefined) {
        result.reference = reference
      }
      if (typePieceId) {
        result.typePieceId = typePieceId
      }
      if (typePieceLabel) {
        result.typePieceLabel = typePieceLabel
      }
      if (quantity !== undefined) {
        result.quantity = quantity
      }
      return result
    })
    .filter((piece): piece is ComponentModelPiece => !!piece)
}

export const sanitizeProducts = (products: any[]): ComponentModelProduct[] => {
  if (!Array.isArray(products)) {
    return []
  }

  return products
    .map((product) => {
      const rawTypeProductId = typeof product?.typeProductId === 'string'
        ? product.typeProductId.trim()
        : typeof product?.typeProduct?.id === 'string'
          ? product.typeProduct.id.trim()
          : ''
      const typeProductId = rawTypeProductId.length > 0 ? rawTypeProductId : undefined

      const rawTypeProductLabel = typeof product?.typeProductLabel === 'string'
        ? product.typeProductLabel.trim()
        : typeof product?.typeProduct?.name === 'string'
          ? product.typeProduct.name.trim()
          : ''
      const typeProductLabel = rawTypeProductLabel.length > 0 ? rawTypeProductLabel : undefined

      const reference = typeof product?.reference === 'string' && product.reference.trim().length > 0
        ? product.reference.trim()
        : undefined

      const rawFamilyCode = typeof product?.familyCode === 'string'
        ? product.familyCode.trim()
        : typeof product?.typeProduct?.code === 'string'
          ? product.typeProduct.code.trim()
          : ''
      const familyCode = rawFamilyCode.length > 0 ? rawFamilyCode : undefined

      const rawRole = typeof product?.role === 'string' ? product.role.trim() : ''
      const role = rawRole.length > 0 ? rawRole : undefined

      if (!typeProductId && !typeProductLabel && !reference && !familyCode) {
        return null
      }

      const result: ComponentModelProduct = {}
      if (role) {
        result.role = role
      }
      if (familyCode) {
        result.familyCode = familyCode
      }
      if (reference !== undefined) {
        result.reference = reference
      }
      if (typeProductId) {
        result.typeProductId = typeProductId
      }
      if (typeProductLabel) {
        result.typeProductLabel = typeProductLabel
      }
      return result
    })
    .filter((product): product is ComponentModelProduct => !!product)
}

export const sanitizeSubcomponents = (components: any[]): ComponentModelStructureNode[] => {
  if (!Array.isArray(components)) {
    return []
  }

  return components
    .map((component) => {
      const rawTypeComposantId = typeof component?.typeComposantId === 'string'
        ? component.typeComposantId.trim()
        : typeof component?.typeComposant?.id === 'string'
          ? component.typeComposant.id.trim()
          : ''
      const typeComposantId = rawTypeComposantId.length > 0 ? rawTypeComposantId : undefined

      const modelId = typeof component?.modelId === 'string' && component.modelId.trim().length > 0
        ? component.modelId.trim()
        : undefined

      const familyCode = typeof component?.familyCode === 'string' && component.familyCode.trim().length > 0
        ? component.familyCode.trim()
        : undefined

      const alias = typeof component?.alias === 'string' && component.alias.trim().length > 0
        ? component.alias.trim()
        : undefined

      if (!typeComposantId && !modelId && !familyCode) {
        return null
      }

      const result: ComponentModelStructureNode = {
        subcomponents: sanitizeSubcomponents(
          Array.isArray(component?.subcomponents)
            ? component.subcomponents
            : component?.subComponents,
        ),
      }

      if (typeComposantId) {
        result.typeComposantId = typeComposantId
      }
      const typeComposantLabel = typeof component?.typeComposantLabel === 'string'
        ? component.typeComposantLabel.trim()
        : typeof component?.typeComposant?.name === 'string'
          ? component.typeComposant.name.trim()
          : ''
      if (typeComposantLabel) {
        result.typeComposantLabel = typeComposantLabel
      }
      if (modelId) {
        result.modelId = modelId
      }
      if (familyCode) {
        result.familyCode = familyCode
      }
      if (alias) {
        result.alias = alias
      }

      return result
    })
    .filter((component): component is ComponentModelStructureNode => !!component)
}
