<template>
  <div>
    <div class="flex flex-wrap items-center justify-between gap-4 pb-10 no-print">
      <h1 class="text-4xl font-bold text-primary-500">Calendrier des absences</h1>
      <div class="flex items-center gap-3">
        <select
          v-model="selectedMonth"
          class="rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
        >
          <option v-for="month in months" :key="month.value" :value="month.value">
            {{ month.label }}
          </option>
        </select>
        <select
          v-model="selectedYear"
          class="rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
        >
          <option v-for="year in years" :key="year" :value="year">
            {{ year }}
          </option>
        </select>
        <button
          type="button"
          class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
          @click="openCreateFromToday"
        >
          Ajouter une absence
        </button>
        <button
          type="button"
          class="rounded-lg border border-neutral-200 px-4 py-2 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
          @click="printMonth('1')"
        >
          Imprimer 1 mois
        </button>
        <button
          type="button"
          class="rounded-lg border border-neutral-200 px-4 py-2 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
          @click="printMonth('3')"
        >
          Imprimer 3 mois
        </button>
      </div>
    </div>

    <div class="max-h-[80vh] overflow-auto rounded-lg border border-neutral-200 bg-white no-print">
      <div class="min-w-[900px]">
        <div class="grid" :style="gridStyle">
          <div class="sticky left-0 z-10 border-b border-neutral-200 bg-tertiary-500 px-4 py-3 text-md font-semibold text-neutral-700">
            Employés
          </div>
          <div
            v-for="day in daysInMonth"
            :key="day.date"
            class="border-b border-neutral-200 bg-tertiary-500 px-2 py-3 text-center text-xs font-semibold text-neutral-700"
          >
            <div>{{ day.label }}</div>
            <div class="text-[10px] text-neutral-500">{{ day.weekday }}</div>
          </div>

          <template v-for="employee in employees" :key="employee.id">
            <div class="sticky left-0 z-10 border-b border-neutral-100 bg-white px-4 py-3 text-md font-semibold text-neutral-800">
              {{ employee.firstName }} {{ employee.lastName }}
            </div>
            <div
              v-for="day in daysInMonth"
              :key="employee.id + '-' + day.date"
              class="border-b border-neutral-100 px-2 py-2 text-center text-xs text-neutral-800"
            >
              <button
                type="button"
                class="flex h-8 w-full items-center justify-center rounded-md border border-neutral-200 text-[11px] font-semibold text-neutral-800 hover:border-primary-500/40"
                :style="getCellStyle(employee.id, day.date)"
                @click="openCreate(employee, day.date)"
              >
                <span v-if="getCellCode(employee.id, day.date)">
                  {{ getCellCode(employee.id, day.date) }}
                </span>
              </button>
            </div>
          </template>
        </div>
      </div>
    </div>

    <div v-if="printMode" class="print-only space-y-8">
      <div
        v-for="month in printMonths"
        :key="`${month.year}-${month.month}`"
        class="overflow-hidden rounded-lg border border-neutral-200 bg-white"
      >
        <div class="flex items-center justify-between border-b border-neutral-200 bg-tertiary-500 px-6 py-3 text-lg font-bold text-neutral-700">
          <span>Calendrier {{ month.label }} {{ month.year }}</span>
        </div>
        <div class="overflow-auto">
          <div class="min-w-[900px]">
            <div class="grid" :style="getGridStyle(month.days.length)">
              <div class="sticky left-0 z-10 border-b border-neutral-200 bg-tertiary-500 px-4 py-3 text-md font-semibold text-neutral-700">
                Employé
              </div>
              <div
                v-for="day in month.days"
                :key="day.date"
                class="border-b border-neutral-200 bg-tertiary-500 px-2 py-3 text-center text-xs font-semibold text-neutral-700"
              >
                <div>{{ day.label }}</div>
                <div class="text-[10px] text-neutral-500">{{ day.weekday }}</div>
              </div>

              <template v-for="employee in employees" :key="employee.id">
                <div class="sticky left-0 z-10 border-b border-neutral-100 bg-white px-4 py-3 text-md font-semibold text-neutral-800">
                  {{ employee.firstName }} {{ employee.lastName }}
                </div>
                <div
                  v-for="day in month.days"
                  :key="employee.id + '-' + day.date"
                  class="border-b border-neutral-100 px-2 py-2 text-center text-xs text-neutral-800"
                >
                  <div
                    class="flex h-8 w-full items-center justify-center rounded-md border border-neutral-200 text-[11px] font-semibold text-neutral-800"
                    :style="getCellStyle(employee.id, day.date)"
                  >
                    <span v-if="getCellCode(employee.id, day.date)">
                      {{ getCellCode(employee.id, day.date) }}
                    </span>
                  </div>
                </div>
              </template>
            </div>
          </div>
        </div>
      </div>
    </div>

    <AppDrawer v-model="isDrawerOpen" title="Nouvelle absence">
      <form class="space-y-4" @submit.prevent="handleSubmit">
        <div>
          <label class="text-md font-semibold text-neutral-700" for="employee">Employé</label>
          <select
            id="employee"
            v-model="form.employeeId"
            class="mt-2 w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
          >
            <option value="" disabled>Choisir un employé</option>
            <option v-for="employee in employees" :key="employee.id" :value="employee.id">
              {{ employee.firstName }} {{ employee.lastName }}
            </option>
          </select>
        </div>

        <div>
          <label class="text-md font-semibold text-neutral-700" for="type">Type d'absence</label>
          <select
            id="type"
            v-model="form.typeId"
            class="mt-2 w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
          >
            <option value="" disabled>Choisir un type</option>
            <option v-for="type in absenceTypes" :key="type.id" :value="type.id">
              {{ type.label }} ({{ type.code }})
            </option>
          </select>
        </div>

        <div class="grid grid-cols-2 gap-4">
          <div>
            <label class="text-md font-semibold text-neutral-700" for="start-date">Date de début</label>
            <input
              id="start-date"
              v-model="form.startDate"
              type="date"
              class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900"
            />
          </div>
          <div>
            <label class="text-md font-semibold text-neutral-700" for="end-date">Date de fin</label>
            <input
              id="end-date"
              v-model="form.endDate"
              type="date"
              class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900"
            />
          </div>
        </div>

        <div>
          <label class="text-md font-semibold text-neutral-700" for="comment">Commentaire</label>
          <textarea
            id="comment"
            v-model="form.comment"
            rows="3"
            class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-md text-neutral-900"
          />
        </div>

        <div class="flex justify-end gap-3 pt-2">
          <button
            v-if="editingAbsence"
            type="button"
            class="rounded-lg border border-red-200 px-4 py-2 text-md font-semibold text-red-600 hover:bg-red-50"
            @click="handleDelete"
          >
            Supprimer
          </button>
          <button
            type="button"
            class="rounded-lg border border-neutral-200 px-4 py-2 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
            @click="closeDrawer"
          >
            Annuler
          </button>
          <button
            type="submit"
            class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
            :disabled="isSubmitting"
          >
            Enregistrer
          </button>
        </div>
      </form>
    </AppDrawer>
  </div>
</template>

<script setup lang="ts">
import type { Employee } from '~/services/dto/employee'
import type { AbsenceType } from '~/services/dto/absence-type'
import type { Absence } from '~/services/dto/absence'
import { listEmployees } from '~/services/employees'
import { listAbsenceTypes } from '~/services/absence-types'
import { createAbsence, deleteAbsence, listAbsences, updateAbsence } from '~/services/absences'
import { getDaysInMonth, normalizeDate, toYmd } from '~/utils/date'

const employees = ref<Employee[]>([])
const absenceTypes = ref<AbsenceType[]>([])
const absences = ref<Absence[]>([])

const isDrawerOpen = ref(false)
const isSubmitting = ref(false)
const editingAbsence = ref<Absence | null>(null)

const now = new Date()
const selectedMonth = ref(now.getMonth())
const selectedYear = ref(now.getFullYear())

const months = [
  { value: 0, label: 'Janvier' },
  { value: 1, label: 'Février' },
  { value: 2, label: 'Mars' },
  { value: 3, label: 'Avril' },
  { value: 4, label: 'Mai' },
  { value: 5, label: 'Juin' },
  { value: 6, label: 'Juillet' },
  { value: 7, label: 'Août' },
  { value: 8, label: 'Septembre' },
  { value: 9, label: 'Octobre' },
  { value: 10, label: 'Novembre' },
  { value: 11, label: 'Décembre' }
]

const years = Array.from({ length: 5 }, (_, i) => now.getFullYear() - 2 + i)


const daysInMonth = computed(() => getDaysInMonth(selectedYear.value, selectedMonth.value))

const getGridStyle = (daysCount: number) => {
  return {
    gridTemplateColumns: `220px repeat(${daysCount}, minmax(44px, 1fr))`
  }
}

const gridStyle = computed(() => getGridStyle(daysInMonth.value.length))

const form = reactive({
  employeeId: '' as number | '',
  typeId: '' as number | '',
  startDate: '',
  endDate: '',
  comment: ''
})

const printMode = ref<'1' | '3' | null>(null)

const monthLabel = (monthIndex: number) => months.find((m) => m.value === monthIndex)?.label ?? ''

const printMonths = computed(() => {
  if (!printMode.value) return []

  const startYear = selectedYear.value
  const startMonth = selectedMonth.value
  const count = printMode.value === '3' ? 3 : 1

  return Array.from({ length: count }, (_, offset) => {
    const date = new Date(startYear, startMonth + offset, 1)
    const year = date.getFullYear()
    const month = date.getMonth()
    return {
      year,
      month,
      label: monthLabel(month),
      days: getDaysInMonth(year, month)
    }
  })
})

const resetForm = () => {
  form.employeeId = ''
  form.typeId = ''
  form.startDate = ''
  form.endDate = ''
  form.comment = ''
}

const closeDrawer = () => {
  isDrawerOpen.value = false
  editingAbsence.value = null
  resetForm()
}

const loadEmployees = async () => {
  employees.value = await listEmployees()
}

const loadAbsenceTypes = async () => {
  absenceTypes.value = await listAbsenceTypes()
}

const loadAbsences = async () => {
  absences.value = await listAbsences()
}

onMounted(async () => {
  await Promise.all([loadEmployees(), loadAbsenceTypes(), loadAbsences()])
})

watch([selectedMonth, selectedYear], async () => {
  await loadAbsences()
})

const getCellAbsence = (employeeId: number, date: string) => {
  const match = absences.value.find((absence) => {
    const employee = absence.employee?.id
    const start = normalizeDate(absence.startDate)
    const end = normalizeDate(absence.endDate)
    return Number(employee) === employeeId && date >= start && date <= end
  })

  if (!match) return null

  return {
    id: match.id,
    code: match.type?.code ?? '',
    color: match.type?.color ?? '#222783'
  }
}

const getCellStyle = (employeeId: number, date: string) => {
  const absence = getCellAbsence(employeeId, date)
  if (!absence) return undefined

  return {
    backgroundColor: absence.color,
    color: '#fff'
  }
}

const getCellCode = (employeeId: number, date: string) => {
  return getCellAbsence(employeeId, date)?.code ?? ''
}

const openCreate = (employee: Employee, date: string) => {
  const existing = absences.value.find((absence) => {
    const start = normalizeDate(absence.startDate)
    const end = normalizeDate(absence.endDate)
    return absence.employee?.id === employee.id && date >= start && date <= end
  })

  if (existing) {
    editingAbsence.value = existing
    form.employeeId = existing.employee.id
    form.typeId = existing.type.id
    form.startDate = normalizeDate(existing.startDate)
    form.endDate = normalizeDate(existing.endDate)
    form.comment = existing.comment ?? ''
  } else {
    editingAbsence.value = null
    form.employeeId = employee.id
    form.startDate = date
    form.endDate = date
    form.typeId = ''
    form.comment = ''
  }

  isDrawerOpen.value = true
}

const openCreateFromToday = () => {
  editingAbsence.value = null
  form.employeeId = ''
  form.typeId = ''
  const now = new Date()
  const today = toYmd(now.getFullYear(), now.getMonth(), now.getDate())
  form.startDate = today
  form.endDate = today
  form.comment = ''
  isDrawerOpen.value = true
}

const handleSubmit = async () => {
  if (isSubmitting.value) return

  isSubmitting.value = true
  try {
    const start = normalizeDate(form.startDate)
    const end = normalizeDate(form.endDate)
    const overlaps = absences.value.filter((absence) => {
      if (absence.employee?.id !== Number(form.employeeId)) return false
      if (editingAbsence.value && absence.id === editingAbsence.value.id) return false
      const aStart = normalizeDate(absence.startDate)
      const aEnd = normalizeDate(absence.endDate)
      return start <= aEnd && end >= aStart
    })

    for (const overlap of overlaps) {
      await deleteAbsence(overlap.id)
    }

    if (editingAbsence.value) {
      await updateAbsence({
        id: editingAbsence.value.id,
        employeeId: Number(form.employeeId),
        typeId: Number(form.typeId),
        startDate: form.startDate,
        endDate: form.endDate,
        comment: form.comment
      })
    } else {
      await createAbsence({
        employeeId: Number(form.employeeId),
        typeId: Number(form.typeId),
        startDate: form.startDate,
        endDate: form.endDate,
        comment: form.comment
      })
    }

    closeDrawer()
    await loadAbsences()
  } finally {
    isSubmitting.value = false
  }
}

const handleDelete = async () => {
  if (!editingAbsence.value) return

  const ok = window.confirm('Supprimer cette absence ?')
  if (!ok) return

  await deleteAbsence(editingAbsence.value.id)
  closeDrawer()
  await loadAbsences()
}

const printMonth = async (mode: '1' | '3') => {
  printMode.value = mode
  await nextTick()
  window.print()
  printMode.value = null
}
</script>

<style>
.print-only {
  display: none;
}

@media print {
  .no-print {
    display: none !important;
  }

  .print-only {
    display: block;
  }

  * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .print-only .border-neutral-200,
  .print-only .border-neutral-100 {
    border-color: #d1d5db !important;
  }

  .print-only .bg-tertiary-500 {
    background-color: #f3f4f8 !important;
  }

  .print-only .rounded-lg,
  .print-only .rounded-md {
    border-radius: 0 !important;
  }

  body {
    background: #fff;
  }
}
</style>
