<script setup lang="ts">

import { onMounted, ref, computed } from 'vue'
import Button from '@/components/ui/crm-button/Button.vue';
import Input from '@/components/ui/crm-input/Input.vue';
import Progress from '@/components/ui/progress/Progress.vue';
import { Table, TableRow, TableBody, TableCell, TableFooter, TableHead, TableHeader } from '@/components/ui/crm-table';
import { Avatar, AvatarFallback, AvatarImage, } from '@/components/ui/avatar'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'
import { useInitials } from '@/composables/useInitials';
import AppLayout from '@/layouts/AppLayout.vue';
import { Head, usePage } from '@inertiajs/vue3';
import { Ellipsis, Menu, Plus, ReceiptEuro, Trash2 } from 'lucide-vue-next';
import { isAfter, isBefore, toLocalDate, toShortISOString, toShortLocalDate } from '@/lib/utils';
import { Timesheet, TimesheetEntry, Invoice, LineItem } from '@/types'
import { newTimesheet, newTimesheetEntry, newInvoice, newLineItem } from '@/types/index.d'
import TimesheetService from '@/services/TimesheetService';
import { toast } from 'vue-sonner';
import { Checkbox } from '@/components/ui/crm-checkbox';
import { alertStore } from "@/stores/alertStore"
import Editable from '@/components/ui/crm-editable/Editable.vue';
import NumberInput from '@/components/ui/crm-number-input/NumberInput.vue';
import axios, { AxiosError } from "axios"

interface Props {
    timesheetData: Timesheet[];
}
const props = defineProps<Props>();
const timesheets = ref([] as Timesheet[])
const page = usePage();
const auth = computed(() => page.props.auth);
const alert = alertStore()
const { getInitials } = useInitials();
const selectedTimesheet = ref(-1);
const hourFormatter = new Intl.NumberFormat('de-DE', {
    style: 'decimal'
})

onMounted(() => {
    timesheets.value = props.timesheetData
    if (timesheets.value.length >= 0) selectTimesheet(timesheets.value[0])
})

const selectTimesheet = (timesheet: Timesheet) => {
    if (timesheets.value.length == 0) return

    selectedTimesheet.value = timesheets.value.findIndex(ts => ts.id === timesheet.id)

    if (!timesheet.entries) {
        TimesheetService.getTimesheetEntries(timesheet.id).then((entries) => {
            timesheets.value[selectedTimesheet.value].entries = entries ?? []
        }).catch((error) => {
            toast.error('Fehler beim Laden der Einträge', { duration: 5000, description: error.message })
        })
    }
}

const createTimesheet = () => {
    const timesheet = newTimesheet()
    timesheets.value.unshift(timesheet)

    TimesheetService.createTimesheet(timesheet).then((timesheet) => {
        let index = timesheets.value.findIndex(ts => ts.id == 0)
        timesheets.value[index] = timesheet
    }).catch((error) => {
        timesheets.value = timesheets.value.filter(t => t.id == 0)
        toast.error('Fehler beim Erstellen des Stundenzettels', { duration: 5000, description: error.message })
    })
}

const updateTimesheet = () => {
    if (selectedTimesheet.value < 0) return
    TimesheetService.updateTimesheet(timesheets.value[selectedTimesheet.value]).catch((error) => {
        toast.error('Fehler beim Speichern des Stundenzettels', { duration: 5000, description: error.message })
    })
}

const deleteTimesheet = (timesheet: Timesheet) => {
    alert.show(
        "Möchtest Du diesen Stundenzettel wirklich löschen?",
        "Alle Einträge gehen dann ebenfalls verloren.",
        {
            actionText: "Löschen",
            actionVariant: "destructive",
            onAction: async () => {
                TimesheetService.deleteTimesheet(timesheet.id).then(() => {
                    timesheets.value = timesheets.value.filter(t => t.id != timesheet.id)
                    selectedTimesheet.value = timesheets.value.length > 0 ? 0 : -1
                }).catch((error) => {
                    toast.error('Fehler beim Löschen des Stundenzettels', { duration: 5000, description: error.message })
                })
            }
        }
    )
}

const addEntry = () => {
    const entry = newTimesheetEntry();
    entry.user = auth.value.user
    entry.timesheetId = timesheets.value[selectedTimesheet.value].id
    entry.userId = page.props.auth.user.id
    TimesheetService.createEntry(entry).then((response) => {
        timesheets.value[selectedTimesheet.value].entries?.push(response)
    }).catch((error) => {
        toast.error('Fehler beim Erstellen des Eintrags', { duration: 5000, description: error.message })
    })
}

const deleteEntry = (entry: TimesheetEntry) => {
    TimesheetService.deleteEntry(entry.id).then((response) => {
        timesheets.value[selectedTimesheet.value].entries?.splice(timesheets.value[selectedTimesheet.value].entries?.indexOf(entry), 1)
    }).catch((error) => {
        toast.error('Fehler beim Löschen des Eintrags', { duration: 5000, description: error.message })
    })
}

const updateEntry = (entry: TimesheetEntry) => {
    TimesheetService.updateEntry(entry).then(() => {
    }).catch((error) => {
        toast.error('Fehler beim Speichern des Eintrags', { duration: 5000, description: error.message })
    })
}

const timesheetSummary = computed(() => {
    return (ts: Timesheet) => {
        const entries = ts.entries ?? []

        if (entries.length > 0) {
            const totalHours = entries.reduce((sum, e) => sum + (e.hours ?? 0), 0)
            const hoursBilled = entries.reduce((sum, e) => sum + ((e.billed ? (e.hours ?? 0) : 0)), 0)

            let earliestDate: string | null = null
            let latestDate: string | null = null
            for (const e of entries) {
                if (!e.date) continue
                if (!earliestDate || new Date(e.date) < new Date(earliestDate)) earliestDate = e.date
                if (!latestDate || new Date(e.date) > new Date(latestDate)) latestDate = e.date
            }

            return {
                totalHours,
                hoursBilled,
                earliestDate,
                latestDate,
            }
        }

        // Fallback to API-provided summary fields until entries are loaded
        return {
            totalHours: ts.totalHours ?? 0,
            hoursBilled: ts.hoursBilled ?? 0,
            earliestDate: ts.earliestDate ?? null,
            latestDate: ts.latestDate ?? null,
        }
    }
})

const createInvoice = async () => {
    let billedEntries: TimesheetEntry[] = []
    let invoice: Invoice = newInvoice()
    invoice.customer = null
    invoice.billingData = null
    timesheets.value[selectedTimesheet.value].entries?.forEach((entry => {
        if (entry.billed) return

        let lineItem: LineItem = newLineItem(false)
        lineItem.title = toLocalDate(entry.date)
        lineItem.description = entry.description || ''
        lineItem.quantity = entry.hours
        lineItem.price = 750 / 8 // TODO: get rate from settings

        if (!invoice.serviceStartDate || isBefore(entry.date, invoice.serviceStartDate)) {
            invoice.serviceStartDate = new Date(entry.date)
        }
        if (!invoice.serviceEndDate || isAfter(entry.date, invoice.serviceEndDate)) {
            invoice.serviceEndDate = new Date(entry.date)
        }

        invoice.items.push(lineItem)
        billedEntries.push(entry)
    }))

    try {
        const response = await axios.post('/api/invoices', invoice).then();
        billedEntries.forEach(entry => {
            entry.billed = true
            updateEntry(entry)
        })
        let newInvoice = response.data
        // got to invoices?
        console.log(newInvoice)
    } catch (e) {
        toast.error('Fehler beim erzeugen der Rechnung', { description: (e as AxiosError).message })
    }
}

</script>

<template>

    <Head title="Zeiterfassung" />

    <AppLayout title="Zeiterfassung">

        <div class="pl-90 print:pl-0">
            <div class="flex items-center justify-between mb-8">
                <Editable v-if="timesheets[selectedTimesheet]" v-model="timesheets[selectedTimesheet].title"
                    @change:model-value="value => { timesheets[selectedTimesheet].title = value; updateTimesheet(); }"
                    default-value="Zeiterfassung" placeholder="Zeiterfassung"
                    class="text-lg! text-primary font-semibold" />
                <h2 v-else class="text-lg text-primary font-semibold">Zeiterfassung</h2>

                <DropdownMenu v-if="selectedTimesheet >= 0">
                    <DropdownMenuTrigger as-child>
                        <Button variant="ghost" size="icon" class="print:hidden">
                            <Ellipsis class="visible-mac" />
                            <Menu class="visible-pc" />
                        </Button>
                    </DropdownMenuTrigger>

                    <DropdownMenuContent align="end">

                        <!-- Delete -->
                        <DropdownMenuItem class="flex justify-between" @click="createInvoice">
                            <div class="flex items-center gap-3">
                                <ReceiptEuro class="text-current" />
                                <span class="mr-2">Rechnung stellen</span>
                            </div>
                        </DropdownMenuItem>

                        <!-- Delete -->
                        <DropdownMenuItem
                            class="flex justify-between text-destructive! hover:bg-destructive! hover:text-destructive-foreground!"
                            @click="deleteTimesheet(timesheets[selectedTimesheet])">
                            <div class="flex items-center gap-3">
                                <Trash2 class="text-current" />
                                <span class="mr-2">Löschen</span>
                            </div>
                        </DropdownMenuItem>
                    </DropdownMenuContent>
                </DropdownMenu>
            </div>


            <Table class="relative">
                <TableHeader>
                    <TableRow>
                        <TableHead class="w-1/100">Abger.</TableHead>
                        <TableHead class="w-1/6">Datum</TableHead>
                        <TableHead class="w-1/6">Mitarbeiter</TableHead>
                        <TableHead class="w-1">Beschreibung</TableHead>
                        <TableHead class="w-1/100 text-right">Dauer</TableHead>
                        <TableHead class="w-1/100 print:hidden"></TableHead>
                    </TableRow>
                </TableHeader>

                <TableBody>
                    <TableRow v-if="selectedTimesheet >= 0 && timesheets[selectedTimesheet].entries"
                        v-for="entry in timesheets[selectedTimesheet].entries" class="bg-background">
                        <TableCell class="p-0">
                            <Checkbox v-model="entry.billed" class="text-success mx-auto"
                                @update:model-value="updateEntry(entry)" />
                        </TableCell>
                        <TableCell>
                            <Input type="date" :model-value="toShortISOString(entry.date)"
                                @update:model-value="value => { entry.date = value as string; updateEntry(entry); }" />
                        </TableCell>
                        <TableCell>
                            <div class="flex items-center gap-2">
                                <Avatar class="size-6">
                                    <AvatarImage :src="'storage/uploads/users/' + entry.user?.avatar"
                                        :alt="entry.user?.name" />
                                    <AvatarFallback class="rounded-full bg-primary text-black dark:text-white">
                                        {{ getInitials(entry.user?.name) }}
                                    </AvatarFallback>
                                </Avatar>
                                {{ entry.user?.name }}
                            </div>
                        </TableCell>
                        <TableCell>
                            <Editable v-model="entry.description as string" placeholder="Beschreibung"
                                @change:model-value="value => { entry.description = value; updateEntry(entry); }" />
                        </TableCell>
                        <TableCell class="text-right">
                            <NumberInput v-model="entry.hours" suffix=" h" :minimumFractionDigits="0"
                                @update:model-value="updateEntry(entry)" />
                        </TableCell>
                        <TableCell class="print:hidden">
                            <Button size="icon" variant="ghost" @click="deleteEntry(entry)">
                                <Trash2 class="size-4 text-muted-foreground" />
                            </Button>
                        </TableCell>
                    </TableRow>

                </TableBody>

                <TableFooter>
                    <TableRow class="font-bold">
                        <TableCell colspan="4" class="text-center">
                            <Button variant="ghost" @click="addEntry" class="print:hidden">
                                <Plus class="text-muted-foreground" /> Zeile einfügen
                            </Button>
                        </TableCell>
                        <TableCell class="text-right" v-if="selectedTimesheet >= 0">{{
                            hourFormatter.format(timesheetSummary(timesheets[selectedTimesheet]).totalHours ?? 0) }} h
                        </TableCell>
                        <TableCell class="print:hidden"></TableCell>
                    </TableRow>
                </TableFooter>
            </Table>

        </div>

        <aside id="timesheets"
            class="fixed top-0 w-90 -ml-8 py-8 px-4 h-full overflow-y-auto border-r border-sidebar-border/30 print:hidden bg-sidebar/50">
            <div class="flex w-full max-w-sm items-center space-x-2">
                <Input placeholder="Suchen..." class="w-full sticky top-0 z-10 bg-background" />
                <Button @click="createTimesheet">
                    <Plus /> Neu
                </Button>
            </div>

            <ul class="flex flex-col mt-6">
                <li v-for="timesheet in timesheets" @click="selectTimesheet(timesheet)"
                    :data-active="selectedTimesheet >= 0 && timesheets[selectedTimesheet].id === timesheet.id"
                    class="data-[active=true]:bg-background data-[active=true]:rounded data-[active=true]:shadow border-sidebar-border/75 data-[active=true]:border-transparent data-[active=true]:z-10 border-b p-4 hover:bg-accent flex gap-2 flex-col -my-px">
                    <h3 class="font-semibold">{{ timesheet.title }}</h3>
                    <div class="text-sm flex items-center justify-between gap-3">
                        <span v-if="timesheetSummary(timesheet).earliestDate" class="grow">
                            <span class="text-muted-foreground">{{
                                toShortLocalDate(timesheetSummary(timesheet).earliestDate!) }}</span>
                            <span class="text-muted-foreground"
                                v-if="timesheetSummary(timesheet).latestDate && timesheetSummary(timesheet).earliestDate && timesheetSummary(timesheet).latestDate! > timesheetSummary(timesheet).earliestDate!">
                                –
                                {{ toShortLocalDate(timesheetSummary(timesheet).latestDate!) }}</span>
                        </span>
                        <span v-if="timesheetSummary(timesheet).totalHours">{{ timesheetSummary(timesheet).totalHours }}
                            Std.</span>
                        <Progress
                            v-if="timesheetSummary(timesheet).hoursBilled && timesheetSummary(timesheet).hoursBilled > 0 && timesheetSummary(timesheet).totalHours"
                            :model-value="(timesheetSummary(timesheet).hoursBilled / timesheetSummary(timesheet).totalHours) * 100"
                            class="h-1 w-10 text-muted-foreground" />
                    </div>
                </li>
            </ul>
        </aside>

    </AppLayout>
</template>
