<script setup>
import { ref, computed, watch } from "vue";
import { addBulkHours, fetchTasks } from "../composables/useHoursApi.js";
import { apiErrorDetail } from "../../../services/api.js";
import { useBaseToast } from "../../../composables/useBaseToast.js";

const props = defineProps({
  visible: { type: Boolean, required: true },
  initialDate: { type: String, default: null },
  registry: { type: Object, required: true },
});

const emit = defineEmits(["update:visible", "saved"]);

const toast = useBaseToast();

// ─── Form fields ──────────────────────────────────────────────────────────────
const hoursInput = ref("0:00");
const selectedProjectKey = ref(null); // "internal_X" | "project_X"
const selectedTaskId = ref(null);
const description = ref("");
const taskOptions = ref([]);
const saving = ref(false);

// ─── Derived registration type ────────────────────────────────────────────────
const selectedType = computed(() => {
  if (!selectedProjectKey.value) return null;
  if (selectedProjectKey.value.startsWith("internal_")) return "internal";
  if (selectedProjectKey.value.startsWith("project_")) return "project";
  return null;
});

const selectedRawId = computed(() => {
  if (!selectedProjectKey.value) return null;
  return parseInt(selectedProjectKey.value.split("_")[1], 10);
});

const isProjectSelected = computed(
  () => selectedProjectKey.value?.startsWith("project_") === true,
);

// ─── Project + category combined options ──────────────────────────────────────
const projectOptions = computed(() => {
  const groups = [];
  if (props.registry.internalCategories?.length) {
    groups.push({
      label: "Intern",
      items: props.registry.internalCategories.map((c) => ({
        key: `internal_${c.id}`,
        label: c.name,
      })),
    });
  }
  if (props.registry.projects?.length) {
    groups.push({
      label: "Projecten",
      items: props.registry.projects.map((p) => ({
        key: `project_${p.id}`,
        label: p.name,
      })),
    });
  }
  return groups;
});

const flatProjectOptions = computed(() =>
  projectOptions.value.flatMap((g) => g.items),
);

watch(selectedProjectKey, async (val) => {
  selectedTaskId.value = null;
  taskOptions.value = [];
  if (val?.startsWith("project_")) {
    const id = parseInt(val.split("_")[1], 10);
    try {
      taskOptions.value = await fetchTasks(id);
    } catch {
      taskOptions.value = [];
    }
  }
});

// ─── Date selection ───────────────────────────────────────────────────────────
const today = new Date();
const pickerYear = ref(today.getFullYear());
const pickerMonth = ref(today.getMonth()); // 0-indexed
const selectedDates = ref(/** @type {string[]} */ ([]));

const NL_MONTHS_SHORT = ["jan", "feb", "mar", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"];
const NL_WEEKDAYS = ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"];

const pickerMonthYear = computed(() => `${pickerYear.value}`);

function monthBadge(monthIdx) {
  return selectedDates.value.filter((d) => {
    const m = parseInt(d.slice(5, 7), 10) - 1;
    const y = parseInt(d.slice(0, 4), 10);
    return m === monthIdx && y === pickerYear.value;
  }).length;
}

function selectMonth(idx) {
  pickerMonth.value = idx;
}

const pickerDays = computed(() => {
  const y = pickerYear.value;
  const m = pickerMonth.value;
  const firstDay = new Date(y, m, 1);
  const lastDay = new Date(y, m + 1, 0);
  // Monday = 0 in our grid
  const leadingBlanks = (firstDay.getDay() + 6) % 7;
  const totalDays = lastDay.getDate();
  const totalSlots = Math.ceil((leadingBlanks + totalDays) / 7) * 7;

  const cells = [];
  for (let i = 0; i < totalSlots; i++) {
    const dayNum = i - leadingBlanks + 1;
    if (dayNum < 1 || dayNum > totalDays) {
      cells.push({ iso: null, day: null, inMonth: false });
    } else {
      const iso = `${y}-${String(m + 1).padStart(2, "0")}-${String(dayNum).padStart(2, "0")}`;
      cells.push({ iso, day: dayNum, inMonth: true });
    }
  }
  return cells;
});

function isSelected(iso) {
  return iso != null && selectedDates.value.includes(iso);
}

function isToday(iso) {
  if (!iso) return false;
  const t = today;
  return (
    iso ===
    `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`
  );
}

function toggleDate(iso) {
  if (!iso) return;
  const idx = selectedDates.value.indexOf(iso);
  if (idx === -1) {
    selectedDates.value = [...selectedDates.value, iso];
  } else {
    selectedDates.value = selectedDates.value.filter((d) => d !== iso);
  }
}

// ─── Hours parsing ────────────────────────────────────────────────────────────
function parseHoursInput(raw) {
  const s = raw.trim().replace(",", ".");
  if (s.includes(":")) {
    const [h, mm] = s.split(":");
    return parseInt(h, 10) + parseInt(mm || "0", 10) / 60;
  }
  return parseFloat(s) || 0;
}

// ─── Open / close ─────────────────────────────────────────────────────────────
watch(
  () => props.visible,
  (v) => {
    if (v) {
      hoursInput.value = "0:00";
      selectedProjectKey.value = null;
      selectedTaskId.value = null;
      description.value = "";
      taskOptions.value = [];
      if (props.initialDate) {
        const d = new Date(props.initialDate + "T12:00:00");
        pickerYear.value = d.getFullYear();
        pickerMonth.value = d.getMonth();
        selectedDates.value = [props.initialDate];
      } else {
        pickerYear.value = today.getFullYear();
        pickerMonth.value = today.getMonth();
        selectedDates.value = [];
      }
    }
  },
);

function close() {
  emit("update:visible", false);
}

// ─── Save ─────────────────────────────────────────────────────────────────────
async function save() {
  const hours = parseHoursInput(hoursInput.value);
  if (hours <= 0 || hours > 24) {
    toast.warn("Vul een geldig aantal uren in (0:01 – 24:00).", "Uren", 4000);
    return;
  }
  if (selectedDates.value.length === 0) {
    toast.warn("Selecteer minstens één dag.", "Datum", 4000);
    return;
  }
  if (!selectedProjectKey.value) {
    toast.warn("Selecteer een project of categorie.", "Project", 4000);
    return;
  }

  const regType = selectedType.value;
  if (!regType) return;

  const options = { description: description.value };
  if (regType === "internal") {
    options.internal_category_id = selectedRawId.value;
  } else if (regType === "project" && selectedTaskId.value) {
    options.hour_task_id = selectedTaskId.value;
  } else if (regType === "project") {
    options.hour_project_id = selectedRawId.value;
  }

  const finalType = regType === "project" && selectedTaskId.value ? "task" : regType;

  saving.value = true;
  try {
    await addBulkHours(selectedDates.value, hours, finalType, options);
    emit("saved");
    close();
  } catch (e) {
    toast.error(apiErrorDetail(e), "Opslaan mislukt", 7000);
  } finally {
    saving.value = false;
  }
}
</script>

<template>
  <Teleport to="body">
    <Transition name="modal-fade">
      <div v-if="visible" class="fixed inset-0 z-50 flex items-center justify-center">
        <!-- Backdrop -->
        <div class="absolute inset-0 bg-black/40" @click="close" />

        <!-- Modal box -->
        <div
          class="relative bg-white dark:bg-surface-900 rounded-2xl shadow-xl w-[56rem] max-w-[95vw] max-h-[90vh] overflow-auto"
          @click.stop
        >
          <!-- Header -->
          <div class="flex items-center justify-between px-6 pt-5 pb-4 border-b border-surface-200 dark:border-surface-700">
            <h2 class="text-base font-semibold text-surface-900 dark:text-surface-0 m-0">
              Tijdregistratie(s) toevoegen
            </h2>
            <button
              type="button"
              class="w-7 h-7 flex items-center justify-center rounded-full text-surface-500 hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors"
              @click="close"
            >
              <i class="pi pi-times text-sm" />
            </button>
          </div>

          <!-- Body -->
          <div class="px-6 py-5 flex flex-col gap-4">
            <!-- Row 1: Uren + Project + Taak -->
            <div class="flex flex-wrap gap-3 items-end">
              <!-- Uren -->
              <div class="flex flex-col gap-1">
                <label class="text-xs font-medium text-surface-700 dark:text-surface-300">
                  Uren <span class="text-red-500">*</span>
                </label>
                <div class="flex items-center gap-1.5">
                  <input
                    v-model="hoursInput"
                    type="text"
                    placeholder="0:00"
                    class="w-20 border border-surface-300 dark:border-surface-600 rounded-lg px-3 py-2 text-sm text-surface-900 dark:text-surface-0 bg-white dark:bg-surface-800 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
                    @focus="($event.target).select()"
                  />
                  <span class="text-sm text-surface-500">uur</span>
                </div>
              </div>

              <!-- Project -->
              <div class="flex flex-col gap-1 flex-1 min-w-[12rem]">
                <label class="text-xs font-medium text-surface-700 dark:text-surface-300">
                  Project <span class="text-red-500">*</span>
                </label>
                <select
                  v-model="selectedProjectKey"
                  class="border border-surface-300 dark:border-surface-600 rounded-lg px-3 py-2 text-sm text-surface-900 dark:text-surface-0 bg-white dark:bg-surface-800 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500 w-full"
                >
                  <option value="" disabled selected>Alle projecten</option>
                  <template v-for="group in projectOptions" :key="group.label">
                    <optgroup :label="group.label">
                      <option
                        v-for="opt in group.items"
                        :key="opt.key"
                        :value="opt.key"
                      >
                        {{ opt.label }}
                      </option>
                    </optgroup>
                  </template>
                </select>
              </div>

              <!-- Taak -->
              <div class="flex flex-col gap-1 flex-1 min-w-[10rem]">
                <label class="text-xs font-medium text-surface-700 dark:text-surface-300">
                  Taak
                </label>
                <select
                  v-model="selectedTaskId"
                  :disabled="!isProjectSelected || taskOptions.length === 0"
                  class="border border-surface-300 dark:border-surface-600 rounded-lg px-3 py-2 text-sm text-surface-900 dark:text-surface-0 bg-white dark:bg-surface-800 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500 w-full disabled:opacity-50 disabled:cursor-not-allowed"
                >
                  <option :value="null">Taak</option>
                  <option v-for="t in taskOptions" :key="t.id" :value="t.id">
                    {{ t.title }}
                  </option>
                </select>
              </div>
            </div>

            <!-- Row 2: Omschrijving -->
            <div class="flex flex-col gap-1">
              <label class="text-xs font-medium text-surface-700 dark:text-surface-300">
                Omschrijving
              </label>
              <input
                v-model="description"
                type="text"
                placeholder="Omschrijving"
                class="border border-surface-300 dark:border-surface-600 rounded-lg px-3 py-2 text-sm text-surface-900 dark:text-surface-0 bg-white dark:bg-surface-800 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500 w-full"
              />
            </div>

            <!-- Info box -->
            <div class="flex items-start gap-2 bg-blue-50 dark:bg-blue-950/30 border border-blue-200 dark:border-blue-800 rounded-lg px-4 py-3">
              <i class="pi pi-info-circle text-blue-500 mt-0.5 text-sm flex-shrink-0" />
              <span class="text-sm text-blue-700 dark:text-blue-300">
                Selecteer de dag(en) waarop je deze tijdregistratie wilt toevoegen
              </span>
            </div>

            <!-- Inline date picker -->
            <div class="flex border border-surface-200 dark:border-surface-700 rounded-xl overflow-hidden">
              <!-- Left: year + months -->
              <div class="w-40 flex-shrink-0 border-r border-surface-200 dark:border-surface-700 p-4 flex flex-col gap-3">
                <!-- Year nav -->
                <div class="flex items-center justify-between">
                  <button
                    type="button"
                    class="w-6 h-6 flex items-center justify-center rounded hover:bg-surface-100 dark:hover:bg-surface-800 text-surface-600 dark:text-surface-300"
                    @click="pickerYear--"
                  >
                    <i class="pi pi-chevron-left text-xs" />
                  </button>
                  <span class="text-sm font-semibold text-surface-900 dark:text-surface-0">
                    {{ pickerYear }}
                  </span>
                  <button
                    type="button"
                    class="w-6 h-6 flex items-center justify-center rounded hover:bg-surface-100 dark:hover:bg-surface-800 text-surface-600 dark:text-surface-300"
                    @click="pickerYear++"
                  >
                    <i class="pi pi-chevron-right text-xs" />
                  </button>
                </div>

                <!-- Month grid -->
                <div class="grid grid-cols-3 gap-1">
                  <button
                    v-for="(name, idx) in NL_MONTHS_SHORT"
                    :key="name"
                    type="button"
                    class="relative flex items-center justify-center rounded-lg py-1.5 text-xs font-medium transition-colors"
                    :class="pickerMonth === idx
                      ? 'bg-primary-600 text-white'
                      : 'text-surface-700 dark:text-surface-300 hover:bg-surface-100 dark:hover:bg-surface-800'"
                    @click="selectMonth(idx)"
                  >
                    {{ name }}
                    <span
                      v-if="monthBadge(idx) > 0"
                      class="absolute -top-1 -right-1 min-w-[14px] h-[14px] bg-primary-500 text-white rounded-full text-[9px] font-bold flex items-center justify-center px-0.5 leading-none"
                    >
                      {{ monthBadge(idx) }}
                    </span>
                  </button>
                </div>
              </div>

              <!-- Right: day grid -->
              <div class="flex-1 p-4">
                <!-- Weekday headers -->
                <div class="grid grid-cols-7 mb-1">
                  <div
                    v-for="wd in NL_WEEKDAYS"
                    :key="wd"
                    class="text-center text-xs font-semibold text-surface-400 dark:text-surface-500 py-1"
                  >
                    {{ wd }}
                  </div>
                </div>

                <!-- Day cells -->
                <div class="grid grid-cols-7 gap-y-0.5">
                  <template v-for="(cell, i) in pickerDays" :key="i">
                    <div class="flex items-center justify-center py-0.5">
                      <button
                        v-if="cell.inMonth && cell.iso"
                        type="button"
                        class="w-8 h-8 flex items-center justify-center rounded-full text-sm font-medium transition-colors"
                        :class="[
                          isSelected(cell.iso)
                            ? 'bg-primary-600 text-white'
                            : isToday(cell.iso)
                              ? 'border-2 border-primary-500 text-primary-600 dark:text-primary-400'
                              : 'text-surface-700 dark:text-surface-300 hover:bg-surface-100 dark:hover:bg-surface-800',
                        ]"
                        @click="toggleDate(cell.iso)"
                      >
                        {{ cell.day }}
                      </button>
                      <span v-else class="w-8 h-8" />
                    </div>
                  </template>
                </div>
              </div>
            </div>
          </div>

          <!-- Footer -->
          <div class="flex items-center justify-end gap-3 px-6 py-4 border-t border-surface-200 dark:border-surface-700">
            <button
              type="button"
              class="px-5 py-2 text-sm font-medium text-surface-700 dark:text-surface-300 bg-white dark:bg-surface-800 border border-surface-300 dark:border-surface-600 rounded-lg hover:bg-surface-50 dark:hover:bg-surface-700 transition-colors"
              @click="close"
            >
              Annuleren
            </button>
            <button
              type="button"
              :disabled="saving"
              class="px-5 py-2 text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 disabled:opacity-60 disabled:cursor-not-allowed rounded-lg transition-colors flex items-center gap-2"
              @click="save"
            >
              <i v-if="saving" class="pi pi-spin pi-spinner text-xs" />
              Toevoegen
            </button>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
.modal-fade-enter-active,
.modal-fade-leave-active {
  transition: opacity 0.15s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
  opacity: 0;
}
</style>
