<script setup>
import { setPageLayout } from "#app"
import { Bar } from "vue-chartjs"

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("list")
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 expandedTaskIds = ref([])

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 taskMap = computed(() => {
  return Object.fromEntries(tasks.value.map((task) => [String(task.id), task]))
})

const taskSuccessorMap = computed(() => {
  const map = {}

  tasks.value.forEach((task) => {
    map[String(task.id)] = []
  })

  tasks.value.forEach((task) => {
    getDependencyIds(task).forEach((dependencyId) => {
      const key = String(dependencyId)
      if (!map[key]) map[key] = []
      map[key].push(task.id)
    })
  })

  return map
})

const dependencyOptions = computed(() => {
  const blockedIds = taskForm.value.id ? getDescendantIds(taskForm.value.id) : new Set()

  return tasks.value
      .filter((task) => String(task.id) !== String(taskForm.value.id) && !blockedIds.has(String(task.id)))
      .map((task) => ({ value: task.id, label: task.name || `#${task.id}` }))
      .sort((a, b) => a.label.localeCompare(b.label, "de"))
})

const waterfallColumns = computed(() => buildWaterfallColumns(filteredTasks.value))
const waterfallHasCycle = computed(() => waterfallColumns.value.some((column) => column.kind === "cycle"))
const waterfallRows = computed(() => buildWaterfallRows(filteredTasks.value, waterfallColumns.value))
const listRootTasks = computed(() => {
  const childIds = new Set()

  filteredTasks.value.forEach((task) => {
    getDependencyIds(task).forEach((dependencyId) => {
      childIds.add(String(dependencyId))
    })
  })

  return filteredTasks.value.filter((task) => !childIds.has(String(task.id)))
})
const waterfallMaxPosition = computed(() => {
  return waterfallRows.value.reduce((max, row) => Math.max(max, row.end), 1)
})
const waterfallChartHeight = computed(() => Math.max(320, waterfallRows.value.length * 54 + 80))
const waterfallChartData = computed(() => ({
  datasets: [
    {
      label: "Ablauf",
      data: waterfallRows.value.map((row) => ({
        x: [row.start, row.end],
        y: row.label,
        taskId: row.task.id,
        taskName: row.task.name,
        dependencies: getDependencySummary(row.task),
        status: normalizeStatus(row.task.categorie),
        stateLabel: getTaskDependencyStateLabel(row.task),
        kind: row.kind
      })),
      borderRadius: 8,
      borderSkipped: false,
      borderWidth: 1.5,
      borderColor(context) {
        const raw = context.raw || {}
        if (raw.kind === "cycle") return "#c2410c"
        return getTaskDependencyState(taskMap.value[String(raw.taskId)]) === "done" ? "#15803d" : "#1d4ed8"
      },
      backgroundColor(context) {
        const raw = context.raw || {}
        if (raw.kind === "cycle") return "rgba(249, 115, 22, 0.85)"
        const state = getTaskDependencyState(taskMap.value[String(raw.taskId)])
        if (state === "done") return "rgba(34, 197, 94, 0.85)"
        if (state === "blocked") return "rgba(245, 158, 11, 0.85)"
        return "rgba(59, 130, 246, 0.82)"
      },
      barThickness: 22
    }
  ]
}))
const waterfallChartOptions = computed(() => ({
  indexAxis: "y",
  responsive: true,
  maintainAspectRatio: false,
  animation: false,
  parsing: true,
  plugins: {
    legend: {
      display: false
    },
    tooltip: {
      callbacks: {
        title(items) {
          return items[0]?.raw?.taskName || items[0]?.label || ""
        },
        label(item) {
          const raw = item.raw || {}
          return `Position: ${formatDependencyRange(raw.x)}`
        },
        afterLabel(item) {
          const raw = item.raw || {}
          return [
            `Status: ${raw.status || "-"}`,
            `Freigabe: ${raw.stateLabel || "-"}`,
            `Unteraufgaben: ${raw.dependencies || "-"}`,
            `Oberaufgaben: ${getDependentSummary(taskMap.value[String(raw.taskId)])}`
          ]
        }
      }
    }
  },
  scales: {
    x: {
      min: 0,
      max: waterfallMaxPosition.value,
      grid: {
        color: "rgba(148, 163, 184, 0.16)"
      },
      border: {
        display: false
      },
      ticks: {
        stepSize: 1,
        display: false
      },
      title: {
        display: true,
        text: "Abhaengigkeitsverlauf"
      }
    },
    y: {
      grid: {
        display: false
      },
      border: {
        display: false
      },
      ticks: {
        color: "#475569"
      }
    }
  },
  onClick: (_event, elements, chart) => {
    const first = elements?.[0]
    if (!first) return
    const raw = chart.data.datasets[first.datasetIndex]?.data?.[first.index]
    if (raw?.taskId) {
      const task = taskMap.value[String(raw.taskId)]
      if (task) openTaskViaRoute(task)
    }
  }
}))

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: "dependencies", label: "Unteraufgaben" },
  { 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",
    dependencyIds: [],
    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 normalizeDependencyIds(value, taskId = null) {
  const ownId = taskId === null || taskId === undefined ? null : String(taskId)

  return [...new Set((Array.isArray(value) ? value : [])
      .map((entry) => Number(entry))
      .filter((entry) => Number.isFinite(entry))
      .filter((entry) => String(entry) !== ownId))]
}

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),
    dependencyIds: getDependencyIds(task),
    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 normalizeTask(task) {
  return {
    ...task,
    categorie: normalizeStatus(task.categorie),
    dependencyIds: getDependencyIds(task)
  }
}

function getDependencyIds(task) {
  return normalizeDependencyIds(task?.dependencyIds ?? task?.dependency_ids ?? [], task?.id)
}

function getTaskLabel(taskId) {
  const task = taskMap.value[String(taskId)]
  return task?.name || `Aufgabe #${taskId}`
}

function getDescendantIds(taskId) {
  const seen = new Set()
  const stack = [...(taskSuccessorMap.value[String(taskId)] || [])]

  while (stack.length) {
    const current = stack.pop()
    const key = String(current)
    if (seen.has(key)) continue
    seen.add(key)
    stack.push(...(taskSuccessorMap.value[key] || []))
  }

  return seen
}

function wouldCreateDependencyCycle(taskId, dependencyIds) {
  if (!taskId) return false

  const targetKey = String(taskId)
  const dependencyKeys = normalizeDependencyIds(dependencyIds, taskId).map((id) => String(id))

  const hasPathToTask = (startKey) => {
    const visited = new Set()
    const stack = [startKey]

    while (stack.length) {
      const currentKey = stack.pop()
      if (currentKey === targetKey) return true
      if (visited.has(currentKey)) continue
      visited.add(currentKey)
      const currentTask = taskMap.value[currentKey]
      if (!currentTask) continue
      getDependencyIds(currentTask).forEach((nextId) => {
        stack.push(String(nextId))
      })
    }

    return false
  }

  return dependencyKeys.some((dependencyKey) => hasPathToTask(dependencyKey))
}

function getTaskDependencyState(task) {
  const dependencies = getDependencyIds(task)
  if (normalizeStatus(task.categorie) === "Abgeschlossen") return "done"
  if (!dependencies.length) return "ready"

  const openDependencies = dependencies.filter((dependencyId) => {
    const dependencyTask = taskMap.value[String(dependencyId)]
    return dependencyTask && normalizeStatus(dependencyTask.categorie) !== "Abgeschlossen"
  })

  return openDependencies.length ? "blocked" : "ready"
}

function getTaskDependencyStateLabel(task) {
  const state = getTaskDependencyState(task)
  if (state === "done") return "Abgeschlossen"
  if (state === "blocked") return "Blockiert"
  return "Bereit"
}

function getDependencySummary(task) {
  const dependencies = getDependencyIds(task)
  if (!dependencies.length) return "-"
  return dependencies.map((dependencyId) => getTaskLabel(dependencyId)).join(", ")
}

function getDependencyPreview(task, limit = 2) {
  const dependencies = getDependencyIds(task)
  if (!dependencies.length) return []
  return dependencies.slice(0, limit).map((dependencyId) => getTaskLabel(dependencyId))
}

function getRemainingDependencyCount(task, shownCount = 2) {
  const dependencies = getDependencyIds(task)
  return Math.max(0, dependencies.length - shownCount)
}

function getDependencyTasks(task, limit = null) {
  const dependencies = getDependencyIds(task)
      .map((dependencyId) => taskMap.value[String(dependencyId)])
      .filter(Boolean)

  return limit === null ? dependencies : dependencies.slice(0, limit)
}

function getSubtaskProgress(task) {
  const subtasks = getDependencyTasks(task)
  const total = subtasks.length
  const done = subtasks.filter((subtask) => normalizeStatus(subtask.categorie) === "Abgeschlossen").length
  return { done, total }
}

function hasSubtasks(task) {
  return getDependencyIds(task).length > 0
}

function hasOpenSubtasks(task) {
  const { done, total } = getSubtaskProgress(task)
  return total > 0 && done < total
}

function isExpanded(taskId) {
  return expandedTaskIds.value.includes(String(taskId))
}

function toggleExpanded(taskId) {
  const key = String(taskId)
  if (isExpanded(key)) {
    expandedTaskIds.value = expandedTaskIds.value.filter((id) => id !== key)
    return
  }
  expandedTaskIds.value = [...expandedTaskIds.value, key]
}

function buildWaterfallColumns(taskList) {
  const filteredIds = new Set(taskList.map((task) => String(task.id)))
  const remaining = new Map(
      taskList.map((task) => [
        String(task.id),
        {
          ...task,
          internalDependencies: getDependencyIds(task).filter((dependencyId) => filteredIds.has(String(dependencyId)))
        }
      ])
  )
  const columns = []
  let level = 1

  while (remaining.size) {
    const ready = [...remaining.values()]
        .filter((task) => task.internalDependencies.every((dependencyId) => !remaining.has(String(dependencyId))))
        .sort((a, b) => a.name.localeCompare(b.name, "de"))

    if (!ready.length) {
      columns.push({
        id: `cycle-${level}`,
        kind: "cycle",
        title: "Zyklische Abhängigkeit",
        tasks: [...remaining.values()].sort((a, b) => a.name.localeCompare(b.name, "de"))
      })
      break
    }

    columns.push({
      id: `level-${level}`,
      kind: "level",
      title: `Schritt ${level}`,
      tasks: ready
    })

    ready.forEach((task) => {
      remaining.delete(String(task.id))
    })

    level += 1
  }

  return columns
}

function buildWaterfallRows(taskList, columns) {
  const filteredIds = new Set(taskList.map((task) => String(task.id)))
  const columnTaskMeta = new Map()

  columns.forEach((column, index) => {
    column.tasks.forEach((task) => {
      columnTaskMeta.set(String(task.id), {
        columnId: column.id,
        start: index,
        end: index + 1,
        kind: column.kind
      })
    })
  })

  const getInternalDependencyIds = (task) =>
      getDependencyIds(task).filter((dependencyId) => filteredIds.has(String(dependencyId)))

  const getTaskDepth = (taskId) => {
    const meta = columnTaskMeta.get(String(taskId))
    return meta?.end || 0
  }

  const rows = []
  const childrenByParent = new Map()
  const taskById = Object.fromEntries(taskList.map((task) => [String(task.id), task]))
  const allChildIds = new Set()

  taskList.forEach((task) => {
    const meta = columnTaskMeta.get(String(task.id))
    if (!meta || meta.kind === "cycle") return

    const internalDependencies = getInternalDependencyIds(task)
    if (!internalDependencies.length) return

    childrenByParent.set(
        String(task.id),
        internalDependencies
            .map((dependencyId) => taskById[String(dependencyId)])
            .filter(Boolean)
    )

    internalDependencies.forEach((dependencyId) => {
      allChildIds.add(String(dependencyId))
    })
  })

  childrenByParent.forEach((children) => {
    children.sort((a, b) => {
      const depthDiff = getTaskDepth(a.id) - getTaskDepth(b.id)
      if (depthDiff !== 0) return depthDiff
      return (a.name || "").localeCompare(b.name || "", "de")
    })
  })

  const appendTaskAndChildren = (task) => {
    const meta = columnTaskMeta.get(String(task.id))
    if (!meta) return

    rows.push({
      id: `${meta.columnId}-${task.id}`,
      task,
      label: task.name || `Aufgabe #${task.id}`,
      start: meta.start,
      end: meta.end,
      kind: meta.kind
    })

    ;(childrenByParent.get(String(task.id)) || []).forEach((child) => {
      appendTaskAndChildren(child)
    })
  }

  const rootTasks = taskList
      .filter((task) => {
        const meta = columnTaskMeta.get(String(task.id))
        return meta && meta.kind !== "cycle" && !allChildIds.has(String(task.id))
      })
      .sort((a, b) => {
        const depthDiff = getTaskDepth(a.id) - getTaskDepth(b.id)
        if (depthDiff !== 0) return depthDiff
        return (a.name || "").localeCompare(b.name || "", "de")
      })

  rootTasks.forEach((task) => {
    appendTaskAndChildren(task)
  })

  taskList
      .filter((task) => columnTaskMeta.get(String(task.id))?.kind === "cycle")
      .sort((a, b) => (a.name || "").localeCompare(b.name || "", "de"))
      .forEach((task) => {
        if (rows.some((row) => String(row.task.id) === String(task.id))) return
        const meta = columnTaskMeta.get(String(task.id))
        rows.push({
          id: `${meta.columnId}-${task.id}`,
          task,
          label: task.name || `Aufgabe #${task.id}`,
          start: meta.start,
          end: meta.end,
          kind: meta.kind
        })
      })

  Object.keys(taskById).forEach((taskId) => {
    if (rows.some((row) => String(row.task.id) === taskId)) return
    const task = taskById[taskId]
    const meta = columnTaskMeta.get(taskId)
    if (!task || !meta) return
    rows.push({
      id: `${meta.columnId}-${task.id}`,
      task,
      label: task.name || `Aufgabe #${task.id}`,
      start: meta.start,
      end: meta.end,
      kind: meta.kind
    })
  })

  return rows
}

function formatDependencyRange(range) {
  if (!Array.isArray(range) || range.length < 2) return "-"
  const start = Number(range[0]) + 1
  const end = Number(range[1])
  if (!Number.isFinite(start) || !Number.isFinite(end)) return "-"
  return start === end ? `${end}` : `${start} bis ${end}`
}

function getDependentSummary(task) {
  if (!task?.id) return "-"
  const dependentIds = taskSuccessorMap.value[String(task.id)] || []
  if (!dependentIds.length) return "-"
  return dependentIds.map((taskId) => getTaskLabel(taskId)).join(", ")
}

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 || "-"
}

async function loadTasks() {
  loading.value = true
  try {
    const rows = await useEntities("tasks").select()
    tasks.value = rows.map((task) => normalizeTask(task))
  } 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"),
    dependencyIds: normalizeDependencyIds(initialData.dependencyIds || initialData.dependency_ids || []),
    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),
    dependencyIds: normalizeDependencyIds(taskForm.value.dependencyIds, taskForm.value.id),
    userId: taskForm.value.userId || null,
    project: toNullableNumber(taskForm.value.project),
    customer: toNullableNumber(taskForm.value.customer),
    plant: toNullableNumber(taskForm.value.plant)
  }

  if (wouldCreateDependencyCycle(taskForm.value.id, payload.dependencyIds)) {
    toast.add({
      title: "Abhängigkeit nicht möglich",
      description: "Diese Auswahl würde einen Zyklus in den Aufgaben-Abhängigkeiten erzeugen.",
      color: "red"
    })
    return
  }

  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 setTaskCompleted(task, completed) {
  if (!canCreate.value) return
  if (!task?.id) return
  if (completed && hasOpenSubtasks(task)) return

  const nextStatus = completed ? "Abgeschlossen" : "Offen"
  if (normalizeStatus(task.categorie) === nextStatus) return

  const previousStatus = task.categorie
  quickCompleteLoadingId.value = task.id
  task.categorie = nextStatus

  try {
    await useEntities("tasks").update(task.id, { categorie: nextStatus }, true)
    toast.add({
      title: completed ? "Aufgabe abgeschlossen" : "Aufgabe wieder geöffnet",
      color: completed ? "green" : "blue"
    })
  } catch (error) {
    task.categorie = previousStatus
    toast.add({ title: "Aufgabe konnte nicht aktualisiert 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 = normalizeTask(loadedTask)
      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"
            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">Ansicht: Nur eigene Aufgaben</span>
    </template>
    <template #right>
      <div class="view-toggle">
        <UButton
            size="xs"
            variant="ghost"
            icon="i-heroicons-view-columns"
            :variant="viewMode === 'kanban' ? 'solid' : 'ghost'"
            @click="viewMode = 'kanban'"
        >
          Kanban
        </UButton>
        <UButton
            size="xs"
            variant="ghost"
            icon="i-heroicons-list-bullet"
            :variant="viewMode === 'list' ? 'solid' : 'ghost'"
            @click="viewMode = 'list'"
        >
          Liste
        </UButton>
      </div>
    </template>
  </UDashboardToolbar>

  <UDashboardPanelContent>
    <div v-if="viewMode === 'kanban'" class="kanban-grid">
      <template v-for="(status, index) in STATUS_COLUMNS" :key="status">
        <section
            class="kanban-column"
            @dragover.prevent="droppingOn = status"
            @dragleave="droppingOn = ''"
            @drop.prevent="onDrop(status)"
        >
          <header class="kanban-column-header">
            <h3>{{ status }}</h3>
            <UBadge 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)" variant="soft">
                {{ getEntityLabel(projectOptions, task.project?.id || task.project) }}
              </UBadge>
              <UBadge v-if="getEntityLabel(customerOptions, task.customer?.id || task.customer)" variant="soft">
                {{ getEntityLabel(customerOptions, task.customer?.id || task.customer) }}
              </UBadge>
              <UBadge v-if="getEntityLabel(plantOptions, task.plant?.id || task.plant)" variant="soft">
                {{ getEntityLabel(plantOptions, task.plant?.id || task.plant) }}
              </UBadge>
            </div>

            <div v-if="getDependencyIds(task).length" class="kanban-card-dependencies">
              <span class="kanban-card-dependencies-label">Unteraufgaben</span>
              <div class="kanban-card-subtasks">
                <button
                    v-for="dependencyTask in getDependencyTasks(task, 3)"
                    :key="dependencyTask.id"
                    type="button"
                    class="kanban-subtask-card"
                    @click.stop="openTaskViaRoute(dependencyTask)"
                >
                  <div class="kanban-subtask-card-head">
                    <span class="kanban-subtask-card-title">{{ dependencyTask.name }}</span>
                    <UBadge size="xs" variant="soft">{{ normalizeStatus(dependencyTask.categorie) }}</UBadge>
                  </div>
                  <p v-if="dependencyTask.description" class="kanban-subtask-card-description">
                    {{ dependencyTask.description }}
                  </p>
                </button>
                <div
                    v-if="getRemainingDependencyCount(task, 3) > 0"
                    class="kanban-subtask-more"
                >
                  +{{ getRemainingDependencyCount(task, 3) }} weitere Unteraufgaben
                </div>
              </div>
            </div>
          </article>

            <div v-if="!groupedTasks[status]?.length" class="kanban-empty">
              Keine Aufgaben
            </div>
          </div>
        </section>

        <div
            v-if="index < STATUS_COLUMNS.length - 1"
            class="kanban-divider"
            aria-hidden="true"
        />
      </template>
    </div>
    <div v-else-if="viewMode === 'list' && listRootTasks.length" class="task-list">
      <article
          v-for="task in listRootTasks"
          :key="task.id"
          class="task-list-item"
      >
        <div class="task-list-row">
          <button
              v-if="hasSubtasks(task)"
              type="button"
              class="task-list-toggle"
              @click="toggleExpanded(task.id)"
          >
            <UIcon
                :name="isExpanded(task.id) ? 'i-heroicons-chevron-down' : 'i-heroicons-chevron-right'"
                class="h-4 w-4"
            />
          </button>
          <div v-else class="task-list-toggle-placeholder" />

          <button
              type="button"
              class="task-list-main"
              @click="openTaskViaRoute(task)"
          >
            <div class="task-list-main-top">
              <div>
                <div class="task-list-title">{{ task.name }}</div>
                <p v-if="task.description" class="task-list-description">{{ task.description }}</p>
              </div>
              <div class="task-list-badges">
                <UBadge variant="soft">{{ normalizeStatus(task.categorie) }}</UBadge>
                <UBadge v-if="hasSubtasks(task)" variant="outline">
                  {{ getSubtaskProgress(task).done }} von {{ getSubtaskProgress(task).total }} abgehakt
                </UBadge>
              </div>
            </div>

            <div class="task-list-meta">
              <span>{{ getAssigneeLabel(task) }}</span>
              <span v-if="getEntityLabel(projectOptions, task.project?.id || task.project)">
                {{ getEntityLabel(projectOptions, task.project?.id || task.project) }}
              </span>
              <span v-if="getEntityLabel(customerOptions, task.customer?.id || task.customer)">
                {{ getEntityLabel(customerOptions, task.customer?.id || task.customer) }}
              </span>
              <span v-if="getEntityLabel(plantOptions, task.plant?.id || task.plant)">
                {{ getEntityLabel(plantOptions, task.plant?.id || task.plant) }}
              </span>
            </div>
          </button>

          <UCheckbox
              v-if="canCreate"
              :model-value="normalizeStatus(task.categorie) === 'Abgeschlossen'"
              :disabled="quickCompleteLoadingId === task.id || hasOpenSubtasks(task)"
              :title="hasOpenSubtasks(task) ? 'Erst alle Unteraufgaben erledigen' : undefined"
              @update:model-value="(value) => setTaskCompleted(task, value)"
          />
        </div>

        <div v-if="hasSubtasks(task) && isExpanded(task.id)" class="task-list-children">
          <div
              v-for="subtask in getDependencyTasks(task)"
              :key="subtask.id"
              class="task-list-child"
          >
            <div class="task-list-child-row">
              <UCheckbox
                  v-if="canCreate"
                  :model-value="normalizeStatus(subtask.categorie) === 'Abgeschlossen'"
                  :disabled="quickCompleteLoadingId === subtask.id"
                  @update:model-value="(value) => setTaskCompleted(subtask, value)"
              />
              <button
                  type="button"
                  class="task-list-child-main"
                  @click="openTaskViaRoute(subtask)"
              >
                <div class="task-list-child-head">
                  <span class="task-list-child-title">{{ subtask.name }}</span>
                  <UBadge size="xs" variant="soft">{{ normalizeStatus(subtask.categorie) }}</UBadge>
                </div>
                <p v-if="subtask.description" class="task-list-child-description">{{ subtask.description }}</p>
              </button>
            </div>
          </div>
        </div>
      </article>
    </div>
    <UAlert
        v-else
        icon="i-heroicons-circle-stack-20-solid"
        title="Keine Aufgaben anzuzeigen"
        variant="subtle"
    />
  </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 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>

        <div>
          <label class="form-label">Unteraufgaben</label>
          <USelectMenu
              v-model="taskForm.dependencyIds"
              :options="dependencyOptions"
              value-attribute="value"
              option-attribute="label"
              :disabled="isFormReadonly || !canCreate"
              multiple
              searchable
              clear-search-on-close
          >
            <template #label>
              {{
                taskForm.dependencyIds?.length
                    ? `${taskForm.dependencyIds.length} Unteraufgabe${taskForm.dependencyIds.length === 1 ? "" : "n"}`
                    : "Keine Unteraufgaben"
              }}
            </template>
          </USelectMenu>
        </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"
                variant="soft"
                :loading="deleting"
                @click="archiveTask"
            >
              Archivieren
            </UButton>
          </div>

          <div class="flex gap-2">
            <UButton variant="ghost" @click="closeModal">Schließen</UButton>
            <UButton
                v-if="modalMode === 'show' && canCreate"
                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: 1.25rem;
  align-items: start;
}

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

.kanban-column {
  border: 1px solid var(--ui-border);
  border-radius: 0.75rem;
  background: var(--ui-bg);
  min-height: 500px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  box-shadow: 0 1px 2px color-mix(in oklab, var(--ui-text) 10%, transparent);
}

.kanban-divider {
  display: none;
}

@media (min-width: 1024px) {
  .kanban-divider {
    display: block;
    align-self: stretch;
    width: 1px;
    border-radius: 999px;
    background:
        linear-gradient(
            to bottom,
            transparent,
            color-mix(in oklab, var(--ui-border) 78%, var(--ui-bg-elevated)) 10%,
            color-mix(in oklab, var(--ui-border) 78%, var(--ui-bg-elevated)) 90%,
            transparent
        );
    opacity: 0.95;
  }
}

.kanban-column-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--ui-border);
  background: var(--ui-bg-muted);
}

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

.kanban-dropzone-active {
  background: var(--ui-bg-muted);
}

.kanban-card {
  border: 1px solid var(--ui-border);
  background: var(--ui-bg-elevated);
  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: var(--ui-text-dimmed);
  font-size: 0.875rem;
  line-height: 1.15rem;
}

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

.kanban-card-dependencies {
  margin-top: 0.7rem;
  padding-top: 0.65rem;
  border-top: 1px dashed color-mix(in oklab, var(--ui-border) 82%, transparent);
}

.kanban-card-dependencies-label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--ui-text-dimmed);
}

.kanban-card-dependency-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.kanban-card-subtasks {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.kanban-subtask-card {
  width: 100%;
  text-align: left;
  border: 1px solid color-mix(in oklab, var(--ui-border) 88%, transparent);
  background: color-mix(in oklab, var(--ui-bg-elevated) 78%, white 22%);
  border-radius: 0.55rem;
  padding: 0.55rem 0.6rem;
  transition: border-color 0.2s ease, transform 0.2s ease, background-color 0.2s ease;
}

.kanban-subtask-card:hover {
  border-color: color-mix(in oklab, var(--ui-primary) 40%, var(--ui-border));
  background: color-mix(in oklab, var(--ui-bg-elevated) 88%, white 12%);
  transform: translateY(-1px);
}

.kanban-subtask-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
}

.kanban-subtask-card-title {
  font-size: 0.83rem;
  font-weight: 600;
  line-height: 1.15rem;
  color: var(--ui-text);
}

.kanban-subtask-card-description {
  margin-top: 0.3rem;
  font-size: 0.8rem;
  line-height: 1.1rem;
  color: var(--ui-text-dimmed);
}

.kanban-subtask-more {
  font-size: 0.78rem;
  color: var(--ui-text-dimmed);
  padding: 0.1rem 0.15rem 0;
}

.kanban-empty {
  border: 1px dashed var(--ui-border);
  color: var(--ui-text-dimmed);
  border-radius: 0.6rem;
  padding: 0.7rem;
  font-size: 0.875rem;
}

.waterfall-shell {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.waterfall-card-shell {
  border: 1px solid var(--ui-border);
  border-radius: 0.85rem;
  background: var(--ui-bg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 1px 2px color-mix(in oklab, var(--ui-text) 10%, transparent);
  padding: 1rem;
  gap: 1rem;
}

.waterfall-chart-wrap {
  position: relative;
  min-height: 20rem;
}

.waterfall-hint {
  font-size: 0.875rem;
  color: var(--ui-text-dimmed);
}

.task-list {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.task-list-item {
  border: 1px solid var(--ui-border);
  border-radius: 0.85rem;
  background: var(--ui-bg);
  overflow: hidden;
  box-shadow: 0 1px 2px color-mix(in oklab, var(--ui-text) 10%, transparent);
}

.task-list-row {
  display: flex;
  align-items: stretch;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
}

.task-list-toggle,
.task-list-toggle-placeholder {
  width: 2rem;
  flex: 0 0 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.task-list-toggle {
  border-radius: 0.55rem;
  color: var(--ui-text-dimmed);
  transition: background-color 0.2s ease, color 0.2s ease;
}

.task-list-toggle:hover {
  background: var(--ui-bg-muted);
  color: var(--ui-text);
}

.task-list-main {
  flex: 1;
  text-align: left;
}

.task-list-main-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.8rem;
}

.task-list-title {
  font-weight: 600;
  line-height: 1.25rem;
  color: var(--ui-text);
}

.task-list-description {
  margin-top: 0.3rem;
  font-size: 0.875rem;
  line-height: 1.2rem;
  color: var(--ui-text-dimmed);
}

.task-list-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.4rem;
}

.task-list-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.6rem;
  font-size: 0.85rem;
  color: var(--ui-text-dimmed);
}

.task-list-children {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0 1rem 1rem 3.75rem;
}

.task-list-child {
  border: 1px solid color-mix(in oklab, var(--ui-border) 88%, transparent);
  background: var(--ui-bg-elevated);
  border-radius: 0.65rem;
  padding: 0.7rem 0.8rem;
}

.task-list-child-row {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
}

.task-list-child-main {
  flex: 1;
  text-align: left;
}

.task-list-child-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.75rem;
}

.task-list-child-title {
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.2rem;
  color: var(--ui-text);
}

.task-list-child-description {
  margin-top: 0.3rem;
  font-size: 0.82rem;
  line-height: 1.15rem;
  color: var(--ui-text-dimmed);
}

.form-label {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
  color: var(--ui-text);
}

.view-toggle {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border: 1px solid var(--ui-border);
  border-radius: 0.5rem;
  padding: 0.25rem;
}
</style>
