import { ref } from 'vue'
import { useApi } from './useApi'
import { useToast } from './useToast'
import { extractCollection, extractTotal } from '~/shared/utils/apiHelpers'

export interface Document {
  id: string
  name: string
  filename: string
  mimeType: string
  size: number
  fileUrl: string
  downloadUrl: string
  type?: string
  /** @deprecated Legacy Base64 data URI — use fileUrl instead */
  path?: string
  createdAt?: string
  siteId?: string
  machineId?: string
  composantId?: string
  productId?: string
  pieceId?: string
  site?: { id: string; name?: string } | null
  machine?: { id: string; name?: string } | null
  composant?: { id: string; name?: string } | null
  piece?: { id: string; name?: string } | null
  product?: { id: string; name?: string } | null
}

export interface UploadContext {
  siteId?: string
  machineId?: string
  composantId?: string
  productId?: string
  pieceId?: string
  type?: string
}

export interface DocumentResult {
  success: boolean
  data?: Document | Document[]
  error?: string
}

interface LoadDocumentsOptions {
  search?: string
  page?: number
  itemsPerPage?: number
  orderBy?: string
  orderDir?: 'asc' | 'desc'
  attachmentFilter?: string
  type?: string
  force?: boolean
}

const documents = ref<Document[]>([])
const total = ref(0)
const loading = ref(false)
const loaded = ref(false)

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

  const loadFromEndpoint = async (
    endpoint: string,
    { updateStore = false, itemsPerPage }: { updateStore?: boolean; itemsPerPage?: number } = {},
  ): Promise<DocumentResult> => {
    loading.value = true
    try {
      const url = itemsPerPage ? `${endpoint}${endpoint.includes('?') ? '&' : '?'}itemsPerPage=${itemsPerPage}` : endpoint
      const result = await get(url)
      if (result.success) {
        const data = extractCollection(result.data)
        if (updateStore) {
          documents.value = data
        }
        return { success: true, data }
      }
      if (result.error) {
        showError(result.error)
      }
      return result as DocumentResult
    } catch (error) {
      const err = error as Error
      console.error(`Erreur lors du chargement des documents (${endpoint}):`, error)
      showError('Impossible de charger les documents')
      return { success: false, error: err.message }
    } finally {
      loading.value = false
    }
  }

  const loadDocuments = async (options: LoadDocumentsOptions = {}): Promise<DocumentResult> => {
    const {
      search = '',
      page = 1,
      itemsPerPage = 30,
      orderBy = 'createdAt',
      orderDir = 'desc',
      attachmentFilter = 'all',
      type = 'all',
      force = false,
    } = options

    if (!force && loaded.value && !search && page === 1 && attachmentFilter === 'all' && type === 'all') {
      return { success: true, data: documents.value }
    }

    if (loading.value) {
      return { success: true, data: documents.value }
    }

    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())
      }

      if (attachmentFilter && attachmentFilter !== 'all') {
        params.set(`exists[${attachmentFilter}]`, 'true')
      }

      if (type && type !== 'all') {
        params.set('type', type)
      }

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

      const result = await get(`/documents?${params.toString()}`)
      if (result.success) {
        const items = extractCollection(result.data)
        documents.value = items
        total.value = extractTotal(result.data, items.length)
        loaded.value = true
        return { success: true, data: items }
      }
      if (result.error) {
        showError(result.error)
      }
      return result as DocumentResult
    } catch (error) {
      const err = error as Error
      console.error('Erreur lors du chargement des documents:', error)
      showError('Impossible de charger les documents')
      return { success: false, error: err.message }
    } finally {
      loading.value = false
    }
  }

  const loadDocumentsBySite = async (
    siteId: string,
    options: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!siteId) {
      return { success: false, error: 'Aucun site sélectionné' }
    }
    return loadFromEndpoint(`/documents/site/${siteId}`, { updateStore: options.updateStore ?? false })
  }

  const loadDocumentsByMachine = async (
    machineId: string,
    options: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!machineId) {
      return { success: false, error: 'Aucune machine sélectionnée' }
    }
    return loadFromEndpoint(`/documents/machine/${machineId}`, { updateStore: options.updateStore ?? false })
  }

  const loadDocumentsByComponent = async (
    componentId: string,
    options: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!componentId) {
      return { success: false, error: 'Aucun composant sélectionné' }
    }
    return loadFromEndpoint(`/documents/composant/${componentId}`, { updateStore: options.updateStore ?? false })
  }

  const loadDocumentsByProduct = async (
    productId: string,
    options: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!productId) {
      return { success: false, error: 'Aucun produit sélectionné' }
    }
    return loadFromEndpoint(`/documents/product/${productId}`, { updateStore: options.updateStore ?? false })
  }

  const loadDocumentsByPiece = async (
    pieceId: string,
    options: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!pieceId) {
      return { success: false, error: 'Aucune pièce sélectionnée' }
    }
    return loadFromEndpoint(`/documents/piece/${pieceId}`, { updateStore: options.updateStore ?? false })
  }

  const uploadDocuments = async (
    { files, context = {} }: { files: File[]; context?: UploadContext },
    { updateStore = false }: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!files.length) {
      return { success: false, error: 'Aucun fichier sélectionné' }
    }

    loading.value = true
    const created: Document[] = []

    try {
      for (const file of files) {
        const formData = new FormData()
        formData.append('file', file)
        formData.append('name', file.name)
        if (context.type) formData.append('type', context.type)

        if (context.siteId) formData.append('siteId', context.siteId)
        if (context.machineId) formData.append('machineId', context.machineId)
        if (context.composantId) formData.append('composantId', context.composantId)
        if (context.productId) formData.append('productId', context.productId)
        if (context.pieceId) formData.append('pieceId', context.pieceId)

        const result = await postFormData('/documents', formData)
        if (result.success) {
          created.push(result.data as Document)
          showSuccess(`Document "${file.name}" ajouté`)
        } else if (result.error) {
          showError(`Erreur sur ${file.name} : ${result.error}`)
        }
      }

      if (created.length) {
        if (updateStore) {
          documents.value = [...created, ...documents.value]
        }
        return { success: true, data: created }
      }

      return { success: false, error: 'Aucun document ajouté' }
    } catch (error) {
      const err = error as Error
      console.error("Erreur lors de l'upload des documents:", error)
      showError("Échec de l'ajout des documents")
      return { success: false, error: err.message }
    } finally {
      loading.value = false
    }
  }

  const deleteDocument = async (
    id: string | number,
    { updateStore = false }: { updateStore?: boolean } = {},
  ): Promise<DocumentResult> => {
    if (!id) {
      return { success: false, error: 'Identifiant manquant' }
    }

    loading.value = true
    try {
      const result = await del(`/documents/${id}`)
      if (result.success) {
        if (updateStore) {
          documents.value = documents.value.filter((doc) => doc.id !== id)
        }
        showSuccess('Document supprimé')
      }
      return result as DocumentResult
    } catch (error) {
      const err = error as Error
      console.error('Erreur lors de la suppression du document:', error)
      showError('Impossible de supprimer le document')
      return { success: false, error: err.message }
    } finally {
      loading.value = false
    }
  }

  const updateDocument = async (
    id: string,
    data: { name?: string; type?: string },
  ): Promise<DocumentResult> => {
    loading.value = true
    try {
      const result = await patch(`/documents/${id}`, data)
      if (result.success && result.data) {
        const updated = result.data as Document
        const index = documents.value.findIndex((doc) => doc.id === id)
        if (index !== -1) {
          documents.value[index] = { ...documents.value[index], ...updated }
        }
        showSuccess('Document mis à jour')
        return { success: true, data: updated }
      }
      if (result.error) showError(result.error)
      return result as DocumentResult
    } catch (error) {
      const err = error as Error
      showError('Impossible de mettre à jour le document')
      return { success: false, error: err.message }
    } finally {
      loading.value = false
    }
  }

  return {
    documents,
    total,
    loading,
    loaded,
    loadDocuments,
    loadDocumentsBySite,
    loadDocumentsByMachine,
    loadDocumentsByComponent,
    loadDocumentsByPiece,
    loadDocumentsByProduct,
    uploadDocuments,
    updateDocument,
    deleteDocument,
  }
}
