<script setup lang="ts">
import dayjs from "dayjs"
import {
  getCreatedDocumentTaxBreakdown,
  getIncomingInvoiceTaxBreakdown
} from "~/composables/useTaxEvaluation"
import {
  getIncomingInvoiceDepreciationRows,
  getIncomingInvoiceImmediateExpenseNet,
  getStatementAllocationImmediateExpenseAmount
} from "~/composables/useDepreciation"

const loading = ref(true)
const summary = ref({
  label: "",
  income: 0,
  expenses: 0,
  depreciations: 0,
  result: 0,
  taxBalance: 0,
  incomeCount: 0,
  expenseCount: 0,
  depreciationCount: 0
})

const formatCurrency = (value: number) => {
  return new Intl.NumberFormat("de-DE", {
    style: "currency",
    currency: "EUR"
  }).format(Number(value || 0))
}

const isRelevantOutputDocument = (doc: any) => {
  return doc?.state === "Gebucht" && ["invoices", "advanceInvoices", "cancellationInvoices"].includes(doc?.type)
}

const isRelevantInputInvoice = (invoice: any) => {
  return invoice?.state === "Gebucht" && !!invoice?.date
}

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

  try {
    const bounds = {
      start: dayjs().startOf("month"),
      end: dayjs().endOf("month")
    }

    const [docs, incoming, allocations] = await Promise.all([
      useEntities("createddocuments").select(),
      useEntities("incominginvoices").select(),
      useEntities("statementallocations").select("*, bankstatement(*)")
    ])

    const outputDocs = (docs || []).filter((doc: any) => {
      if (!isRelevantOutputDocument(doc)) {
        return false
      }

      const date = dayjs(doc.documentDate)
      return date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day")
    })

    const inputDocs = (incoming || []).filter((invoice: any) => {
      if (!isRelevantInputInvoice(invoice)) {
        return false
      }

      const date = dayjs(invoice.date)
      return date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day")
    })

    const directExpenses = (allocations || []).filter((allocation: any) => {
      if (allocation?.account === null || typeof allocation?.account === "undefined") {
        return false
      }

      const statementDate = allocation?.bankstatement?.date || allocation?.bankstatement?.valueDate || allocation?.date || allocation?.created_at
      const date = dayjs(statementDate)
      const amount = getStatementAllocationImmediateExpenseAmount(allocation)

      return amount > 0 && date.isValid() && !date.isBefore(bounds.start, "day") && !date.isAfter(bounds.end, "day")
    })

    const income = outputDocs.reduce((sum: number, doc: any) => {
      return sum + (doc.rows || []).reduce((rowSum: number, row: any) => {
        if (!row || ["pagebreak", "title", "text"].includes(row.mode)) {
          return rowSum
        }

        const quantity = Number(row.quantity || 0)
        const price = Number(row.price || 0)
        const discountPercent = Number(row.discountPercent || 0)

        return rowSum + (quantity * price * (1 - discountPercent / 100))
      }, 0)
    }, 0)

    const invoiceExpenses = inputDocs.reduce((sum: number, invoice: any) => {
      return sum + getIncomingInvoiceImmediateExpenseNet(invoice)
    }, 0)

    const directAccountExpenses = directExpenses.reduce((sum: number, allocation: any) => {
      return sum + Number(getStatementAllocationImmediateExpenseAmount(allocation) || 0)
    }, 0)

    const depreciationRows = [
      ...inputDocs.flatMap((invoice: any) => getIncomingInvoiceDepreciationRows(invoice, bounds.start, bounds.end))
    ]

    const depreciations = depreciationRows.reduce((sum: number, row: any) => sum + Number(row.amount || 0), 0)

    const outputTax = outputDocs.reduce((sum: number, doc: any) => {
      const breakdown = getCreatedDocumentTaxBreakdown(doc)
      return sum + breakdown.tax19 + breakdown.tax7
    }, 0)

    const inputTax = inputDocs.reduce((sum: number, invoice: any) => {
      const breakdown = getIncomingInvoiceTaxBreakdown(invoice)
      return sum + breakdown.tax19 + breakdown.tax7
    }, 0)

    const expenses = invoiceExpenses + directAccountExpenses + depreciations

    summary.value = {
      label: dayjs().format("MMMM YYYY"),
      income: Number(income.toFixed(2)),
      expenses: Number(expenses.toFixed(2)),
      depreciations: Number(depreciations.toFixed(2)),
      result: Number((income - expenses).toFixed(2)),
      taxBalance: Number((outputTax - inputTax).toFixed(2)),
      incomeCount: outputDocs.length,
      expenseCount: inputDocs.filter((invoice: any) => getIncomingInvoiceImmediateExpenseNet(invoice) > 0).length + directExpenses.filter((allocation: any) => getStatementAllocationImmediateExpenseAmount(allocation) > 0).length,
      depreciationCount: depreciationRows.length
    }
  } finally {
    loading.value = false
  }
}

onMounted(loadSummary)
</script>

<template>
  <div class="space-y-3">
    <div class="bwa-summary-top">
      <div>
        <p class="bwa-summary-period">{{ summary.label }}</p>
        <p class="bwa-summary-range">Aktueller Monat</p>
      </div>
      <UButton
        size="xs"
        variant="soft"
        color="gray"
        icon="i-heroicons-arrow-top-right-on-square"
        @click="navigateTo('/accounting/bwa')"
      >
        Details
      </UButton>
    </div>

    <div class="bwa-summary-row">
      <span class="bwa-summary-label">Einnahmen</span>
      <span class="bwa-summary-value text-primary-500">
        {{ loading ? "..." : formatCurrency(summary.income) }}
      </span>
    </div>

    <div class="bwa-summary-row">
      <span class="bwa-summary-label">Ausgaben</span>
      <span class="bwa-summary-value text-error">
        {{ loading ? "..." : formatCurrency(summary.expenses) }}
      </span>
    </div>

    <div class="bwa-summary-row">
      <span class="bwa-summary-label">Davon Abschreibungen</span>
      <span class="bwa-summary-value text-amber-600">
        {{ loading ? "..." : formatCurrency(summary.depreciations) }}
      </span>
    </div>

    <div class="bwa-summary-row">
      <span class="bwa-summary-label">Ergebnis</span>
      <span class="bwa-summary-value" :class="summary.result >= 0 ? 'text-primary-500' : 'text-error'">
        {{ loading ? "..." : formatCurrency(summary.result) }}
      </span>
    </div>

    <div class="bwa-summary-meta">
      {{ summary.incomeCount }} Einnahmenbelege | {{ summary.expenseCount }} Ausgabenbelege | {{ summary.depreciationCount }} Abschreibungen | USt-Saldo {{ formatCurrency(summary.taxBalance) }}
    </div>
  </div>
</template>

<style scoped>
.bwa-summary-top {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  align-items: flex-start;
}

.bwa-summary-period {
  margin: 0;
  font-weight: 700;
  color: rgb(17 24 39);
}

.bwa-summary-range,
.bwa-summary-meta {
  margin: 0;
  font-size: 0.875rem;
  color: rgb(107 114 128);
}

.bwa-summary-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: center;
}

.bwa-summary-label {
  color: rgb(55 65 81);
}

.bwa-summary-value {
  font-weight: 700;
  text-align: right;
}

:deep(.dark) .bwa-summary-period {
  color: rgb(243 244 246);
}

:deep(.dark) .bwa-summary-range,
:deep(.dark) .bwa-summary-meta,
:deep(.dark) .bwa-summary-label {
  color: rgb(156 163 175);
}
</style>
