import type { Employee } from '~/services/dto/employee'
import { CONTRACT_TYPES } from '~/services/dto/contract'
import { getEmployee } from '~/services/employees'
import { useEmployeeContractPhase } from '~/composables/useEmployeeContractPhase'
import { getEmployeeOvertimeContingent, type OvertimeContingent } from '~/services/employee-overtime-contingent'

export const useEmployeeDetailPage = () => {
  const route = useRoute()
  const employee = ref<Employee | null>(null)
  const isLoading = ref(false)
  const activeTab = ref<'contract' | 'leave' | 'rtt' | 'mileage' | 'formation' | 'bonus' | 'observation'>('contract')
  const overtimeContingent = ref<OvertimeContingent | null>(null)

  const phase = useEmployeeContractPhase(employee)

  const showLeaveTab = computed(() => employee.value?.currentContractNature !== 'INTERIM')
  const showRttTab = computed(() => phase.selectedPhase.value?.contractType !== CONTRACT_TYPES.FORFAIT)
  const isForfait = computed(() => phase.selectedPhase.value?.contractType === CONTRACT_TYPES.FORFAIT)
  // Jours à travailler du forfait : prorata exposé par le backend (218 sur année pleine,
  // moins sur une entrée en cours d'année). Fallback 218 tant que le récap n'est pas chargé.
  const forfaitWorkTargetDays = computed(() => {
    const target = leave.leaveSummary.value?.forfaitWorkTargetDays
    return (target === null || target === undefined) ? 218 : Math.round(target)
  })
  const employeeContractWorkLabel = computed(() => {
    const contract = employee.value?.contract
    if (!contract) return '-'
    if (contract.type === CONTRACT_TYPES.FORFAIT) return `Forfait - ${forfaitWorkTargetDays.value} jours`
    if (contract.weeklyHours !== null && contract.weeklyHours !== undefined) return `${contract.weeklyHours} heures`
    return contract.name || '-'
  })

  const loadOvertimeContingent = async () => {
    if (!employee.value || !showRttTab.value) {
      overtimeContingent.value = null
      return
    }
    try {
      overtimeContingent.value = await getEmployeeOvertimeContingent(employee.value.id)
    } catch {
      overtimeContingent.value = null
    }
  }

  const loadEmployee = async () => {
    const idParam = Array.isArray(route.params.id) ? route.params.id[0] : route.params.id
    const employeeId = Number(idParam)
    if (!Number.isInteger(employeeId) || employeeId <= 0) {
      return
    }

    isLoading.value = true
    try {
      employee.value = await getEmployee(employeeId)
      phase.resetToCurrent()

      if (!showLeaveTab.value && activeTab.value === 'leave') {
        activeTab.value = 'contract'
      }
      if (!showRttTab.value && activeTab.value === 'rtt') {
        activeTab.value = 'contract'
      }

      leave.resetLoaded()
      rtt.resetLoaded()
      mileage.resetLoaded()
      formation.resetLoaded()
      bonus.resetLoaded()
      observation.resetLoaded()

      if (activeTab.value === 'leave' && showLeaveTab.value) {
        await leave.loadLeaveData()
      } else if (activeTab.value === 'rtt' && showRttTab.value) {
        await rtt.loadRttData()
      } else if (activeTab.value === 'mileage') {
        await mileage.loadMileageData()
      } else if (activeTab.value === 'formation') {
        await formation.loadFormationData()
      } else if (activeTab.value === 'bonus') {
        await bonus.loadBonusData()
      } else if (activeTab.value === 'observation') {
        await observation.loadObservationData()
      } else if (showLeaveTab.value) {
        // Eager load: the header shows présence (et jours à travailler/restant pour le forfait),
        // qui proviennent du récap congés — nécessaire même quand on ouvre un autre onglet.
        await leave.loadLeaveData()
      }
      await loadOvertimeContingent()
    } finally {
      isLoading.value = false
    }
  }

  const contract = useEmployeeContract(employee, loadEmployee)
  const leave = useEmployeeLeave(employee, loadEmployee, phase.selectedPhase)
  const formatDays = (n: number) => (Number.isInteger(n) ? String(n) : (Math.round(n * 100) / 100).toFixed(2).replace('.', ','))
  // Forfait : « (présence · restant à travailler) ». restant = jours à travailler (prorata) − présence.
  const forfaitRemainingDaysLabel = computed(() => {
    if (!isForfait.value) return ''
    const presence = leave.leaveSummary.value?.presenceDaysToToday
    if (presence === undefined || presence === null) return ''
    const remaining = forfaitWorkTargetDays.value - presence
    return ` (${formatDays(presence)} présence · ${formatDays(remaining)} restants)`
  })
  // Non-forfait : « (présence) » seul (pas de cible de jours à travailler).
  const nonForfaitPresenceLabel = computed(() => {
    if (isForfait.value) return ''
    const presence = leave.leaveSummary.value?.presenceDaysToToday
    if (presence === undefined || presence === null) return ''
    return ` (${formatDays(presence)} présence)`
  })
  const overtimeContingentLabel = computed(() => {
    if (!showRttTab.value) return ''
    const c = overtimeContingent.value
    if (!c) return ''
    const h = c.paidMinutes / 60
    const hStr = Number.isInteger(h) ? String(h) : (Math.round(h * 10) / 10).toFixed(1).replace('.', ',')
    return `Total H.payés ${c.year} : ${hStr} h / ${c.capHours} h`
  })
  const overtimeContingentExceeded = computed(() => {
    const c = overtimeContingent.value
    return c ? c.paidMinutes > c.capHours * 60 : false
  })
  const rtt = useEmployeeRtt(employee, loadEmployee, phase.selectedPhase)
  const mileage = useEmployeeMileage(employee, loadEmployee)
  const formation = useEmployeeFormation(employee, loadEmployee)
  const bonus = useEmployeeBonus(employee, loadEmployee)
  const observation = useEmployeeObservation(employee, loadEmployee)

  watch(() => phase.selectedPhase.value?.id, (newId, oldId) => {
    if (newId === oldId || oldId === undefined) return
    // Bascule onglet si on entre dans une phase qui ne supporte plus le tab actuel
    if (!showRttTab.value && activeTab.value === 'rtt') {
      activeTab.value = 'leave'
    }
    // Recharger l'onglet courant ; sinon recharger quand même le récap congés
    // pour que le libellé de présence / jours à travailler du header reste à jour.
    if (activeTab.value === 'leave' && showLeaveTab.value) {
      leave.loadLeaveData()
    } else if (activeTab.value === 'rtt' && showRttTab.value) {
      rtt.loadRttData()
    } else if (showLeaveTab.value) {
      leave.loadLeaveData()
    }
  })

  watch(activeTab, (tab) => {
    if (tab === 'leave' && !leave.leaveDataLoaded.value && showLeaveTab.value) {
      leave.loadLeaveData()
    } else if (tab === 'rtt' && !rtt.rttDataLoaded.value && showRttTab.value) {
      rtt.loadRttData()
    } else if (tab === 'mileage' && !mileage.mileageDataLoaded.value) {
      mileage.loadMileageData()
    } else if (tab === 'formation' && !formation.formationDataLoaded.value) {
      formation.loadFormationData()
    } else if (tab === 'bonus' && !bonus.bonusDataLoaded.value) {
      bonus.loadBonusData()
    } else if (tab === 'observation' && !observation.observationDataLoaded.value) {
      observation.loadObservationData()
    }
  })

  onMounted(async () => {
    await Promise.all([contract.loadContracts(), contract.loadInterimAgencies()])
    await loadEmployee()
  })

  return {
    employee,
    isLoading,
    activeTab,
    showLeaveTab,
    showRttTab,
    employeeContractWorkLabel,
    forfaitRemainingDaysLabel,
    nonForfaitPresenceLabel,
    overtimeContingentLabel,
    overtimeContingentExceeded,
    ...phase,
    ...contract,
    ...leave,
    ...rtt,
    ...mileage,
    ...formation,
    ...bonus,
    ...observation
  }
}
