<script setup lang="ts">

import AppLayout from '@/layouts/AppLayout.vue'
import { invoices } from '@/routes'
import { type Invoice, type Customer, type Address } from '@/types'
import { newInvoice } from '@/types/index.d'
import { Head } from '@inertiajs/vue3'
import { computed, ref, onMounted, watch } from 'vue'
import axios, { Axios, AxiosError, AxiosResponse } from 'axios'
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from '@/components/ui/select'
import { Button } from '@/components/ui/button'
import DocumentTable from '@/components/documents/DocumentTable.vue'
import { ChevronLeft, ChevronRight, Plus, Search, Delete } from "lucide-vue-next"
import InvoiceDialog from '@/components/documents/InvoiceDialog.vue'
import Fuse from 'fuse.js';
import { Input } from '@/components/ui/input'
import { toast } from 'vue-sonner'
import { testToast } from '@/lib/utils'
import SelectSeparator from '@/components/ui/select/SelectSeparator.vue'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { Kbd, KbdGroup } from '@/components/ui/kbd'
import { statusBadgeLabels } from '@/components/ui/status-badge'

const invoicesData = ref([] as Invoice[])
const activeInvoice = ref<Invoice | null>(null)
const customersData = ref([] as Customer[])
const selectedYearIndex = ref(0)
const detailDialogOpen = ref(false)
const searchQuery = ref('')
const searchField = ref()

onMounted(async () => {
    const invoiceResponse = await axios.get('/api/invoices')
    invoicesData.value = invoiceResponse.data as Invoice[]

    const customerResponse = await axios.get('/api/customers')
    customersData.value = customerResponse.data as Customer[]

    searchField.value = document.getElementById('search')

    let queryString = window.location.search
    let params = new URLSearchParams(queryString)
    if (params.get('action') == 'new') showDetail(newInvoice())
})

watch(invoicesData, () => {
    // Die watch-Funktion wird automatisch ausgelöst, wenn sich invoicesData ändert
    // Das filteredInvoices-Array wird automatisch aktualisiert
    // Fügen Sie eine kleine Verzögerung hinzu, um sicherzustellen, dass die Daten aktualisiert werden
    setTimeout(() => {
        // Die watch-Funktion wird automatisch ausgelöst, wenn sich invoicesData ändert
        // Das filteredInvoices-Array wird automatisch aktualisiert
    }, 0);
}, { deep: true });

const years = computed((): number[] => {
    const allYears = invoicesData.value.map(invoice => {
        const date = new Date(invoice.invoiceDate);
        return date.getFullYear();
    })
    const uniqueYears = [...new Set(allYears.filter(year => !isNaN(year)))]
    uniqueYears.sort((a, b) => b - a)
    return uniqueYears
})

const fuse = computed(() => {
    const options = {
        keys: [
            'customer.companyName',
            {
                name: 'paymentStatus',
                getFn: (invoice: Invoice) => statusBadgeLabels[invoice.paymentStatus] || invoice.paymentStatus
            },
            'title',
            'nr'
        ],
        threshold: 0.3,
    }

    return new Fuse(invoicesData.value, options);
})

const filteredInvoices = computed(() => {
    // Filter by query
    if (!searchQuery.value) {
        return years.value[selectedYearIndex.value] ?
            invoicesData.value.filter(invoice => {
                const invoiceDate = new Date(invoice.invoiceDate);
                return invoiceDate.getFullYear() === years.value[selectedYearIndex.value];
            }) :
            invoicesData.value;
    }

    return fuse.value.search(searchQuery.value)
        .map(result => result.item)
        .filter(invoice => {
            // Stellen Sie sicher, dass die gefilterten Rechnungen auch zum ausgewählten Jahr gehören
            const invoiceDate = new Date(invoice.invoiceDate);
            return !years.value[selectedYearIndex.value] || invoiceDate.getFullYear() === years.value[selectedYearIndex.value];
        });
});

const showDetail = (invoice: Invoice) => {
    // make a deep copy, so the changes in the dialog won’t affect the data until saved
    activeInvoice.value = JSON.parse(JSON.stringify(invoice))
    detailDialogOpen.value = true
}

const saveInvoice = async (updatedInvoice: Invoice) => {
    try {
        // Prepare the invoice data for API request
        const invoiceToSave = {
            nr: updatedInvoice.nr,
            invoiceDate: updatedInvoice.invoiceDate,
            dueDate: updatedInvoice.dueDate,
            serviceStartDate: updatedInvoice.serviceStartDate,
            serviceEndDate: updatedInvoice.serviceEndDate,
            isRecurring: updatedInvoice.isRecurring,
            isPartialService: updatedInvoice.isPartialService,
            paymentStatus: updatedInvoice.paymentStatus,
            totalAmount: updatedInvoice.totalAmount,
            title: updatedInvoice.title,
            text: updatedInvoice.text,
            customerId: updatedInvoice.customer ? updatedInvoice.customer.id : null,
            billingData: {
                companyName: updatedInvoice.billingData?.companyName,
                vatId: updatedInvoice.billingData?.vatId,
                billingAddress: updatedInvoice.billingData?.billingAddress,
                contactSalutation: updatedInvoice.billingData?.contactSalutation,
                contactFirstName: updatedInvoice.billingData?.contactFirstName,
                contactLastName: updatedInvoice.billingData?.contactLastName,
                paymentTerms: updatedInvoice.billingData?.paymentTerms
            },

            // Items will be handled separately in the controller
            items: updatedInvoice.items.map(item => ({
                id: item.id, // Include ID for existing items
                position: item.position,
                type: item.type,
                title: item.title,
                description: item.description,
                quantity: item.quantity,
                unit: item.unit,
                price: item.price
            }))
        };
        // console.log('Saving invoice:', invoiceToSave);

        if (updatedInvoice.id === 0) {
            // Create new invoice
            const response = await axios.post('/api/invoices', invoiceToSave);
            invoicesData.value.push(response.data);

            // Update selectedYearIndex to ensure the new invoice is displayed
            const newInvoiceYear = new Date(response.data.invoiceDate).getFullYear();
            const currentYearIndex = years.value.findIndex(year => year === newInvoiceYear);
            if (currentYearIndex !== -1) {
                selectedYearIndex.value = currentYearIndex;
            }
        } else {
            // Update existing invoice
            const response = await axios.put(`/api/invoices/${updatedInvoice.id}`, invoiceToSave);
            const index = invoicesData.value.findIndex(inv => inv.id === updatedInvoice.id);
            if (index !== -1) {
                invoicesData.value[index] = response.data;
            }
        }
    } catch (error) {
        toast.error("Rechnung konnte nicht gespeichert werden", {
            description: (error as Error).message,
        });
    }
}

const deleteInvoice = async (id: number) => {

    try {
        const response = axios.delete('/api/invoices/' + id)
        const index = invoicesData.value.findIndex(invoice => invoice.id === id);
        if (index !== -1) {
            invoicesData.value.splice(index, 1)
        }
    } catch (error) {
        toast.error("Rechnung konnte nicht gelöscht werden", {
            description: (error as Error).message,
        });
    }
}

</script>

<template>

    <Head title="Rechnungen" />

    <!-- Function Header -->
    <AppLayout>

        <div
            class="flex h-full flex-1 flex-col gap-4 overflow-x-auto p-4 lg:p-8 lg:pl-4 print:bg-transparent print:p-0 print:m-0">

            <div id="function-header" class="flex row justify-between items-center mb-4 gap-4">

                <!-- Year select -->
                <div class="flex row items-center">
                    <Button :variant="'ghost'" :disabled="selectedYearIndex >= (years.length - 1)"
                        @click="selectedYearIndex++">
                        <ChevronLeft />
                    </Button>
                    <Select :size="'sm'" v-model="selectedYearIndex" v-if="years.length > 1">
                        <SelectTrigger class="   hover:bg-accent">
                            <SelectValue placeholder="Jahr" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectGroup>
                                <SelectItem :value="null">
                                    <SelectLabel>Alle</SelectLabel>
                                </SelectItem>
                                <SelectSeparator />
                                <SelectItem v-for="(year, index) in years" :value="index">
                                    <SelectLabel>{{ year }}</SelectLabel>
                                </SelectItem>
                            </SelectGroup>
                        </SelectContent>
                    </Select>
                    <Button :variant="'ghost'" @click="selectedYearIndex--" :disabled="selectedYearIndex <= 0">
                        <ChevronRight />
                    </Button>
                </div>

                <!-- Search field -->
                <div class="relative w-full max-w-sm items-center">
                    <Input ref="search-field" id="search" type="text" placeholder="Filtern" class="px-8 bg-background"
                        v-model="searchQuery" />
                    <span class="absolute start-0 inset-y-0 flex items-center justify-center px-2">
                        <Search class="size-4 text-muted-foreground" :stroke-width="1.5" />
                    </span>
                    <span class="absolute end-0 inset-y-0 flex items-center justify-center px-0 mr-1">
                        <Button :size="'sm'" :variant="'ghost'" @click="searchQuery = ''; searchField.focus()">
                            <Delete class="size-4 text-muted-foreground" :stroke-width="1.5" />
                        </Button>
                    </span>
                </div>

                <!-- <Button size="sm" @click="testToast" class="mr-2">
                Toast
            </Button> -->

                <!-- New button -->
                <TooltipProvider>
                    <Tooltip>
                        <TooltipTrigger>
                            <Button size="sm" variant="action" @click="showDetail(newInvoice())">
                                <Plus />
                                Neu
                            </Button>
                        </TooltipTrigger>
                        <TooltipContent>
                            <span>Neue Rechnung anlegen</span>
                            <KbdGroup class="ml-2">
                                <Kbd class="visible-mac">⌘</Kbd>
                                <Kbd class="visible-pc">Ctrl</Kbd>
                                <Kbd>N</Kbd>
                            </KbdGroup>
                        </TooltipContent>
                    </Tooltip>
                </TooltipProvider>

            </div>


            <!-- Invoice Table -->
            <DocumentTable :invoices="filteredInvoices" :onItemClicked="showDetail" />

            <!-- Invoice detail dialog -->
            <InvoiceDialog :invoiceData="activeInvoice" :customers="customersData" v-model="detailDialogOpen"
                @save="saveInvoice" @delete="deleteInvoice" />

        </div>
    </AppLayout>
</template>

<style>
@media print {
    #function-header {
        display: none;
    }
}
</style>