<script setup>
import dayjs from "dayjs"

const props = defineProps({
  item: {
    required: true,
    type: Object
  }
})

const loading = ref(true)
const incomingInvoices = ref([])
const createddocuments = ref([])
const costcentres = ref([])
const selectedYear = ref(String(dayjs().year()))
const selectedMonth = ref("all")

const currency = (value) => `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`

const getCostCentreId = (value) => {
  if (!value) {
    return null
  }

  return typeof value === "object" ? value.id : value
}

const costCentreMap = computed(() => {
  return new Map(costcentres.value.map((costcentre) => [costcentre.id, costcentre]))
})

const relevantCostCentreIds = computed(() => {
  const rootId = props.item?.id

  if (!rootId) {
    return new Set()
  }

  const childrenByParent = new Map()

  costcentres.value.forEach((costcentre) => {
    const parentId = getCostCentreId(costcentre.parentCostcentre)

    if (!parentId) {
      return
    }

    if (!childrenByParent.has(parentId)) {
      childrenByParent.set(parentId, [])
    }

    childrenByParent.get(parentId).push(costcentre.id)
  })

  const collectedIds = new Set([rootId])
  const queue = [rootId]

  while (queue.length > 0) {
    const currentId = queue.shift()
    const childIds = childrenByParent.get(currentId) || []

    childIds.forEach((childId) => {
      if (collectedIds.has(childId)) {
        return
      }

      collectedIds.add(childId)
      queue.push(childId)
    })
  }

  return collectedIds
})

const yearItems = computed(() => {
  const years = [...new Set(
    incomingInvoices.value
      .map((invoice) => invoice.date ? String(dayjs(invoice.date).year()) : null)
      .filter(Boolean)
  )].sort((a, b) => Number(b) - Number(a))

  return years.length > 0 ? years.map((year) => ({ label: year, value: year })) : [{ label: String(dayjs().year()), value: String(dayjs().year()) }]
})

const monthItems = [
  { label: "Ganzes Jahr", value: "all" },
  { label: "Januar", value: "1" },
  { label: "Februar", value: "2" },
  { label: "März", value: "3" },
  { label: "April", value: "4" },
  { label: "Mai", value: "5" },
  { label: "Juni", value: "6" },
  { label: "Juli", value: "7" },
  { label: "August", value: "8" },
  { label: "September", value: "9" },
  { label: "Oktober", value: "10" },
  { label: "November", value: "11" },
  { label: "Dezember", value: "12" }
]

const reportRows = computed(() => {
  const incomingRows = incomingInvoices.value.flatMap((invoice) => {
    const invoiceDate = invoice.date ? dayjs(invoice.date) : null

    if (invoiceDate && invoiceDate.year().toString() !== selectedYear.value) {
      return []
    }

    if (invoiceDate && selectedMonth.value !== "all" && invoiceDate.month() + 1 !== Number(selectedMonth.value)) {
      return []
    }

    const matchingAccounts = (invoice.accounts || []).filter((account) =>
      relevantCostCentreIds.value.has(account.costCentre)
    )

    return matchingAccounts.map((account, index) => {
      const amountNet = Number(account.amountNet || 0)
      const amountTax = Number(account.amountTax || 0)
      const amountGross = Number(account.amountGross || amountNet + amountTax || 0)
      const accountCostCentre = costCentreMap.value.get(getCostCentreId(account.costCentre))

      return {
        id: `incoming-${invoice.id}-${index}`,
        sourceLabel: "Eingangsbeleg",
        invoiceId: invoice.id,
        reference: invoice.reference || "-",
        date: invoice.date,
        state: invoice.state || "-",
        vendorName: invoice.vendor?.name || "-",
        accountLabel: account.account?.label || account.accountLabel || "-",
        costCentreName: accountCostCentre ? `${accountCostCentre.number} - ${accountCostCentre.name}` : "-",
        description: account.description || invoice.description || "-",
        amountNet,
        amountTax,
        amountGross
      }
    })
  })

  const outgoingRows = createddocuments.value.flatMap((document) => {
    const documentDate = document.documentDate ? dayjs(document.documentDate) : null

    if (documentDate && documentDate.year().toString() !== selectedYear.value) {
      return []
    }

    if (documentDate && selectedMonth.value !== "all" && documentDate.month() + 1 !== Number(selectedMonth.value)) {
      return []
    }

    return (document.rows || [])
      .filter((row) => !["pagebreak", "title", "text"].includes(row.mode))
      .map((row, index) => {
        const costCentreId = getCostCentreId(row.costCentre || row.costcentre || document.costcentre)

        if (!relevantCostCentreIds.value.has(costCentreId)) {
          return null
        }

        const amountNet = Number((Number(row.quantity || 0) * Number(row.price || 0) * (1 - Number(row.discountPercent || 0) / 100)).toFixed(2))
        const taxPercent = Number(row.taxPercent || 0)
        const amountTax = Number((amountNet * (taxPercent / 100)).toFixed(2))
        const amountGross = Number((amountNet + amountTax).toFixed(2))
        const accountCostCentre = costCentreMap.value.get(costCentreId)

        return {
          id: `outgoing-${document.id}-${index}`,
          sourceLabel: "Ausgangsbeleg",
          invoiceId: document.id,
          reference: document.documentNumber || document.title || "-",
          date: document.documentDate,
          state: document.state || "-",
          vendorName: document.customer?.name || "-",
          accountLabel: "Umsatz",
          costCentreName: accountCostCentre ? `${accountCostCentre.number} - ${accountCostCentre.name}` : "-",
          description: row.text || row.description || document.description || "-",
          amountNet,
          amountTax,
          amountGross
        }
      })
      .filter(Boolean)
  })

  return [...incomingRows, ...outgoingRows]
})

const totals = computed(() => {
  return reportRows.value.reduce((acc, row) => {
    acc.net += row.amountNet
    acc.tax += row.amountTax
    acc.gross += row.amountGross
    return acc
  }, { net: 0, tax: 0, gross: 0 })
})

const columns = [
  { accessorKey: "sourceLabel", header: "Art" },
  { accessorKey: "reference", header: "Beleg" },
  { accessorKey: "date", header: "Datum" },
  { accessorKey: "vendorName", header: "Kontakt" },
  { accessorKey: "accountLabel", header: "Konto" },
  { accessorKey: "costCentreName", header: "Kostenstelle" },
  { accessorKey: "description", header: "Beschreibung" },
  { accessorKey: "amountNet", header: "Netto" },
  { accessorKey: "amountTax", header: "Steuer" },
  { accessorKey: "amountGross", header: "Brutto" }
]

const setupPage = async () => {
  loading.value = true

  costcentres.value = await useEntities("costcentres").select("*", null, false, true)
  const invoices = await useEntities("incominginvoices").select("*, vendor(id,name)")
  const documents = await useEntities("createddocuments").select("*, customer(id,name)")

  incomingInvoices.value = invoices.filter((invoice) =>
    (invoice.accounts || []).some((account) => relevantCostCentreIds.value.has(account.costCentre))
  )
  createddocuments.value = documents.filter((document) =>
    ["invoices", "advanceInvoices", "cancellationInvoices"].includes(document.type)
    && document.state === "Gebucht"
    && (document.rows || []).some((row) => relevantCostCentreIds.value.has(getCostCentreId(row.costCentre || row.costcentre || document.costcentre)))
  )

  const firstYear = yearItems.value[0]?.value
  if (firstYear && !yearItems.value.some((item) => item.value === selectedYear.value)) {
    selectedYear.value = firstYear
  }

  loading.value = false
}

setupPage()
</script>

<template>
  <div class="space-y-4">
    <div class="flex flex-col gap-3 md:flex-row md:items-end">
      <UFormField label="Jahr" class="w-full md:w-48">
        <USelectMenu
            v-model="selectedYear"
            :items="yearItems"
            value-key="value"
            label-key="label"
            class="w-full"
        />
      </UFormField>

      <UFormField label="Monat" class="w-full md:w-56">
        <USelectMenu
            v-model="selectedMonth"
            :items="monthItems"
            value-key="value"
            label-key="label"
            class="w-full"
        />
      </UFormField>
    </div>

    <div class="grid gap-3 md:grid-cols-3">
      <UCard>
        <div class="text-sm text-gray-500 dark:text-gray-400">Netto gesamt</div>
        <div class="mt-1 text-xl font-semibold">{{ currency(totals.net) }}</div>
      </UCard>

      <UCard>
        <div class="text-sm text-gray-500 dark:text-gray-400">Steuer gesamt</div>
        <div class="mt-1 text-xl font-semibold">{{ currency(totals.tax) }}</div>
      </UCard>

      <UCard>
        <div class="text-sm text-gray-500 dark:text-gray-400">Brutto gesamt</div>
        <div class="mt-1 text-xl font-semibold">{{ currency(totals.gross) }}</div>
      </UCard>
    </div>

    <UTable
        v-if="!loading"
        :data="reportRows"
        :columns="columns"
        class="w-full"
    >
      <template #reference-cell="{ row }">
        <div class="truncate font-medium">{{ row.original.reference }}</div>
      </template>

      <template #date-cell="{ row }">
        <div class="truncate">{{ row.original.date ? dayjs(row.original.date).format("DD.MM.YYYY") : "-" }}</div>
      </template>

      <template #vendorName-cell="{ row }">
        <div class="truncate">{{ row.original.vendorName }}</div>
      </template>

      <template #accountLabel-cell="{ row }">
        <div class="truncate">{{ row.original.accountLabel }}</div>
      </template>

      <template #costCentreName-cell="{ row }">
        <div class="truncate">{{ row.original.costCentreName }}</div>
      </template>

      <template #description-cell="{ row }">
        <UTooltip :text="row.original.description">
          <div class="max-w-[18rem] truncate">{{ row.original.description }}</div>
        </UTooltip>
      </template>

      <template #amountNet-cell="{ row }">
        <div class="text-right tabular-nums">{{ currency(row.original.amountNet) }}</div>
      </template>

      <template #amountTax-cell="{ row }">
        <div class="text-right tabular-nums">{{ currency(row.original.amountTax) }}</div>
      </template>

      <template #amountGross-cell="{ row }">
        <div class="text-right font-medium tabular-nums">{{ currency(row.original.amountGross) }}</div>
      </template>
      <template #empty>
        <TableEmptyState label="Keine Belege mit dieser Kostenstelle oder ihren Unterkostenstellen gefunden" />
      </template>
    </UTable>

    <UProgress v-else animation="carousel" class="w-3/4 mx-auto" />
  </div>
</template>
