<script setup lang="ts">
import type { CalendarEvent, CalendarSignup } from '@shared/types/calendar'
import { CircleAlert, Clock4, EllipsisVertical, MapPin, User, X } from 'lucide-vue-next';
import { computed, ref, watch } from 'vue';
import ButtonGroup from '../ui/button-group/ButtonGroup.vue';
import Button from '../ui/button/Button.vue';
import { CalendarAttendance, getCalendarEvent, setCalendarEventAttendance, setCancelCalendarEvent } from '@/api/calendar';
import { useUserStore } from '@/stores/user';
import { useRoute } from 'vue-router';
import DropdownMenu from '../ui/dropdown-menu/DropdownMenu.vue';
import DropdownMenuTrigger from '../ui/dropdown-menu/DropdownMenuTrigger.vue';
import DropdownMenuContent from '../ui/dropdown-menu/DropdownMenuContent.vue';
import DropdownMenuItem from '../ui/dropdown-menu/DropdownMenuItem.vue';
import { Calendar } from 'lucide-vue-next';
import MemberCard from '../members/MemberCard.vue';
import Spinner from '../ui/spinner/Spinner.vue';

const route = useRoute();

const loaded = ref<boolean>(false);
const activeEvent = ref<CalendarEvent | null>(null);

watch(
    () => route.params.id,
    async (id) => {
        if (!id) return;
        activeEvent.value = await getCalendarEvent(Number(id));
        loaded.value = true;
    },
    { immediate: true }
);

const emit = defineEmits<{
    (e: 'close'): void
    (e: 'reload'): void
    (e: 'edit', event: CalendarEvent): void
}>()

const dateFmt = new Intl.DateTimeFormat(undefined, {
    weekday: 'long', month: 'short', day: 'numeric',
})

const timeFmt = new Intl.DateTimeFormat(undefined, {
    hour: 'numeric', minute: '2-digit'
})

const dateText = computed(() => {
    let start = dateFmt.format(new Date(activeEvent.value.start));
    let end = dateFmt.format(new Date(activeEvent.value.end));
    if (start === end)
        return start;
    else
        return `${start} - ${end}`;
})

const timeText = computed(() => {
    let startTime = timeFmt.format(new Date(activeEvent.value.start))
    let endTime = timeFmt.format(new Date(activeEvent.value.end))
    return [startTime, endTime]
})

const attending = computed<CalendarSignup[]>(() => { return activeEvent.value.eventSignups.filter((s) => s.status == CalendarAttendance.Attending) })
const maybe = computed<CalendarSignup[]>(() => { return activeEvent.value.eventSignups.filter((s) => s.status == CalendarAttendance.Maybe) })
const declined = computed<CalendarSignup[]>(() => { return activeEvent.value.eventSignups.filter((s) => s.status == CalendarAttendance.NotAttending) })
const viewedState = ref<CalendarAttendance>(CalendarAttendance.Attending);

let user = useUserStore();
const myAttendance = computed<CalendarSignup | null>(() => {
    if (!user.isLoggedIn) return null;
    return activeEvent.value.eventSignups.find(
        (s) => s.member_id === user.user.id
    ) || null;
});

async function setAttendance(state: CalendarAttendance) {
    await setCalendarEventAttendance(activeEvent.value.id, state);
    //refresh event data
    activeEvent.value = await getCalendarEvent(activeEvent.value.id);
}

const canEditEvent = computed(() => {
    if (!user.isLoggedIn) return false;
    if (user.user.id == activeEvent.value.creator_id)
        return true;
});

async function setCancel(isCancelled: boolean) {
    await setCancelCalendarEvent(activeEvent.value.id, isCancelled);
    emit("reload");
    activeEvent.value = await getCalendarEvent(activeEvent.value.id);
}

async function forceReload() {
    activeEvent.value = await getCalendarEvent(activeEvent.value.id);
}

const isPast = computed(() => {
    const end = new Date(activeEvent.value.end)
    // is current date later than end date
    return new Date() < end;
})

const attendanceTab = ref<"Alpha" | "Echo" | "Other">("Alpha");
const attendanceList = computed<CalendarSignup[]>(() => {
    let out: CalendarSignup[] = [];
    if (attendanceTab.value === 'Alpha') {
        out = activeEvent.value.eventSignups?.filter((s) => s.member_unit === 'Alpha Company');
    } else if (attendanceTab.value === 'Echo') {
        out = activeEvent.value.eventSignups?.filter((s) => s.member_unit === 'Echo Company')
    } else {
        out = activeEvent.value.eventSignups?.filter((s) => s.member_unit != 'Alpha Company' && s.member_unit != 'Echo Company')
    }

    const statusOrder: Record<CalendarAttendance, number> = {
        [CalendarAttendance.Attending]: 1,
        [CalendarAttendance.Maybe]: 2,
        [CalendarAttendance.NotAttending]: 3,
    };

    out.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]);

    return out;
})

const attendanceCountsByGroup = computed(() => {
    const signups = activeEvent.value.eventSignups ?? [];

    return {
        Alpha: signups.filter(s => s.member_unit === "Alpha Company").length,
        Echo: signups.filter(s => s.member_unit === "Echo Company").length,
        Other: signups.filter(s =>
            s.member_unit !== "Alpha Company" &&
            s.member_unit !== "Echo Company"
        ).length,
    };
});

const attendanceStatusSummary = computed(() => {
    const signups = activeEvent.value.eventSignups ?? [];

    return {
        attending: signups.filter(s => s.status === CalendarAttendance.Attending).length,
        maybe: signups.filter(s => s.status === CalendarAttendance.Maybe).length,
        notAttending: signups.filter(s => s.status === CalendarAttendance.NotAttending).length,
    };
});

const statusColor = (status: CalendarAttendance) => {
    switch (status) {
        case CalendarAttendance.Attending:
            return "text-success";
        case CalendarAttendance.Maybe:
            return "text-yellow-600";
        case CalendarAttendance.NotAttending:
            return "text-destructive";
        default:
            return "";
    }
};

const displayStatus = (status: CalendarAttendance) => {
    switch (status) {
        case CalendarAttendance.Attending:
            return "Attending";
        case CalendarAttendance.Maybe:
            return "Maybe";
        case CalendarAttendance.NotAttending:
            return "Declined";
        default:
            return status;
    }
};

defineExpose({ forceReload })
</script>

<template>
    <div v-if="loaded">
        <!-- Header -->
        <div class="flex items-center justify-between gap-3 border-b px-4 py-3 h-14">
            <h2 class="text-lg font-semibold break-all">
                {{ activeEvent?.name || 'Event' }}
            </h2>
            <div class="flex gap-4 items-center">
                <DropdownMenu v-if="canEditEvent">
                    <DropdownMenuTrigger>
                        <button
                            class="inline-flex flex-none size-8 items-center justify-center cursor-pointer rounded-md hover:bg-muted/40 transition">
                            <EllipsisVertical class="size-6" />
                        </button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent>
                        <DropdownMenuItem @click="emit('edit', activeEvent)">
                            Edit
                        </DropdownMenuItem>
                        <DropdownMenuItem v-if="activeEvent.cancelled" @click="setCancel(false)">
                            Un-Cancel
                        </DropdownMenuItem>
                        <DropdownMenuItem v-else @click="setCancel(true)">
                            Cancel
                        </DropdownMenuItem>
                    </DropdownMenuContent>
                </DropdownMenu>
                <button
                    class="inline-flex flex-none size-8 items-center justify-center rounded-md border hover:bg-muted/40 transition cursor-pointer"
                    aria-label="Close" @click="emit('close')">
                    <X class="size-4" />
                </button>
            </div>
        </div>
        <!-- Body -->
        <div class="flex-1 flex flex-col items-center min-h-0 overflow-y-auto px-4 py-4 space-y-6 w-full">
            <section v-if="activeEvent.cancelled == true" class="w-full">
                <div class="flex p-2 rounded-md w-full bg-destructive gap-3">
                    <CircleAlert></CircleAlert> This event has been cancelled
                </div>
            </section>
            <section v-if="isPast && user.isLoggedIn" class="w-full">
                <ButtonGroup class="flex w-full">
                    <Button variant="outline"
                        :class="myAttendance?.status === CalendarAttendance.Attending ? 'border-2 border-primary text-primary' : ''"
                        @click="setAttendance(CalendarAttendance.Attending)">Going</Button>
                    <Button variant="outline"
                        :class="myAttendance?.status === CalendarAttendance.Maybe ? 'border-2 !border-l-2 border-primary text-primary' : ''"
                        @click="setAttendance(CalendarAttendance.Maybe)">Maybe</Button>
                    <Button variant="outline"
                        :class="myAttendance?.status === CalendarAttendance.NotAttending ? 'border-2 !border-l-2 border-primary text-primary' : ''"
                        @click="setAttendance(CalendarAttendance.NotAttending)">Declined</Button>
                </ButtonGroup>
            </section>
            <!-- Meta -->
            <section class="space-y-3 w-full">
                <p class="text-lg font-semibold">Details</p>
                <div class="text-foreground/80 flex gap-3 items-center">
                    <Calendar :size="20"></Calendar> {{ dateText }}
                </div>
                <div class="text-foreground/80 flex gap-3 items-center">
                    <Clock4 :size="20"></Clock4> {{ timeText[0] }} - {{ timeText[1] }}
                </div>
                <div class="text-foreground/80 flex gap-3 items-center">
                    <MapPin :size="20"></MapPin> {{ activeEvent.location || "Unknown" }}
                </div>
                <div class="text-foreground/80 flex gap-3 items-center">
                    <User :size="20"></User>
                    <MemberCard :member-id="activeEvent.creator_id"></MemberCard>
                </div>
            </section>
            <!-- Description -->
            <section class="space-y-2 w-full">
                <p class="text-lg font-semibold">Description</p>
                <p class="border bg-muted/50 px-3 py-2 rounded-lg min-h-24 my-2 whitespace-pre-line">
                    {{ activeEvent.description }}
                </p>
            </section>
            <!-- attendance -->
            <section class="space-y-2 w-full">
                <div class="flex items-center gap-5">
                    <p class="text-lg font-semibold">Attendance</p>
                    <!-- <div class="text-muted-foreground flex gap-6">
                        <p>Going <span class="ml-1">{{ attendanceStatusSummary.attending }}</span></p>
                        <p>Maybe <span class="ml-1">{{ attendanceStatusSummary.maybe }}</span></p>
                        <p>Declined <span class="ml-1">{{ attendanceStatusSummary.notAttending }}</span></p>
                    </div> -->
                </div>
                <div class="flex flex-col border bg-muted/50 rounded-lg min-h-24 my-2">
                    <div class="flex w-full pt-2 border-b *:w-full *:text-center *:pb-1 *:cursor-pointer">
                        <label :class="attendanceTab === 'Alpha' ? 'border-b-3 border-foreground' : 'mb-[2px]'"
                            @click="attendanceTab = 'Alpha'">Alpha {{ attendanceCountsByGroup.Alpha }}</label>
                        <label :class="attendanceTab === 'Echo' ? 'border-b-3 border-foreground' : 'mb-[2px]'"
                            @click="attendanceTab = 'Echo'">Echo {{ attendanceCountsByGroup.Echo }}</label>
                        <label :class="attendanceTab === 'Other' ? 'border-b-3 border-foreground' : 'mb-[2px]'"
                            @click="attendanceTab = 'Other'">Other {{ attendanceCountsByGroup.Other }}</label>
                    </div>
                    <div class="pb-1 min-h-48">
                        <div class="grid grid-cols-2 font-semibold text-muted-foreground border-b py-1 px-3 mb-2">
                            <p>Name</p>
                            <p class="text-right">Status</p>
                        </div>

                        <div v-for="person in attendanceList" :key="person.member_id"
                            class="grid grid-cols-2 py-1 *:px-3 hover:bg-muted">
                            <div>
                                <MemberCard :member-id="person.member_id"></MemberCard>
                            </div>
                            <p :class="statusColor(person.status)" class="text-right">
                                {{ displayStatus(person.status) }}
                            </p>
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </div>
    <div v-else class="flex justify-center h-full items-center">
        <button
            class="absolute top-4 right-4 inline-flex flex-none size-8 items-center justify-center rounded-md border hover:bg-muted/40 transition cursor-pointer z-50"
            aria-label="Close" @click="emit('close')">
            <X class="size-4" />
        </button>

        <Spinner class="size-8"></Spinner>
    </div>
</template>