<script setup>
import InputGroup from "~/components/InputGroup.vue";
import dayjs from "dayjs";
import { useDraggable } from '@vueuse/core'

// --- Standard Setup & Data ---
const dataStore = useDataStore()
const route = useRoute()
const mode = ref(route.params.mode)
const toast = useToast()

// --- Page Leave Logic ---
const isModified = ref(false) // Speichert, ob Änderungen vorgenommen wurden

// State für das PDF Fenster
const isPdfDetached = ref(false)
const pdfEl = ref(null)
const { style: pdfStyle } = useDraggable(pdfEl, {
  initialValue: { x: 50, y: 100 },
})

const itemInfo = ref({
  vendor: null,
  expense: true,
  reference: "",
  date:  null,
  dueDate: null,
  paymentType: "Überweisung",
  description: "",
  state: "Entwurf",
  accounts: [
    {
      account: null,
      amountNet: null,
      amountTax: null,
      taxType: "19",
      costCentre: null,
      amountGross: null
    }
  ]
})

const costcentres = ref([])
const vendors = ref([])
const accounts = ref([])
const loadedFileId = ref(null)

const setup = async () => {
  // 1. Daten laden
  costcentres.value = await useEntities("costcentres").select()
  vendors.value = await useEntities("vendors").select()
  accounts.value = await useEntities("accounts").selectSpecial()

  const invoiceData = await useEntities("incominginvoices").selectSingle(route.params.id, "*, files(*)")

  // 2. Mapping
  itemInfo.value = {
    ...invoiceData,
    vendor: invoiceData.vendor?.id || invoiceData.vendor,
    accounts: invoiceData.accounts || []
  }

  // Fallback Accounts
  if(itemInfo.value.accounts.length === 0) {
    itemInfo.value.accounts.push({ account: null, amountNet: null, amountTax: null, taxType: "19", costCentre: null })
  }

  // Datei laden
  if (itemInfo.value.files && itemInfo.value.files.length > 0) {
    loadedFileId.value = itemInfo.value.files[itemInfo.value.files.length-1].id
  }

  if(itemInfo.value.date && !itemInfo.value.dueDate) itemInfo.value.dueDate = itemInfo.value.date

  // 3. Watcher initialisieren (erst NACH dem Laden der Daten)
  // Wir warten einen Tick, damit die Initialisierung nicht als Änderung zählt
  await nextTick()
  isModified.value = false // Sicherstellen, dass Status sauber ist

  watch(itemInfo, () => {
    if (mode.value !== 'show') {
      isModified.value = true
    }
  }, { deep: true })
}

setup()

// --- Berechnungslogik ---
const useNetMode = ref(false)

const taxOptions = ref([
  { label: "19% USt", percentage: 19, key: "19" },
  { label: "7% USt", percentage: 7, key: "7" },
  { label: "IG Erwerb 19%", percentage: 0, key: "19I" },
  { label: "IG Erwerb 7%", percentage: 0, key: "7I" },
  { label: "§13b UStG", percentage: 0, key: "13B" },
  { label: "Keine USt", percentage: 0, key: "null" },
])

const totalCalculated = computed(() => {
  let totalNet = 0
  let totalAmount19Tax = 0
  let totalAmount7Tax = 0
  let totalGross = 0

  itemInfo.value.accounts.forEach(account => {
    if(account.amountNet) totalNet += Number(account.amountNet)

    if(account.taxType === "19" && account.amountTax) {
      totalAmount19Tax += Number(account.amountTax)
    } else if(account.taxType === "7" && account.amountTax) {
      totalAmount7Tax += Number(account.amountTax)
    }
  })

  totalGross = Number(totalNet + totalAmount19Tax + totalAmount7Tax)

  return { totalNet, totalAmount19Tax, totalAmount7Tax, totalGross }
})

const hasAmount = (value) => value !== null && value !== undefined && value !== ""
const hasValidNumber = (value) => hasAmount(value) && Number.isFinite(Number(value))

const recalculateItem = (item, source) => {
  const taxRate = Number(taxOptions.value.find(i => i.key === item.taxType)?.percentage || 0);
  const calculateFromNet = () => {
    if(!hasAmount(item.amountNet)) return
    item.amountTax = Number((item.amountNet * (taxRate/100)).toFixed(2))
    item.amountGross = Number((Number(item.amountNet) + item.amountTax).toFixed(2))
  }
  const calculateFromGross = () => {
    if(!hasAmount(item.amountGross)) return
    item.amountNet = Number((item.amountGross / (1 + taxRate/100)).toFixed(2))
    item.amountTax = Number((item.amountGross - item.amountNet).toFixed(2))
  }

  if (source === 'net') {
    calculateFromNet()
  } else if (source === 'gross') {
    calculateFromGross()
  } else if (source === 'taxType' || source === 'manual') {
    if(hasAmount(item.amountNet)) calculateFromNet()
    else if(hasAmount(item.amountGross)) calculateFromGross()
  }
}

const moveGrossToNet = (item) => {
  if(!hasAmount(item.amountGross)) return
  item.amountNet = Number(item.amountGross)
  recalculateItem(item, 'net')
}

// --- Saving ---
const updateIncomingInvoice = async (setBooked = false) => {
  if (setBooked && hasBlockingIncomingInvoiceErrors.value) {
    toast.add({
      title: "Buchen nicht möglich",
      description: "Bitte beheben Sie zuerst die rot markierten Pflichtfehler.",
      color: "rose"
    })
    return
  }

  let item = { ...itemInfo.value }
  delete item.files
  item.state = setBooked ? "Gebucht" : "Entwurf"

  await useEntities('incominginvoices').update(itemInfo.value.id, item, !setBooked)

  // WICHTIG: Nach dem Speichern ist das Formular "sauber"
  isModified.value = false
}

const findIncomingInvoiceErrors = computed(() => {
  const errors = []
  const i = itemInfo.value

  if(!i.vendor) errors.push({message: "Es ist kein Lieferant ausgewählt", type: "breaking"})
  if(!i.reference || !String(i.reference).trim()) errors.push({message: "Es ist keine Referenz angegeben", type: "breaking"})
  if(!i.date) errors.push({message: "Es ist kein Datum ausgewählt", type: "breaking"})
  if(!i.accounts || i.accounts.length === 0) errors.push({message: "Es ist keine Position vorhanden", type: "breaking"})

  i.accounts.forEach((account, idx) => {
    if(!account.account) errors.push({message: `Pos ${idx+1}: Keine Kategorie`, type: "breaking"})
    if(!hasValidNumber(account.amountNet) && !hasValidNumber(account.amountGross)) {
      errors.push({message: `Pos ${idx+1}: Kein gültiger Betrag`, type: "breaking"})
    }
    if(!account.taxType) errors.push({message: `Pos ${idx+1}: Kein Steuerschlüssel`, type: "breaking"})
    if(hasValidNumber(account.amountNet) && !hasValidNumber(account.amountTax)) {
      errors.push({message: `Pos ${idx+1}: Steuerbetrag fehlt, bitte Steuer neu berechnen`, type: "warning"})
    }
  })

  const order = { breaking: 0, warning: 1 }
  return errors.sort((a,b) => order[a.type] - order[b.type])
})

const blockingIncomingInvoiceErrors = computed(() => findIncomingInvoiceErrors.value.filter(i => i.type === "breaking"))
const warningIncomingInvoiceErrors = computed(() => findIncomingInvoiceErrors.value.filter(i => i.type === "warning"))
const hasBlockingIncomingInvoiceErrors = computed(() => blockingIncomingInvoiceErrors.value.length > 0)
</script>

<template>
  <UDashboardNavbar>
    <template #left>
      <UButton
          icon="i-heroicons-chevron-left"
          @click="navigateTo(`/incomingInvoices`)"
          variant="outline"
      >
        Eingangsbelege
      </UButton>
    </template>
    <template #center>
      <h1 class="text-xl font-medium">
        {{`Eingangsbeleg ${mode === 'show' ? 'anzeigen' : 'bearbeiten'}`}}
      </h1>
    </template>
    <template #right>
      <ArchiveButton
          v-if="mode !== 'show'"
          color="rose"
          variant="outline"
          type="incominginvoices"
          @confirmed="useEntities('incominginvoices').archive(route.params.id)"
      />
      <UButton v-if="mode !== 'show'" @click="updateIncomingInvoice(false)">
        Speichern
      </UButton>
      <UButton
          v-if="mode !== 'show'"
          @click="updateIncomingInvoice(true)"
          :disabled="hasBlockingIncomingInvoiceErrors"
      >
        Speichern & Buchen
      </UButton>
    </template>
  </UDashboardNavbar>

  <UDashboardPanelContent class="p-0 overflow-hidden relative">
    <div class="flex h-[calc(100vh-4rem)]">

      <div
          v-if="!isPdfDetached && loadedFileId"
          class="w-1/2 h-full bg-gray-100 border-r border-gray-200 dark:bg-gray-800 dark:border-gray-700 flex flex-col"
      >
        <div class="p-2 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 flex justify-between items-center">
          <span class="text-xs text-gray-500 font-mono pl-2">Vorschau</span>
          <UTooltip text="Dokument lösen (Draggable Window)">
            <UButton
                icon="i-heroicons-arrows-pointing-out"
                variant="ghost"
                size="xs"
                @click="isPdfDetached = true"
            >
              Lösen
            </UButton>
          </UTooltip>
        </div>
        <div class="flex-grow overflow-hidden relative">
          <PDFViewer
              :file-id="loadedFileId"
              location="split_view"
              class="h-full w-full"
          />
        </div>
      </div>

      <div
          class="flex flex-col bg-white dark:bg-gray-900 overflow-y-auto transition-all duration-300"
          :class="(!isPdfDetached && loadedFileId) ? 'w-1/2' : 'w-full'"
      >
        <div class="p-6 max-w-4xl mx-auto w-full space-y-6 pb-20">

          <UButton
              v-if="isPdfDetached && loadedFileId"
              icon="i-heroicons-arrows-pointing-in"
              variant="outline"
              class="mb-4"
              @click="isPdfDetached = false"
          >
            Dokument andocken
          </UButton>

          <UAlert
              v-if="findIncomingInvoiceErrors.length > 0"
              title="Prüfung erforderlich"
              :color="hasBlockingIncomingInvoiceErrors ? 'rose' : 'orange'"
              variant="soft"
              icon="i-heroicons-exclamation-triangle"
          >
            <template #description>
              <div class="space-y-3 text-sm mt-1">
                <div v-if="blockingIncomingInvoiceErrors.length > 0">
                  <p class="font-semibold text-rose-700 dark:text-rose-300">Pflichtfehler</p>
                  <ul class="list-disc list-inside mt-1">
                    <li
                        v-for="(err, idx) in blockingIncomingInvoiceErrors"
                        :key="`blocking-${idx}-${err.message}`"
                    >
                      {{ err.message }}
                    </li>
                  </ul>
                </div>
                <div v-if="warningIncomingInvoiceErrors.length > 0">
                  <p class="font-semibold text-orange-700 dark:text-orange-300">Hinweise</p>
                  <ul class="list-disc list-inside mt-1">
                    <li
                        v-for="(err, idx) in warningIncomingInvoiceErrors"
                        :key="`warning-${idx}-${err.message}`"
                    >
                      {{ err.message }}
                    </li>
                  </ul>
                </div>
              </div>
            </template>
          </UAlert>

          <UCard>
            <template #header>
              <div class="flex justify-between items-center">
                <h3 class="font-semibold">Stammdaten</h3>
                <div class="flex bg-gray-100 dark:bg-gray-800 p-1 rounded-lg">
                  <UButton size="xs" :variant="itemInfo.expense ? 'solid' : 'ghost'" color="rose" @click="itemInfo.expense = true" :disabled="mode === 'show'">Ausgabe</UButton>
                  <UButton size="xs" :variant="!itemInfo.expense ? 'solid' : 'ghost'" color="emerald" @click="itemInfo.expense = false" :disabled="mode === 'show'">Einnahme</UButton>
                </div>
              </div>
            </template>

            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <UFormGroup label="Lieferant / Partner" class="md:col-span-2">
                <div class="flex gap-2">
                  <USelectMenu
                      class="w-full"
                      v-model="itemInfo.vendor"
                      :options="vendors"
                      option-attribute="name"
                      value-attribute="id"
                      searchable
                      :disabled="mode === 'show'"
                      :search-attributes="['name', 'vendorNumber']"
                      placeholder="Lieferant suchen..."
                  >
                    <template #label>
                      {{ vendors.find(v => v.id === itemInfo.vendor)?.name || 'Bitte wählen' }}
                    </template>
                    <template #option="{ option }">
                      <span class="font-mono text-xs opacity-75 mr-2">{{ option.vendorNumber }}</span> {{ option.name }}
                    </template>
                  </USelectMenu>
                  <UButton
                      v-if="mode !== 'show'"
                      icon="i-heroicons-x-mark"
                      variant="outline"
                      color="rose"
                      :disabled="!itemInfo.vendor"
                      @click="itemInfo.vendor = null"
                  />
                  <EntityModalButtons
                      v-if="mode !== 'show'"
                      type="vendors"
                      :id="itemInfo.vendor"
                      @return-data="(data) => itemInfo.vendor = data.id"
                  />
                </div>
              </UFormGroup>

              <UFormGroup label="Rechnungsnummer">
                <UInput v-model="itemInfo.reference" icon="i-heroicons-hashtag" :disabled="mode === 'show'" />
              </UFormGroup>

              <UFormGroup label="Zahlart">
                <USelectMenu v-model="itemInfo.paymentType" :options="['Überweisung', 'Lastschrift', 'Kreditkarte', 'PayPal', 'Bar', 'Sonstiges']" :disabled="mode === 'show'" />
              </UFormGroup>

              <UFormGroup label="Rechnungsdatum">
                <UPopover :popper="{ placement: 'bottom-start' }">
                  <UButton block color="white" icon="i-heroicons-calendar" :label="itemInfo.date ? dayjs(itemInfo.date).format('DD.MM.YYYY') : '-'" :disabled="mode === 'show'" />
                  <template #panel="{ close }">
                    <LazyDatePicker v-model="itemInfo.date" @close="() => { if(!itemInfo.dueDate) itemInfo.dueDate = itemInfo.date; close() }" />
                  </template>
                </UPopover>
              </UFormGroup>

              <UFormGroup label="Fälligkeitsdatum">
                <UPopover :popper="{ placement: 'bottom-start' }">
                  <UButton block color="white" icon="i-heroicons-calendar" :label="itemInfo.dueDate ? dayjs(itemInfo.dueDate).format('DD.MM.YYYY') : '-'" :disabled="mode === 'show'" />
                  <template #panel="{ close }">
                    <LazyDatePicker v-model="itemInfo.dueDate" @close="close" />
                  </template>
                </UPopover>
              </UFormGroup>

              <UFormGroup label="Beschreibung / Notiz" class="md:col-span-2">
                <UTextarea v-model="itemInfo.description" :rows="2" autoresize :disabled="mode === 'show'" />
              </UFormGroup>
            </div>
          </UCard>

          <div class="space-y-4">
            <div class="flex justify-between items-end border-b pb-2 dark:border-gray-700">
              <h3 class="font-semibold text-lg">Positionen</h3>
              <div class="flex items-center gap-2 text-sm">
                <span :class="{'font-bold': !useNetMode, 'opacity-50': useNetMode}">Brutto</span>
                <UToggle v-model="useNetMode" color="primary" :disabled="mode === 'show'" />
                <span :class="{'font-bold': useNetMode, 'opacity-50': !useNetMode}">Netto Eingabe</span>
              </div>
            </div>

            <UCard
                v-for="(item, index) in itemInfo.accounts"
                :key="index"
                :ui="{ body: { padding: 'p-4 sm:p-4' } }"
                class="relative border-l-4"
                :class="item.amountNet ? 'border-l-primary-500' : 'border-l-gray-300 dark:border-l-gray-700'"
            >
              <UButton
                  v-if="itemInfo.accounts.length > 1 && mode !== 'show'"
                  icon="i-heroicons-trash"
                  color="rose"
                  variant="ghost"
                  size="xs"
                  class="absolute top-2 right-2"
                  @click="itemInfo.accounts.splice(index, 1)"
              />

              <div class="grid grid-cols-12 gap-3">
                <div class="col-span-12 md:col-span-6">
                  <UFormGroup label="Konto / Kategorie">
                    <USelectMenu
                        v-model="item.account"
                        :options="accounts"
                        searchable
                        placeholder="Kategorie wählen"
                        option-attribute="label"
                        value-attribute="id"
                        :disabled="mode === 'show'"
                        :search-attributes="['label', 'number']"
                    >
                      <template #option="{ option }">
                        <span class="font-mono text-xs text-gray-500 mr-2">{{ option.number }}</span> {{ option.label }}
                      </template>
                      <template #label>
                        {{ accounts.find(a => a.id === item.account)?.label || 'Auswählen' }}
                      </template>
                    </USelectMenu>
                  </UFormGroup>
                </div>

                <div class="col-span-12 md:col-span-6">
                  <UFormGroup label="Kostenstelle">
                    <USelectMenu
                        v-model="item.costCentre"
                        :options="costcentres"
                        searchable
                        option-attribute="name"
                        value-attribute="id"
                        placeholder="Optional"
                        :disabled="mode === 'show'"
                    >
                      <template #label>
                        {{ costcentres.find(c => c.id === item.costCentre)?.name || 'Keine' }}
                      </template>
                    </USelectMenu>
                  </UFormGroup>
                </div>

                <div class="col-span-12 md:col-span-3">
                  <UFormGroup label="Betrag (Netto)">
                    <UInput
                        type="number"
                        step="0.01"
                        :disabled="mode === 'show' || !useNetMode"
                        :model-value="item.amountNet"
                        @update:model-value="(val) => { item.amountNet = Number(val); recalculateItem(item, 'net') }"
                    >
                      <template #trailing>€</template>
                    </UInput>
                  </UFormGroup>
                </div>

                <div class="col-span-12 md:col-span-3">
                  <UFormGroup label="Betrag (Brutto)">
                    <UInput
                        type="number"
                        step="0.01"
                        :disabled="mode === 'show' || useNetMode"
                        :model-value="item.amountGross"
                        @update:model-value="(val) => { item.amountGross = Number(val); recalculateItem(item, 'gross') }"
                    >
                      <template #trailing>€</template>
                    </UInput>
                  </UFormGroup>
                </div>

                <div class="col-span-6 md:col-span-3">
                  <UFormGroup label="Steuerschlüssel">
                    <USelectMenu
                        v-model="item.taxType"
                        :options="taxOptions"
                        value-attribute="key"
                        option-attribute="label"
                        :disabled="mode === 'show'"
                        @change="recalculateItem(item, 'taxType')"
                    />
                  </UFormGroup>
                </div>

                <div class="col-span-6 md:col-span-3">
                  <UFormGroup label="Steuerbetrag" help="Automatisch berechnet">
                    <UInput :model-value="item.amountTax" disabled color="gray" >
                      <template #trailing>€</template>
                    </UInput>
                  </UFormGroup>
                </div>

                <div class="col-span-12 flex justify-end gap-2">
                  <UButton
                      size="xs"
                      variant="outline"
                      icon="i-heroicons-calculator"
                      :disabled="mode === 'show'"
                      @click="recalculateItem(item, 'manual')"
                  >
                    Steuer berechnen
                  </UButton>
                  <UButton
                      size="xs"
                      variant="soft"
                      icon="i-heroicons-arrow-right"
                      :disabled="mode === 'show' || !hasAmount(item.amountGross)"
                      @click="moveGrossToNet(item)"
                  >
                    Brutto als Netto
                  </UButton>
                </div>

                <div class="col-span-12">
                  <UInput v-model="item.description" :disabled="mode === 'show'" placeholder="Positionstext (optional)" icon="i-heroicons-bars-3-bottom-left" variant="none" class="border-b border-gray-100 dark:border-gray-800" />
                </div>
              </div>
            </UCard>

            <UButton
                v-if="mode !== 'show'"
                icon="i-heroicons-plus"
                variant="soft"
                block
                @click="itemInfo.accounts.push({account:null, amountNet: null, amountTax:0, amountGross: null, taxType: '19'})"
            >
              Weitere Position hinzufügen
            </UButton>
          </div>

          <div class="mt-8 border-t pt-4 dark:border-gray-700">
            <div class="flex justify-end">
              <div class="w-full md:w-1/2 space-y-2 text-sm">
                <div class="flex justify-between text-gray-500">
                  <span>Netto Gesamt</span>
                  <span>{{ totalCalculated.totalNet.toFixed(2) }} €</span>
                </div>
                <div class="flex justify-between text-gray-500" v-if="totalCalculated.totalAmount7Tax > 0">
                  <span>+ 7% USt</span>
                  <span>{{ totalCalculated.totalAmount7Tax.toFixed(2) }} €</span>
                </div>
                <div class="flex justify-between text-gray-500" v-if="totalCalculated.totalAmount19Tax > 0">
                  <span>+ 19% USt</span>
                  <span>{{ totalCalculated.totalAmount19Tax.toFixed(2) }} €</span>
                </div>
                <div class="flex justify-between font-bold text-xl text-gray-900 dark:text-white pt-2 border-t dark:border-gray-700">
                  <span>Rechnungsbetrag</span>
                  <span>{{ totalCalculated.totalGross.toFixed(2) }} €</span>
                </div>
              </div>
            </div>
          </div>

        </div>
      </div>
    </div>
  </UDashboardPanelContent>

  <PageLeaveGuard :when="mode !== 'show' && isModified"/>

  <div
      v-if="isPdfDetached && loadedFileId"
      ref="pdfEl"
      :style="pdfStyle"
      class="fixed z-[999] w-[600px] h-[750px] bg-white dark:bg-gray-900 shadow-2xl rounded-xl border border-gray-200 dark:border-gray-800 flex flex-col resize overflow-hidden"
  >
    <div class="flex items-center justify-between p-2 cursor-move border-b border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-800/50 select-none">
      <div class="flex items-center gap-2 text-gray-500 px-2">
        <UIcon name="i-heroicons-paper-clip" />
        <span class="text-xs font-bold uppercase tracking-wider">Dokumentenansicht</span>
      </div>
      <div class="flex items-center gap-1">
        <UTooltip text="Wieder andocken">
          <UButton
              color="gray"
              variant="ghost"
              icon="i-heroicons-arrows-pointing-in"
              size="xs"
              @click="isPdfDetached = false"
          />
        </UTooltip>
      </div>
    </div>
    <div class="flex-grow relative bg-gray-200 dark:bg-gray-900 overflow-hidden">
      <PDFViewer
          :file-id="loadedFileId"
          location="draggable_window"
          class="w-full h-full"
      />
    </div>
    <div class="absolute bottom-0 right-0 w-4 h-4 cursor-se-resize opacity-50">
      <UIcon name="i-heroicons-arrows-pointing-out" class="w-3 h-3 text-gray-400 transform rotate-90" />
    </div>
  </div>

</template>

<style scoped>
.resize {
  resize: both;
}
</style>
