<script setup>
import { setPageLayout } from "#app"

const router = useRouter()
const route = useRoute()
const toast = useToast()
const auth = useAuthStore()
const profileStore = useProfileStore()
const { has } = usePermission()

const STATUS_COLUMNS = ["Offen", "In Bearbeitung", "Abgeschlossen"]

const loading = ref(false)
const saving = ref(false)
const deleting = ref(false)
const quickCompleteLoadingId = ref(null)
const tasks = ref([])
const search = ref("")
const viewMode = ref("kanban")
const draggingTaskId = ref(null)
const droppingOn = ref("")
const projects = ref([])
const customers = ref([])
const plants = ref([])

const canViewAll = computed(() => has("tasks-viewAll"))
const canCreate = computed(() => has("tasks-create"))
const currentUserId = computed(() => auth.user?.user_id || auth.user?.id || null)
const showOnlyMine = ref(!canViewAll.value)

const isModalOpen = ref(false)
const modalMode = ref("show")
const taskForm = ref(getEmptyTask())

const assigneeOptions = computed(() =>
    (profileStore.profiles || [])
        .map((profile) => {
          const value = profile.user_id || profile.id
          const label = profile.full_name || profile.fullName || profile.email
          return value && label ? { value, label } : null
        })
        .filter(Boolean)
)

const projectOptions = computed(() =>
    (projects.value || []).map((project) => ({ value: project.id, label: project.name }))
)

const customerOptions = computed(() =>
    (customers.value || []).map((customer) => ({ value: customer.id, label: customer.name }))
)

const plantOptions = computed(() =>
    (plants.value || []).map((plant) => ({ value: plant.id, label: plant.name }))
)

const filteredTasks = computed(() => {
  const needle = search.value.trim().toLowerCase()

  return tasks.value.filter((task) => {
    const assigneeId = getTaskAssigneeId(task)
    const mineMatch = !showOnlyMine.value || (currentUserId.value && assigneeId === currentUserId.value)
    const searchMatch = !needle || [task.name, task.description, task.categorie].some((value) => String(value || "").toLowerCase().includes(needle))
    return !task.archived && mineMatch && searchMatch
  })
})

const groupedTasks = computed(() => {
  return STATUS_COLUMNS.reduce((acc, status) => {
    acc[status] = filteredTasks.value.filter((task) => normalizeStatus(task.categorie) === status)
    return acc
  }, {})
})

const modalTitle = computed(() => {
  if (modalMode.value === "create") return "Neue Aufgabe"
  if (modalMode.value === "edit") return "Aufgabe bearbeiten"
  return "Aufgabe"
})

const isFormReadonly = computed(() => modalMode.value === "show")
const listColumns = [
  { key: "actions", label: "" },
  { key: "name", label: "Titel" },
  { key: "categorie", label: "Status" },
  { key: "assignee", label: "Zuweisung" },
  { key: "project", label: "Projekt" },
  { key: "customer", label: "Kunde" },
  { key: "plant", label: "Objekt" }
]

function getEmptyTask() {
  return {
    id: null,
    name: "",
    description: "",
    categorie: "Offen",
    userId: currentUserId.value || null,
    project: null,
    customer: null,
    plant: null
  }
}

function normalizeStatus(status) {
  if (!status) return "Offen"
  if (status === "Erledigt") return "Abgeschlossen"
  return STATUS_COLUMNS.includes(status) ? status : "Offen"
}

function getTaskAssigneeId(task) {
  return task.userId || task.user_id || task.profile || null
}

function toNullableNumber(value) {
  if (value === null || value === undefined || value === "") return null
  const parsed = Number(value)
  return Number.isFinite(parsed) ? parsed : null
}

function mapTaskToForm(task) {
  return {
    id: task.id,
    name: task.name || "",
    description: task.description || "",
    categorie: normalizeStatus(task.categorie),
    userId: getTaskAssigneeId(task),
    project: toNullableNumber(task.project?.id ?? task.project),
    customer: toNullableNumber(task.customer?.id ?? task.customer),
    plant: toNullableNumber(task.plant?.id ?? task.plant)
  }
}

function getEntityLabel(options, id) {
  if (!id) return null
  const hit = options.find((item) => Number(item.value) === Number(id))
  return hit?.label || null
}

function getAssigneeLabel(task) {
  const assigneeId = getTaskAssigneeId(task)
  return assigneeOptions.value.find((option) => option.value === assigneeId)?.label || "-"
}

function getStatusBadgeColor(status) {
  const normalized = normalizeStatus(status)
  if (normalized === "Offen") return "gray"
  if (normalized === "In Bearbeitung") return "amber"
  return "green"
}

async function loadTasks() {
  loading.value = true
  try {
    const rows = await useEntities("tasks").select()
    tasks.value = rows.map((task) => ({ ...task, categorie: normalizeStatus(task.categorie) }))
  } finally {
    loading.value = false
  }
}

async function loadTaskOptions() {
  const [projectRows, customerRows, plantRows] = await Promise.all([
    useEntities("projects").select(),
    useEntities("customers").select(),
    useEntities("plants").select()
  ])

  projects.value = projectRows || []
  customers.value = customerRows || []
  plants.value = plantRows || []
}

function openCreateTask(initialData = {}) {
  if (!canCreate.value) return
  modalMode.value = "create"
  taskForm.value = {
    ...getEmptyTask(),
    ...initialData,
    categorie: normalizeStatus(initialData.categorie || "Offen"),
    userId: initialData.userId || initialData.user_id || currentUserId.value || null
  }
  isModalOpen.value = true
}

function openTask(task, mode = "show") {
  modalMode.value = mode
  taskForm.value = mapTaskToForm(task)
  isModalOpen.value = true
}

function closeModal() {
  isModalOpen.value = false
  modalMode.value = "show"
  taskForm.value = getEmptyTask()
  const query = { ...route.query }
  delete query.mode
  delete query.id
  router.replace({ path: "/tasks", query })
}

async function saveTask() {
  if (!canCreate.value) return
  const name = taskForm.value.name?.trim()
  if (!name) {
    toast.add({ title: "Name fehlt", description: "Bitte einen Aufgabennamen angeben.", color: "orange" })
    return
  }

  const payload = {
    name,
    description: taskForm.value.description || null,
    categorie: normalizeStatus(taskForm.value.categorie),
    userId: taskForm.value.userId || null,
    project: toNullableNumber(taskForm.value.project),
    customer: toNullableNumber(taskForm.value.customer),
    plant: toNullableNumber(taskForm.value.plant)
  }

  saving.value = true
  try {
    let targetId = taskForm.value.id
    if (taskForm.value.id) {
      await useEntities("tasks").update(taskForm.value.id, payload, true)
    } else {
      const created = await useEntities("tasks").create(payload, true)
      targetId = created?.id || null
    }

    await loadTasks()

    if (targetId) {
      const query = { ...route.query, mode: "show", id: String(targetId) }
      router.replace({ path: "/tasks", query })
      const target = tasks.value.find((task) => String(task.id) === String(targetId))
      if (target) openTask(target, "show")
      return
    }

    closeModal()
  } finally {
    saving.value = false
  }
}

async function archiveTask() {
  if (!canCreate.value || !taskForm.value.id) return
  deleting.value = true
  try {
    await useEntities("tasks").update(taskForm.value.id, { archived: true }, true)
    await loadTasks()
    closeModal()
  } finally {
    deleting.value = false
  }
}

async function completeTaskQuick(task) {
  if (!canCreate.value) return
  if (!task?.id || normalizeStatus(task.categorie) === "Abgeschlossen") return

  const previousStatus = task.categorie
  quickCompleteLoadingId.value = task.id
  task.categorie = "Abgeschlossen"

  try {
    await useEntities("tasks").update(task.id, { categorie: "Abgeschlossen" }, true)
    toast.add({ title: "Aufgabe abgeschlossen", color: "green" })
  } catch (error) {
    task.categorie = previousStatus
    toast.add({ title: "Aufgabe konnte nicht abgeschlossen werden", color: "red" })
  } finally {
    quickCompleteLoadingId.value = null
  }
}

function onDragStart(task) {
  draggingTaskId.value = task.id
}

async function onDrop(status) {
  if (!canCreate.value || !draggingTaskId.value) return

  const droppedTask = tasks.value.find((task) => String(task.id) === String(draggingTaskId.value))
  draggingTaskId.value = null
  droppingOn.value = ""

  if (!droppedTask || normalizeStatus(droppedTask.categorie) === status) return

  const oldStatus = droppedTask.categorie
  droppedTask.categorie = status

  try {
    await useEntities("tasks").update(droppedTask.id, { categorie: status }, true)
  } catch (error) {
    droppedTask.categorie = oldStatus
    toast.add({ title: "Status konnte nicht geändert werden", color: "red" })
  }
}

async function handleRouteIntent() {
  const mode = typeof route.query.mode === "string" ? route.query.mode : null
  const id = typeof route.query.id === "string" ? route.query.id : null

  if (!mode) {
    if (isModalOpen.value) closeModal()
    return
  }

  if (mode === "create") {
    openCreateTask({
      project: toNullableNumber(route.query.project),
      customer: toNullableNumber(route.query.customer),
      plant: toNullableNumber(route.query.plant),
      userId: route.query.userId || route.query.user_id || currentUserId.value || null
    })
    return
  }

  if (!id) return

  let task = tasks.value.find((item) => String(item.id) === id)
  if (!task) {
    const loadedTask = await useEntities("tasks").selectSingle(id, "*", true)
    if (loadedTask) {
      task = { ...loadedTask, categorie: normalizeStatus(loadedTask.categorie) }
      const idx = tasks.value.findIndex((item) => String(item.id) === id)
      if (idx === -1) tasks.value.push(task)
    }
  }

  if (!task) return
  openTask(task, mode === "edit" ? "edit" : "show")
}

function openCreateViaRoute() {
  router.push({ path: "/tasks", query: { ...route.query, mode: "create" } })
}

function openTaskViaRoute(task) {
  router.push({ path: "/tasks", query: { ...route.query, mode: "show", id: String(task.id) } })
}

watch(
    () => route.query,
    async () => {
      await handleRouteIntent()
    },
    { deep: true }
)

onMounted(async () => {
  setPageLayout("default")
  await Promise.all([loadTasks(), loadTaskOptions()])
  await handleRouteIntent()
})
</script>

<template>
  <UDashboardNavbar title="Aufgaben" :badge="filteredTasks.length">
    <template #right>
      <div class="flex items-center gap-2">
        <UInput
            v-model="search"
            icon="i-heroicons-magnifying-glass"
            placeholder="Aufgaben durchsuchen..."
            class="w-72"
        />
        <UButton
            icon="i-heroicons-arrow-path"
            color="gray"
            variant="soft"
            :loading="loading"
            @click="loadTasks"
        />
        <UButton
            v-if="canCreate"
            icon="i-heroicons-plus"
            @click="openCreateViaRoute"
        >
          Aufgabe
        </UButton>
      </div>
    </template>
  </UDashboardNavbar>

  <UDashboardToolbar>
    <template #left>
      <UCheckbox
          v-if="canViewAll"
          v-model="showOnlyMine"
          label="Nur meine Aufgaben"
      />
      <span v-else class="text-sm text-gray-500">Ansicht: Nur eigene Aufgaben</span>
    </template>
    <template #right>
      <div class="flex items-center gap-1 rounded-lg border border-gray-200 p-1 dark:border-gray-700">
        <UButton
            size="xs"
            variant="ghost"
            icon="i-heroicons-view-columns"
            :color="viewMode === 'kanban' ? 'primary' : 'gray'"
            @click="viewMode = 'kanban'"
        >
          Kanban
        </UButton>
        <UButton
            size="xs"
            variant="ghost"
            icon="i-heroicons-list-bullet"
            :color="viewMode === 'list' ? 'primary' : 'gray'"
            @click="viewMode = 'list'"
        >
          Liste
        </UButton>
      </div>
    </template>
  </UDashboardToolbar>

  <UDashboardPanelContent>
    <div v-if="viewMode === 'kanban'" class="kanban-grid">
      <section
          v-for="status in STATUS_COLUMNS"
          :key="status"
          class="kanban-column"
          @dragover.prevent="droppingOn = status"
          @dragleave="droppingOn = ''"
          @drop.prevent="onDrop(status)"
      >
        <header class="kanban-column-header">
          <h3>{{ status }}</h3>
          <UBadge color="gray" variant="subtle">{{ groupedTasks[status]?.length || 0 }}</UBadge>
        </header>

        <div :class="['kanban-dropzone', droppingOn === status ? 'kanban-dropzone-active' : '']">
          <article
              v-for="task in groupedTasks[status]"
              :key="task.id"
              class="kanban-card"
              draggable="true"
              @dragstart="onDragStart(task)"
              @click="openTaskViaRoute(task)"
          >
            <div class="kanban-card-title">{{ task.name }}</div>
            <p v-if="task.description" class="kanban-card-description">{{ task.description }}</p>

            <div class="kanban-card-meta">
              <UBadge v-if="getEntityLabel(projectOptions, task.project?.id || task.project)" color="primary" variant="soft">
                {{ getEntityLabel(projectOptions, task.project?.id || task.project) }}
              </UBadge>
              <UBadge v-if="getEntityLabel(customerOptions, task.customer?.id || task.customer)" color="gray" variant="soft">
                {{ getEntityLabel(customerOptions, task.customer?.id || task.customer) }}
              </UBadge>
              <UBadge v-if="getEntityLabel(plantOptions, task.plant?.id || task.plant)" color="gray" variant="soft">
                {{ getEntityLabel(plantOptions, task.plant?.id || task.plant) }}
              </UBadge>
            </div>
          </article>

          <div v-if="!groupedTasks[status]?.length" class="kanban-empty">
            Keine Aufgaben
          </div>
        </div>
      </section>
    </div>
    <UTable
        v-else
        :rows="filteredTasks"
        :columns="listColumns"
        :empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Aufgaben anzuzeigen' }"
        @select="(task) => openTaskViaRoute(task)"
    >
      <template #actions-data="{ row }">
        <UButton
            v-if="normalizeStatus(row.categorie) !== 'Abgeschlossen' && canCreate"
            size="xs"
            color="green"
            variant="soft"
            icon="i-heroicons-check"
            :loading="quickCompleteLoadingId === row.id"
            @click.stop="completeTaskQuick(row)"
        >
          Erledigt
        </UButton>
      </template>
      <template #categorie-data="{ row }">
        <UBadge :color="getStatusBadgeColor(row.categorie)" variant="soft">
          {{ normalizeStatus(row.categorie) }}
        </UBadge>
      </template>
      <template #assignee-data="{ row }">
        {{ getAssigneeLabel(row) }}
      </template>
      <template #project-data="{ row }">
        {{ getEntityLabel(projectOptions, row.project?.id || row.project) || "-" }}
      </template>
      <template #customer-data="{ row }">
        {{ getEntityLabel(customerOptions, row.customer?.id || row.customer) || "-" }}
      </template>
      <template #plant-data="{ row }">
        {{ getEntityLabel(plantOptions, row.plant?.id || row.plant) || "-" }}
      </template>
    </UTable>
  </UDashboardPanelContent>

  <UModal v-model="isModalOpen" :prevent-close="saving || deleting">
    <UCard>
      <template #header>
        <div class="flex items-center justify-between">
          <h3 class="font-semibold">{{ modalTitle }}</h3>
          <UBadge color="gray" variant="subtle">{{ taskForm.id ? `#${taskForm.id}` : "Neu" }}</UBadge>
        </div>
      </template>

      <div class="space-y-3">
        <div>
          <label class="form-label">Titel</label>
          <UInput v-model="taskForm.name" :disabled="isFormReadonly || !canCreate" />
        </div>
        <div>
          <label class="form-label">Beschreibung</label>
          <UTextarea v-model="taskForm.description" :disabled="isFormReadonly || !canCreate" />
        </div>

        <USelectMenu
            v-model="taskForm.categorie"
            :options="STATUS_COLUMNS.map((status) => ({ label: status, value: status }))"
            value-attribute="value"
            option-attribute="label"
            :disabled="isFormReadonly || !canCreate"
        >
          <template #label>
            {{ taskForm.categorie || "Status auswählen" }}
          </template>
        </USelectMenu>

        <USelectMenu
            v-model="taskForm.userId"
            :options="assigneeOptions"
            value-attribute="value"
            option-attribute="label"
            :disabled="isFormReadonly || !canCreate"
            searchable
        >
          <template #label>
            {{ assigneeOptions.find((option) => option.value === taskForm.userId)?.label || "Zuweisung" }}
          </template>
        </USelectMenu>

        <USelectMenu
            v-model="taskForm.project"
            :options="projectOptions"
            value-attribute="value"
            option-attribute="label"
            :disabled="isFormReadonly || !canCreate"
            searchable
            clear-search-on-close
        >
          <template #label>
            {{ getEntityLabel(projectOptions, taskForm.project) || "Projekt" }}
          </template>
        </USelectMenu>

        <USelectMenu
            v-model="taskForm.customer"
            :options="customerOptions"
            value-attribute="value"
            option-attribute="label"
            :disabled="isFormReadonly || !canCreate"
            searchable
            clear-search-on-close
        >
          <template #label>
            {{ getEntityLabel(customerOptions, taskForm.customer) || "Kunde" }}
          </template>
        </USelectMenu>

        <USelectMenu
            v-model="taskForm.plant"
            :options="plantOptions"
            value-attribute="value"
            option-attribute="label"
            :disabled="isFormReadonly || !canCreate"
            searchable
            clear-search-on-close
        >
          <template #label>
            {{ getEntityLabel(plantOptions, taskForm.plant) || "Objekt" }}
          </template>
        </USelectMenu>
      </div>

      <template #footer>
        <div class="flex items-center justify-between gap-2">
          <div class="flex gap-2">
            <UButton
                v-if="taskForm.id && canCreate"
                color="red"
                variant="soft"
                :loading="deleting"
                @click="archiveTask"
            >
              Archivieren
            </UButton>
          </div>

          <div class="flex gap-2">
            <UButton color="gray" variant="ghost" @click="closeModal">Schließen</UButton>
            <UButton
                v-if="modalMode === 'show' && canCreate"
                color="gray"
                variant="soft"
                @click="modalMode = 'edit'"
            >
              Bearbeiten
            </UButton>
            <UButton
                v-if="modalMode !== 'show' && canCreate"
                :loading="saving"
                @click="saveTask"
            >
              Speichern
            </UButton>
          </div>
        </div>
      </template>
    </UCard>
  </UModal>
</template>

<style scoped>
.kanban-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

@media (min-width: 1024px) {
  .kanban-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.kanban-column {
  border: 1px solid rgb(229 231 235);
  border-radius: 0.75rem;
  background: rgb(249 250 251);
  min-height: 500px;
  display: flex;
  flex-direction: column;
}

.kanban-column-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.75rem 0.9rem;
  border-bottom: 1px solid rgb(229 231 235);
}

.kanban-dropzone {
  padding: 0.75rem;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  transition: background-color 0.2s ease;
}

.kanban-dropzone-active {
  background: rgb(239 246 255);
}

.kanban-card {
  border: 1px solid rgb(229 231 235);
  background: white;
  border-radius: 0.6rem;
  padding: 0.7rem;
  cursor: pointer;
}

.kanban-card-title {
  font-weight: 600;
  line-height: 1.25rem;
}

.kanban-card-description {
  margin-top: 0.4rem;
  color: rgb(107 114 128);
  font-size: 0.875rem;
  line-height: 1.15rem;
}

.kanban-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.6rem;
}

.kanban-empty {
  border: 1px dashed rgb(209 213 219);
  color: rgb(156 163 175);
  border-radius: 0.6rem;
  padding: 0.7rem;
  font-size: 0.875rem;
}

.form-label {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
}

:global(.dark) .kanban-column {
  border-color: rgb(55 65 81);
  background: rgb(17 24 39);
}

:global(.dark) .kanban-column-header {
  border-bottom-color: rgb(55 65 81);
}

:global(.dark) .kanban-dropzone-active {
  background: rgb(30 41 59);
}

:global(.dark) .kanban-card {
  border-color: rgb(75 85 99);
  background: rgb(31 41 55);
}

:global(.dark) .kanban-card-description {
  color: rgb(209 213 219);
}

:global(.dark) .kanban-empty {
  border-color: rgb(75 85 99);
  color: rgb(156 163 175);
}

:global(.dark) .form-label {
  color: rgb(229 231 235);
}
</style>
