import { ref } from 'vue'
import { updateTech } from 'src/api/dispatch'
import { toErpStatus } from 'src/composables/useHelpers'

const ABSENCE_REASONS = [
  { value: 'vacation', label: 'Vacances', icon: '🏖️' },
  { value: 'sick', label: 'Maladie', icon: '🤒' },
  { value: 'personal', label: 'Personnel', icon: '🏠' },
  { value: 'training', label: 'Formation', icon: '📚' },
  { value: 'injury', label: 'Blessure', icon: '🩹' },
  { value: 'other', label: 'Autre', icon: '📋' },
]

export { ABSENCE_REASONS }

export function useTechManagement (store, invalidateRoutes) {
  const editingTech = ref(null)
  const newTechName = ref('')
  const newTechPhone = ref('')
  const newTechDevice = ref('')
  const addingTech = ref(false)

  // Absence modal state
  const absenceModalOpen = ref(false)
  const absenceModalTech = ref(null)
  const absenceForm = ref({ reason: 'vacation', from: '', until: '', jobAction: 'unassign' })
  const absenceProcessing = ref(false)

  async function saveTechField (tech, field, value) {
    const trimmed = typeof value === 'string' ? value.trim() : value
    if (field === 'full_name') {
      if (!trimmed || trimmed === tech.fullName) return
      tech.fullName = trimmed
    } else if (field === 'status') {
      tech.status = trimmed
      tech.active = trimmed !== 'inactive' && trimmed !== 'off'
    } else if (field === 'phone') {
      if (trimmed === tech.phone) return
      tech.phone = trimmed
    }
    const saveValue = field === 'status' ? toErpStatus(trimmed) : trimmed
    try { await updateTech(tech.name || tech.id, { [field]: saveValue }) }
    catch (_e) { /* save failed */ }
  }

  async function addTech (extraFields = {}) {
    const name = newTechName.value.trim()
    if (!name || addingTech.value) return
    addingTech.value = true
    try {
      const tech = await store.createTechnician({
        full_name: name,
        phone: newTechPhone.value.trim() || '',
        traccar_device_id: newTechDevice.value || '',
        ...extraFields,
      })
      newTechName.value = ''
      newTechPhone.value = ''
      newTechDevice.value = ''
      if (tech.traccarDeviceId) await store.pollGps()
    } catch (e) {
      const msg = e?.message || String(e)
      alert('Erreur création technicien:\n' + msg.replace(/<[^>]+>/g, ''))
    }
    finally { addingTech.value = false }
  }

  // ── Absence flow ──

  function openAbsenceModal (tech) {
    absenceModalTech.value = tech
    const today = new Date().toISOString().slice(0, 10)
    absenceForm.value = {
      reason: tech.absenceReason || 'vacation',
      from: tech.absenceFrom || today,
      until: tech.absenceUntil || '',
      jobAction: 'unassign',  // 'unassign' | 'reassign'
    }
    absenceModalOpen.value = true
  }

  async function confirmAbsence () {
    const tech = absenceModalTech.value
    if (!tech) return
    absenceProcessing.value = true

    try {
      const { reason, from, until, jobAction } = absenceForm.value

      // 1. Handle assigned jobs
      const linkedJobs = store.jobs.filter(j => j.assignedTech === tech.id)
      if (linkedJobs.length > 0) {
        if (jobAction === 'unassign') {
          for (const job of linkedJobs) {
            await store.unassignJob(job.id)
          }
        }
        // 'reassign' is handled by the user manually after — jobs stay visible in unassigned pool
      }

      // 2. Update tech status + absence fields
      tech.status = 'off'
      tech.active = false
      tech.absenceReason = reason
      tech.absenceFrom = from || null
      tech.absenceUntil = until || null
      tech.absenceStartTime = null
      tech.absenceEndTime = null

      await updateTech(tech.name || tech.id, {
        status: toErpStatus('off'),
        absence_reason: reason,
        absence_from: from || '',
        absence_until: until || '',
        absence_start_time: '',
        absence_end_time: '',
      })

      absenceModalOpen.value = false
    } catch (e) {
      const msg = e?.message || String(e)
      alert('Erreur: ' + msg.replace(/<[^>]+>/g, ''))
    }
    absenceProcessing.value = false
  }

  async function endAbsence (tech) {
    tech.status = 'available'
    tech.active = true
    tech.absenceReason = ''
    tech.absenceFrom = null
    tech.absenceUntil = null
    tech.absenceStartTime = null
    tech.absenceEndTime = null

    try {
      await updateTech(tech.name || tech.id, {
        status: toErpStatus('available'),
        absence_reason: '',
        absence_from: '',
        absence_until: '',
        absence_start_time: '',
        absence_end_time: '',
      })
    } catch (_e) {
      tech.status = 'off'
      tech.active = false
    }
  }

  // Permanent deactivation (non-dispatchable resource like support staff)
  async function deactivateTech (tech) {
    if (!confirm(`Désactiver ${tech.fullName} du dispatch ?\n\nLa ressource ne sera plus dispatchable mais reste dans le système.`)) return
    try {
      const linkedJobs = store.jobs.filter(j => j.assignedTech === tech.id)
      for (const job of linkedJobs) await store.unassignJob(job.id)
      tech.status = 'inactive'
      tech.active = false
      tech.absenceReason = ''
      tech.absenceFrom = null
      tech.absenceUntil = null
      tech.absenceStartTime = null
      tech.absenceEndTime = null
      await updateTech(tech.name || tech.id, { status: toErpStatus('inactive'), absence_reason: '', absence_from: '', absence_until: '', absence_start_time: '', absence_end_time: '' })
    } catch (e) {
      alert('Erreur: ' + (e?.message || String(e)).replace(/<[^>]+>/g, ''))
    }
  }

  async function reactivateTech (tech) {
    tech.status = 'available'
    tech.active = true
    tech.absenceReason = ''
    tech.absenceFrom = null
    tech.absenceUntil = null
    tech.absenceStartTime = null
    tech.absenceEndTime = null
    try {
      await updateTech(tech.name || tech.id, { status: toErpStatus('available'), absence_reason: '', absence_from: '', absence_until: '', absence_start_time: '', absence_end_time: '' })
    } catch (_e) {
      tech.status = 'inactive'
      tech.active = false
    }
  }

  async function removeTech (tech) {
    if (!confirm(`⚠ SUPPRIMER DÉFINITIVEMENT ${tech.fullName} ?\n\nCette action est irréversible.`)) return
    try {
      const linkedJobs = store.jobs.filter(j => j.assignedTech === tech.id)
      for (const job of linkedJobs) await store.unassignJob(job.id)
      await store.deleteTechnician(tech.id)
    } catch (e) {
      alert('Erreur: ' + (e?.message || String(e)).replace(/<[^>]+>/g, ''))
    }
  }

  async function saveWeeklySchedule (tech, schedule) {
    tech.weeklySchedule = { ...schedule }
    try {
      await updateTech(tech.name || tech.id, { weekly_schedule: JSON.stringify(schedule) })
    } catch (e) {
      alert('Erreur: ' + (e?.message || String(e)).replace(/<[^>]+>/g, ''))
    }
  }

  async function saveTraccarLink (tech, deviceId) {
    tech.traccarDeviceId = deviceId || null
    tech.gpsCoords = null
    tech.gpsOnline = false
    await updateTech(tech.name || tech.id, { traccar_device_id: deviceId || '' })
    await store.pollGps()
    invalidateRoutes()
  }

  // Persist a tech's "home base" coordinates (where they start the day from
  // when no live GPS is available). Coords are stored in ERPNext as
  // separate Float fields `latitude` / `longitude`; the dispatch store
  // reads them back as `tech.coords = [longitude, latitude]` (the
  // [lng, lat] order is what Mapbox/MapLibre + GeoJSON expect).
  // Route optimization is recomputed because changing the start point
  // shifts every tech's optimal job sequence for the day.
  async function saveTechHome (tech, longitude, latitude) {
    const lng = Number(longitude); const lat = Number(latitude)
    if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
      throw new Error('Coordonnées invalides')
    }
    tech.coords = [lng, lat]
    await updateTech(tech.name || tech.id, { longitude: lng, latitude: lat })
    invalidateRoutes()
  }

  return {
    editingTech, newTechName, newTechPhone, newTechDevice, addingTech,
    absenceModalOpen, absenceModalTech, absenceForm, absenceProcessing,
    saveTechField, addTech,
    openAbsenceModal, confirmAbsence, endAbsence,
    deactivateTech, reactivateTech, removeTech, saveTraccarLink, saveWeeklySchedule, saveTechHome,
    ABSENCE_REASONS,
  }
}
