<script setup lang="ts">
import MainContainer from '@/packages/ui/src/MainContainer.vue';
import AppLayout from '@/Layouts/AppLayout.vue';
import { FolderIcon } from '@heroicons/vue/16/solid';
import PageTitle from '@/Components/Common/PageTitle.vue';
import {
    ChartBarIcon,
    UserGroupIcon,
    CheckCircleIcon,
    TagIcon,
} from '@heroicons/vue/20/solid';
import DateRangePicker from '@/packages/ui/src/Input/DateRangePicker.vue';
import ReportingChart from '@/Components/Common/Reporting/ReportingChart.vue';
import BillableIcon from '@/packages/ui/src/Icons/BillableIcon.vue';
import { onMounted, ref } from 'vue';
import {
    formatHumanReadableDuration,
    getDayJsInstance,
    getLocalizedDayJs,
} from '@/packages/ui/src/utils/time';
import { type GroupingOption, useReportingStore } from '@/utils/useReporting';
import { storeToRefs } from 'pinia';
import TagDropdown from '@/packages/ui/src/Tag/TagDropdown.vue';
import type { AggregatedTimeEntriesQueryParams } from '@/packages/api/src';
import ReportingFilterBadge from '@/Components/Common/Reporting/ReportingFilterBadge.vue';
import ProjectMultiselectDropdown from '@/Components/Common/Project/ProjectMultiselectDropdown.vue';
import MemberMultiselectDropdown from '@/Components/Common/Member/MemberMultiselectDropdown.vue';
import TaskMultiselectDropdown from '@/Components/Common/Task/TaskMultiselectDropdown.vue';
import SelectDropdown from '@/packages/ui/src/Input/SelectDropdown.vue';
import ReportingGroupBySelect from '@/Components/Common/Reporting/ReportingGroupBySelect.vue';
import ReportingRow from '@/Components/Common/Reporting/ReportingRow.vue';
import { getOrganizationCurrencyString } from '@/utils/money';
import ReportingPieChart from '@/Components/Common/Reporting/ReportingPieChart.vue';
import { getCurrentMembershipId, getCurrentRole } from '@/utils/useUser';
import ClientMultiselectDropdown from '@/Components/Common/Client/ClientMultiselectDropdown.vue';
import { useTagsStore } from '@/utils/useTags';
import { formatCents } from '@/packages/ui/src/utils/money';

const startDate = ref<string>(
    getLocalizedDayJs(getDayJsInstance()().format()).subtract(14, 'd').format()
);
const endDate = ref<string>(
    getLocalizedDayJs(getDayJsInstance()().format()).format()
);
const selectedTags = ref<string[]>([]);
const selectedProjects = ref<string[]>([]);
const selectedMembers = ref<string[]>([]);
const selectedTasks = ref<string[]>([]);
const selectedClients = ref<string[]>([]);

const billable = ref<'true' | 'false' | null>(null);

const group = ref<GroupingOption>('project');
const subGroup = ref<GroupingOption>('task');

const reportingStore = useReportingStore();

const { aggregatedGraphTimeEntries, aggregatedTableTimeEntries } =
    storeToRefs(reportingStore);

const { groupByOptions } = reportingStore;

function getFilterAttributes() {
    let params: AggregatedTimeEntriesQueryParams = {
        start: getLocalizedDayJs(startDate.value).startOf('day').utc().format(),
        end: getLocalizedDayJs(endDate.value).endOf('day').utc().format(),
    };
    params = {
        ...params,
        member_ids:
            selectedMembers.value.length > 0
                ? selectedMembers.value
                : undefined,
        project_ids:
            selectedProjects.value.length > 0
                ? selectedProjects.value
                : undefined,
        task_ids:
            selectedTasks.value.length > 0 ? selectedTasks.value : undefined,
        client_ids:
            selectedClients.value.length > 0
                ? selectedClients.value
                : undefined,
        tag_ids: selectedTags.value.length > 0 ? selectedTags.value : undefined,
        billable: billable.value !== null ? billable.value : undefined,
    };
    return params;
}

function updateGraphReporting() {
    const diffInDays = getDayJsInstance()(endDate.value).diff(
        getDayJsInstance()(startDate.value),
        'd'
    );
    const params = getFilterAttributes();
    if (getCurrentRole() === 'employee') {
        params.member_id = getCurrentMembershipId();
    }
    params.fill_gaps_in_time_groups = 'true';
    params.group = getOptimalGroupingOption(diffInDays);
    useReportingStore().fetchGraphReporting(params);
}

function updateTableReporting() {
    const params = getFilterAttributes();
    if (group.value === subGroup.value) {
        const fallbackOption = groupByOptions.find(
            (el) => el.value !== group.value
        );
        if (fallbackOption?.value) {
            subGroup.value = fallbackOption.value;
        }
    }
    if (getCurrentRole() === 'employee') {
        params.member_id = getCurrentMembershipId();
    }
    params.group = group.value;
    params.sub_group = subGroup.value;
    useReportingStore().fetchTableReporting(params);
}

function updateReporting() {
    updateGraphReporting();
    updateTableReporting();
}

function getOptimalGroupingOption(diff: number): 'day' | 'week' | 'month' {
    if (diff <= 31) {
        return 'day';
    } else if (diff <= 200) {
        return 'week';
    } else {
        return 'month';
    }
}

onMounted(() => {
    updateGraphReporting();
    updateTableReporting();
});

const { tags } = storeToRefs(useTagsStore());
async function createTag(tag: string) {
    return await useTagsStore().createTag(tag);
}
</script>

<template>
    <AppLayout title="Reporting" data-testid="reporting_view">
        <MainContainer
            class="py-3 sm:py-5 border-b border-default-background-separator flex justify-between items-center">
            <div class="flex items-center space-x-3 sm:space-x-6">
                <PageTitle :icon="ChartBarIcon" title="Reporting"></PageTitle>
            </div>
        </MainContainer>
        <div class="p-3 w-full border-b border-default-background-separator">
            <MainContainer
                class="sm:flex space-y-4 sm:space-y-0 justify-between">
                <div
                    class="flex flex-wrap items-center space-y-2 sm:space-y-0 space-x-4">
                    <div class="text-sm font-medium">Filters</div>
                    <MemberMultiselectDropdown
                        @submit="updateReporting"
                        v-model="selectedMembers">
                        <template v-slot:trigger>
                            <ReportingFilterBadge
                                :count="selectedMembers.length"
                                :active="selectedMembers.length > 0"
                                title="Members"
                                :icon="UserGroupIcon"></ReportingFilterBadge>
                        </template>
                    </MemberMultiselectDropdown>
                    <ProjectMultiselectDropdown
                        @submit="updateReporting"
                        v-model="selectedProjects">
                        <template v-slot:trigger>
                            <ReportingFilterBadge
                                :count="selectedProjects.length"
                                :active="selectedProjects.length > 0"
                                title="Projects"
                                :icon="FolderIcon"></ReportingFilterBadge>
                        </template>
                    </ProjectMultiselectDropdown>
                    <TaskMultiselectDropdown
                        @submit="updateReporting"
                        v-model="selectedTasks">
                        <template v-slot:trigger>
                            <ReportingFilterBadge
                                :count="selectedTasks.length"
                                :active="selectedTasks.length > 0"
                                title="Tasks"
                                :icon="CheckCircleIcon"></ReportingFilterBadge>
                        </template>
                    </TaskMultiselectDropdown>
                    <ClientMultiselectDropdown
                        @submit="updateReporting"
                        v-model="selectedClients">
                        <template v-slot:trigger>
                            <ReportingFilterBadge
                                title="Clients"
                                :icon="FolderIcon"></ReportingFilterBadge>
                        </template>
                    </ClientMultiselectDropdown>
                    <TagDropdown
                        @submit="updateReporting"
                        :createTag
                        v-model="selectedTags"
                        :tags="tags">
                        <template v-slot:trigger>
                            <ReportingFilterBadge
                                :count="selectedTags.length"
                                :active="selectedTags.length > 0"
                                title="Tags"
                                :icon="TagIcon"></ReportingFilterBadge>
                        </template>
                    </TagDropdown>

                    <SelectDropdown
                        @changed="updateReporting"
                        v-model="billable"
                        :get-key-from-item="(item) => item.value"
                        :get-name-for-item="(item) => item.label"
                        :items="[
                            {
                                label: 'Both',
                                value: null,
                            },
                            {
                                label: 'Billable',
                                value: 'true',
                            },
                            {
                                label: 'Non Billable',
                                value: 'false',
                            },
                        ]">
                        <template v-slot:trigger>
                            <ReportingFilterBadge
                                :active="billable !== null"
                                :title="
                                    billable === 'false'
                                        ? 'Non Billable'
                                        : 'Billable'
                                "
                                :icon="BillableIcon"></ReportingFilterBadge>
                        </template>
                    </SelectDropdown>
                </div>
                <div>
                    <DateRangePicker
                        v-model:start="startDate"
                        v-model:end="endDate"
                        @submit="updateReporting"></DateRangePicker>
                </div>
            </MainContainer>
        </div>
        <MainContainer>
            <div class="pt-10 w-full px-3 relative">
                <ReportingChart
                    :groupedType="aggregatedGraphTimeEntries?.grouped_type"
                    :groupedData="
                        aggregatedGraphTimeEntries?.grouped_data
                    "></ReportingChart>
            </div>
        </MainContainer>
        <MainContainer>
            <div class="sm:grid grid-cols-4 pt-6 items-start">
                <div
                    class="col-span-3 bg-card-background rounded-lg border border-card-border pt-3">
                    <div
                        class="text-sm flex text-white items-center space-x-3 font-medium px-6 border-b border-card-background-separator pb-3">
                        <span>Group by</span>
                        <ReportingGroupBySelect
                            :group-by-options="groupByOptions"
                            @changed="updateTableReporting"
                            v-model="group"></ReportingGroupBySelect>
                        <span>and</span>
                        <ReportingGroupBySelect
                            :group-by-options="
                                groupByOptions.filter(
                                    (el) => el.value !== group
                                )
                            "
                            @changed="updateTableReporting"
                            v-model="subGroup"></ReportingGroupBySelect>
                    </div>
                    <div
                        class="grid items-center"
                        style="grid-template-columns: 1fr 100px 150px">
                        <div
                            class="contents [&>*]:border-card-background-separator [&>*]:border-b [&>*]:bg-tertiary [&>*]:pb-1.5 [&>*]:pt-1 text-muted text-sm">
                            <div class="pl-6">Name</div>
                            <div class="text-right">Duration</div>
                            <div class="text-right pr-6">Cost</div>
                        </div>
                        <template
                            v-if="
                                aggregatedTableTimeEntries?.grouped_data &&
                                aggregatedTableTimeEntries.grouped_data
                                    ?.length > 0
                            ">
                            <ReportingRow
                                v-for="entry in aggregatedTableTimeEntries.grouped_data"
                                :key="entry.key ?? 'none'"
                                :entry="entry"
                                :type="
                                    aggregatedTableTimeEntries.grouped_type
                                "></ReportingRow>
                            <div
                                class="contents [&>*]:transition text-text-tertiary [&>*]:h-[50px]">
                                <div class="flex items-center pl-6 font-medium">
                                    <span>Total</span>
                                </div>
                                <div
                                    class="justify-end flex items-center font-medium">
                                    {{
                                        formatHumanReadableDuration(
                                            aggregatedTableTimeEntries.seconds
                                        )
                                    }}
                                </div>
                                <div
                                    class="justify-end pr-6 flex items-center font-medium">
                                    {{
                                        formatCents(
                                            aggregatedTableTimeEntries.cost,
                                            getOrganizationCurrencyString()
                                        )
                                    }}
                                </div>
                            </div>
                        </template>
                        <div
                            class="chart flex flex-col items-center justify-center py-12 col-span-3"
                            v-else>
                            <p class="text-lg text-white font-semibold">
                                No time entries found
                            </p>
                            <p>Try to change the filters and time range</p>
                        </div>
                    </div>
                </div>
                <div>
                    <ReportingPieChart
                        :type="aggregatedTableTimeEntries?.grouped_type"
                        :data="
                            aggregatedTableTimeEntries?.grouped_data
                        "></ReportingPieChart>
                </div>
            </div>
        </MainContainer>
    </AppLayout>
</template>
