import { ref } from 'vue'
import { useToast } from './useToast'
import { useApi } from './useApi'
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
import { useConstructeurs, type Constructeur } from './useConstructeurs'
import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations'
import { extractCollection, extractTotal } from '~/shared/utils/apiHelpers'

export interface Composant {
  id: string
  name: string
  reference?: string | null
  description?: string | null
  typeComposantId?: string | null
  typeComposant?: { id: string; name?: string } | null
  productId?: string | null
  product?: { id: string; name?: string } | null
  constructeurs?: Constructeur[]
  constructeurIds?: string[]
  documents?: unknown[]
  createdAt?: string | null
  updatedAt?: string | null
  [key: string]: unknown
}

interface ComposantListResult {
  success: boolean
  data?: { items: Composant[]; total: number; page: number; itemsPerPage: number }
  error?: string
}

interface ComposantSingleResult {
  success: boolean
  data?: Composant
  error?: string
}

interface LoadComposantsOptions {
  search?: string
  page?: number
  itemsPerPage?: number
  orderBy?: string
  orderDir?: 'asc' | 'desc'
  typeName?: string
  typeComposantId?: string
  force?: boolean
}

const composants = ref<Composant[]>([])
const total = ref(0)
const loading = ref(false)
const loaded = ref(false)

export function useComposants() {
  const { showSuccess } = useToast()
  const { get, post, patch, delete: del } = useApi()
  const { ensureConstructeurs } = useConstructeurs()

  const withResolvedConstructeurs = async (composant: Composant): Promise<Composant> => {
    if (!composant || typeof composant !== 'object') {
      return composant
    }
    if (!composant.typeComposantId) {
      const typeComposantId = extractRelationId(composant.typeComposant)
      if (typeComposantId) {
        composant.typeComposantId = typeComposantId
      }
    }
    if (!composant.productId) {
      const productId = extractRelationId(composant.product)
      if (productId) {
        composant.productId = productId
      }
    }
    const ids = uniqueConstructeurIds(
      composant.constructeurIds,
      composant.constructeurs,
    )
    const hasResolvedConstructeurs =
      Array.isArray(composant.constructeurs) &&
      composant.constructeurs.length > 0 &&
      composant.constructeurs.every((item) => item && typeof item === 'object')

    if (ids.length && !hasResolvedConstructeurs) {
      const resolved = await ensureConstructeurs(ids)
      if (resolved.length) {
        composant.constructeurs = resolved
        composant.constructeurIds = ids
      }
    }
    return composant
  }

  const loadComposants = async (options: LoadComposantsOptions = {}): Promise<ComposantListResult> => {
    const {
      search = '',
      page = 1,
      itemsPerPage = 30,
      orderBy = 'name',
      orderDir = 'asc',
      typeName,
      typeComposantId,
      force = false,
    } = options

    if (!force && loaded.value && !search && !typeName && !typeComposantId && page === 1) {
      return {
        success: true,
        data: { items: composants.value, total: total.value, page, itemsPerPage },
      }
    }

    if (!typeComposantId && loading.value) {
      return {
        success: true,
        data: { items: composants.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('search', search.trim())
      }

      if (typeName && typeName.trim()) {
        params.set('typeComposant.name', typeName.trim())
      }

      if (typeComposantId) {
        params.set('typeComposant', typeComposantId)
      }

      params.set(`order[${orderBy}]`, orderDir)

      const result = await get(`/composants?${params.toString()}`)
      if (result.success) {
        const items = extractCollection(result.data)
        const enrichedItems = await Promise.all(items.map((item) => withResolvedConstructeurs(item)))
        const resultTotal = extractTotal(result.data, items.length)

        if (!typeComposantId) {
          composants.value = enrichedItems
          total.value = resultTotal
          loaded.value = true
        }

        return {
          success: true,
          data: {
            items: enrichedItems,
            total: resultTotal,
            page,
            itemsPerPage,
          },
        }
      }
      return result as ComposantListResult
    } catch (error) {
      console.error('Erreur lors du chargement des composants:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const createComposant = async (composantData: Partial<Composant>): Promise<ComposantSingleResult> => {
    loading.value = true
    try {
      const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = composantData as any
      const normalizedPayload = normalizeRelationIds(cleanPayload)
      const result = await post('/composants', normalizedPayload)
      if (result.success && result.data) {
        const enriched = await withResolvedConstructeurs(result.data as Composant)
        composants.value.unshift(enriched)
        total.value += 1
        const definition = (composantData as Record<string, unknown>)?.definition as Record<string, unknown> | undefined
        const displayName =
          (result.data as Composant)?.name ||
          (definition?.name as string | undefined) ||
          composantData?.name ||
          'Composant'
        showSuccess(`Composant "${displayName}" créé avec succès`)
        return { success: true, data: enriched }
      }
      return { success: false, error: result.error }
    } catch (error) {
      console.error('Erreur lors de la création du composant:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const updateComposantData = async (id: string, composantData: Partial<Composant>): Promise<ComposantSingleResult> => {
    loading.value = true
    try {
      const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = composantData as any
      const normalizedPayload = normalizeRelationIds(cleanPayload)
      const result = await patch(`/composants/${id}`, normalizedPayload)
      if (result.success && result.data) {
        const updated = await withResolvedConstructeurs(result.data as Composant)
        const index = composants.value.findIndex((comp) => comp.id === id)
        if (index !== -1) {
          composants.value[index] = updated
        }
        showSuccess(`Composant "${updated?.name || composantData.name || ''}" mis à 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 du composant:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const deleteComposant = async (id: string): Promise<ComposantSingleResult> => {
    loading.value = true
    try {
      const result = await del(`/composants/${id}`)
      if (result.success) {
        const deletedComposant = composants.value.find((comp) => comp.id === id)
        composants.value = composants.value.filter((comp) => comp.id !== id)
        total.value = Math.max(0, total.value - 1)
        showSuccess(`Composant "${deletedComposant?.name || 'inconnu'}" supprimé avec succès`)
        return { success: true }
      }
      return { success: false, error: result.error }
    } catch (error) {
      console.error('Erreur lors de la suppression du composant:', error)
      return { success: false, error: (error as Error).message }
    } finally {
      loading.value = false
    }
  }

  const getComposants = () => composants.value
  const isLoading = () => loading.value

  const clearComposantsCache = () => {
    composants.value = []
    total.value = 0
    loaded.value = false
  }

  return {
    composants,
    total,
    loading,
    loaded,
    loadComposants,
    createComposant,
    updateComposant: updateComposantData,
    deleteComposant,
    getComposants,
    isLoading,
    clearComposantsCache,
  }
}
