import { computed, onMounted, reactive, ref, watch } from 'vue'
import { navigateTo, useRoute } from '#imports'
import { useSites } from '~/composables/useSites'
import { useToast } from '~/composables/useToast'
import { humanizeError } from '~/shared/utils/errorMessages'
import { useDocuments } from '~/composables/useDocuments'
import { useConfirm } from '~/composables/useConfirm'
import { getFileIcon } from '~/utils/fileIcons'
import { canPreviewDocument } from '~/utils/documentPreview'

type SiteForm = {
  name: string
  color: string
  contactName: string
  contactPhone: string
  contactAddress: string
  contactPostalCode: string
  contactCity: string
}

type SiteDocument = {
  id: string
  name?: string
  filename?: string
  mimeType?: string
  size?: number
  path?: string
  fileUrl?: string
  downloadUrl?: string
}

type SiteWithDocuments = {
  id: string
  name?: string
  color?: string
  contactName?: string
  contactPhone?: string
  contactAddress?: string
  contactPostalCode?: string
  contactCity?: string
  documents?: SiteDocument[]
  machines?: Array<unknown>
}

export function useSiteManagement() {
  const route = useRoute()
  const { showError, showSuccess } = useToast()
  const { sites, loading, loadSites, createSite, updateSite, deleteSite } = useSites()
  const { uploadDocuments, deleteDocument, loadDocumentsBySite } = useDocuments()
  const { confirm: confirmDialog } = useConfirm()

  const showAddSiteModal = ref(false)
  const showEditSiteModal = ref(false)

  const siteBeingEdited = ref<SiteWithDocuments | null>(null)

  const newSite = reactive<SiteForm>({
    name: '',
    color: '',
    contactName: '',
    contactPhone: '',
    contactAddress: '',
    contactPostalCode: '',
    contactCity: ''
  })

  const editSiteForm = reactive<SiteForm>({
    name: '',
    color: '',
    contactName: '',
    contactPhone: '',
    contactAddress: '',
    contactPostalCode: '',
    contactCity: ''
  })

  const selectedFiles = ref<File[]>([])
  const uploadingDocuments = ref(false)
  const previewDocument = ref<SiteDocument | null>(null)
  const previewVisible = ref(false)

  const siteDocuments = computed(() => siteBeingEdited.value?.documents || [])
  const documentIcon = (doc: SiteDocument) =>
    getFileIcon({ name: doc.filename || doc.name, mime: doc.mimeType })

  const resetNewSite = () => {
    newSite.name = ''
    newSite.color = ''
    newSite.contactName = ''
    newSite.contactPhone = ''
    newSite.contactAddress = ''
    newSite.contactPostalCode = ''
    newSite.contactCity = ''
  }

  const closeCreateModal = () => {
    showAddSiteModal.value = false
    resetNewSite()
  }

  const openCreateSiteModal = () => {
    resetNewSite()
    showAddSiteModal.value = true
  }

  const handleCreateSite = async () => {
    const result = await createSite({
      name: newSite.name,
      color: newSite.color,
      contactName: newSite.contactName,
      contactPhone: newSite.contactPhone,
      contactAddress: newSite.contactAddress,
      contactPostalCode: newSite.contactPostalCode,
      contactCity: newSite.contactCity
    })

    if (result.success) {
      closeCreateModal()
    }
  }

  const editSite = (site: SiteWithDocuments) => {
    siteBeingEdited.value = site
    editSiteForm.name = site.name || ''
    editSiteForm.color = site.color || ''
    editSiteForm.contactName = site.contactName || ''
    editSiteForm.contactPhone = site.contactPhone || ''
    editSiteForm.contactAddress = site.contactAddress || ''
    editSiteForm.contactPostalCode = site.contactPostalCode || ''
    editSiteForm.contactCity = site.contactCity || ''
    selectedFiles.value = []
    refreshSiteDocuments(site.id)
    showEditSiteModal.value = true
  }

  const closeEditModal = () => {
    showEditSiteModal.value = false
    siteBeingEdited.value = null
    selectedFiles.value = []
  }

  const updateSiteInCollection = (id: string, updated: Partial<SiteWithDocuments>) => {
    const index = sites.value.findIndex(site => site.id === id)
    if (index !== -1) {
      sites.value[index] = {
        ...sites.value[index],
        ...updated,
        id,
      }
    }
  }

  const handleUpdateSite = async () => {
    if (!siteBeingEdited.value) return

    const baseUpdate = {
      name: editSiteForm.name,
      color: editSiteForm.color,
      contactName: editSiteForm.contactName,
      contactPhone: editSiteForm.contactPhone,
      contactAddress: editSiteForm.contactAddress,
      contactPostalCode: editSiteForm.contactPostalCode,
      contactCity: editSiteForm.contactCity
    }

    const result = await updateSite(siteBeingEdited.value.id, baseUpdate)

    if (!result.success) return

    let uploadedDocuments: SiteDocument[] = []
    const existingDocuments = siteBeingEdited.value?.documents || []
    if (selectedFiles.value.length) {
      uploadingDocuments.value = true
      const uploadResult = await uploadDocuments(
        {
          files: selectedFiles.value,
          context: { siteId: siteBeingEdited.value.id }
        },
        { updateStore: false }
      )
      uploadingDocuments.value = false

      if (uploadResult.success && uploadResult.data) {
        const data = uploadResult.data
        uploadedDocuments = (Array.isArray(data) ? data : [data]) as SiteDocument[]
        selectedFiles.value = []
      }
    }

    if (uploadedDocuments.length) {
      const mergedDocuments = [...uploadedDocuments, ...existingDocuments]
      if (siteBeingEdited.value) {
        siteBeingEdited.value.documents = mergedDocuments
      }
      updateSiteInCollection(siteBeingEdited.value.id, {
        ...baseUpdate,
        documents: mergedDocuments
      })
    } else {
      updateSiteInCollection(siteBeingEdited.value.id, baseUpdate)
    }

    closeEditModal()
  }

  const handleRemoveSiteDocument = async (documentId: string) => {
    if (!documentId) return

    const result = await deleteDocument(documentId, { updateStore: false })
    if (!result.success) return

    if (siteBeingEdited.value) {
      siteBeingEdited.value.documents = (siteBeingEdited.value.documents || []).filter(
        doc => doc.id !== documentId
      )
      updateSiteInCollection(siteBeingEdited.value.id, {
        documents: siteBeingEdited.value.documents
      })
    }
  }

  const downloadDocument = (doc: SiteDocument) => {
    if (doc?.downloadUrl) {
      window.open(doc.downloadUrl, '_blank')
      return
    }

    const url = doc?.fileUrl || doc?.path
    if (!url) return

    if (url.startsWith('data:')) {
      const link = document.createElement('a')
      link.href = url
      link.download = doc.filename || doc.name || 'document'
      link.click()
      return
    }

    window.open(url, '_blank')
  }

  const openPreview = (doc: SiteDocument) => {
    if (!canPreviewDocument(doc)) return
    previewDocument.value = doc
    previewVisible.value = true
  }

  const closePreview = () => {
    previewVisible.value = false
    previewDocument.value = null
  }

  const refreshSiteDocuments = async (siteId: string) => {
    if (!siteId) return
    const result = await loadDocumentsBySite(siteId, { updateStore: false })
    if (result.success && siteBeingEdited.value && siteBeingEdited.value.id === siteId) {
      const cloned = Array.isArray(result.data) ? [...result.data] : []
      siteBeingEdited.value.documents = cloned
      updateSiteInCollection(siteId, { documents: cloned })
    }
  }

  const formatSize = (size?: number | null) => {
    if (size === undefined || size === null) return '—'
    if (size === 0) return '0 B'
    const units = ['B', 'KB', 'MB', 'GB']
    const index = Math.min(units.length - 1, Math.floor(Math.log(size) / Math.log(1024)))
    const formatted = size / Math.pow(1024, index)
    return `${formatted.toFixed(1)} ${units[index]}`
  }

  const confirmDeleteSite = async (site: SiteWithDocuments) => {
    if (
      !await confirmDialog({
        message: `Êtes-vous sûr de vouloir supprimer le site "${site.name}" ? Cette action est irréversible.`,
      })
    ) {
      return
    }

    try {
      const result = await deleteSite(site.id)
      if (result.success) {
        showSuccess(`Site "${site.name}" supprimé avec succès`)
      } else {
        showError(`Impossible de supprimer le site : ${humanizeError(result.error)}`)
      }
    } catch (error: any) {
      showError(`Impossible de supprimer le site : ${humanizeError(error.message)}`)
    }
  }

  onMounted(async () => {
    await loadSites()
  })

  watch(
    () => route.query.add,
    async (shouldOpen) => {
      if (shouldOpen === 'true') {
        openCreateSiteModal()
        await navigateTo('/sites', { replace: true })
      }
    },
    { immediate: true }
  )

  return {
    sites,
    loading,
    showAddSiteModal,
    showEditSiteModal,
    siteBeingEdited,
    newSite,
    editSiteForm,
    selectedFiles,
    uploadingDocuments,
    previewDocument,
    previewVisible,
    siteDocuments,
    documentIcon,
    openCreateSiteModal,
    closeCreateModal,
    handleCreateSite,
    editSite,
    handleUpdateSite,
    closeEditModal,
    handleRemoveSiteDocument,
    downloadDocument,
    openPreview,
    closePreview,
    refreshSiteDocuments,
    formatSize,
    confirmDeleteSite,
    canPreviewDocument
  }
}
