<script setup lang="ts">
import { DateTime, type DurationInput } from 'luxon';
import { useNuxtApp } from 'nuxt/app';

import useSimpleHead from '~/composables/useSimpleHead.ts';
import { min, max, MONTHS, PERIODS, type TimesheetData } from '~/src/timesheets.ts';

function* range(start: number, end: number) {
    for (let i = start; i <= end; i++) {
        yield i;
    }
}

const { $translator: translator } = useNuxtApp();
useSimpleHead({
    title: `${translator.translate('admin.header')} • Timesheets overview`,
}, translator);

const { data: timesheets } = await useFetch<Record<string, TimesheetData>>(
    '/api/admin/timesheets',
    { default: () => ({}) },
);

const firstPeriod = '2020-2022';
const startYear = ref(PERIODS[firstPeriod][0]);
const startMonth = ref(PERIODS[firstPeriod][1]);
const endYear = ref(PERIODS[firstPeriod][2]);
const endMonth = ref(PERIODS[firstPeriod][3]);

const years = [...range(min.year, max.year)];

const hoursSummary = computed((): Record<string, number> => {
    const hoursSummary: Record<string, number> = {};
    if (!timesheets.value) {
        return hoursSummary;
    }

    for (const [username, timesheetData] of Object.entries(timesheets.value)) {
        const timesheet = timesheetData.timesheet;
        let hours = 0;
        for (const year of Object.keys(timesheet)) {
            for (const month of Object.keys(timesheet[parseInt(year)])) {
                if (!isInRange(parseInt(year), parseInt(month))) {
                    continue;
                }
                for (const h of Object.values(timesheet[parseInt(year)][month])) {
                    hours += h;
                }
            }
        }
        if (hours > 0) {
            hoursSummary[username] = hours;
        }
    }
    return hoursSummary;
});

const hoursSum = computed(() => {
    let sum = 0;
    for (const username in hoursSummary.value) {
        if (!Object.hasOwn(hoursSummary.value, username) || timesheets.value[username].transfer === 'skip') {
            continue;
        }
        sum += hoursSummary.value[username];
    }
    return sum;
});
const hoursSumTotal = computed(() => {
    let sum = 0;
    for (const username in hoursSummary.value) {
        sum += hoursSummary.value[username];
    }
    return sum;
});

const setPeriod = (period: keyof typeof PERIODS) => {
    startYear.value = PERIODS[period][0];
    startMonth.value = PERIODS[period][1];
    endYear.value = PERIODS[period][2];
    endMonth.value = PERIODS[period][3];
};

const addPeriod = (offset: DurationInput) => {
    const startTime = DateTime.fromObject({ year: startYear.value, month: startMonth.value }).plus(offset);
    const endTime = DateTime.fromObject({ year: endYear.value, month: endMonth.value }).plus(offset);

    startYear.value = startTime.year;
    startMonth.value = startTime.month;
    endYear.value = endTime.year;
    endMonth.value = endTime.month;
};
const isInRange = (year: number, month: number): boolean => {
    const x = DateTime.local(year, month, 15);
    const begin = DateTime.local(startYear.value, startMonth.value, 1).startOf('month');
    const end = DateTime.local(endYear.value, endMonth.value, 1).endOf('month');
    // @ts-expect-error: DateTime.ts: number not in typings but in code (probably version mismatch)
    return x.ts >= begin.ts && x.ts <= end.ts;
};
</script>

<template>
    <Page wide>
        <NotFound v-if="!$isGranted('panel')" />
        <div v-else>
            <p class="d-flex justify-content-between">
                <nuxt-link to="/admin">
                    <Icon v="user-cog" />
                    <T>admin.header</T>
                </nuxt-link>
                <span>
                    <nuxt-link to="/admin/timesheets">
                        <Icon v="file-spreadsheet" />
                        Fill out your timesheet
                    </nuxt-link>
                    <nuxt-link to="/admin/timesheets/expenses">
                        <Icon v="file-spreadsheet" />
                        Declare expenses
                    </nuxt-link>
                </span>
            </p>
            <h2>
                <Icon v="file-spreadsheet" />
                Timesheets overview
            </h2>
            <div class="row my-4">
                <ul class="list-inline">
                    <li class="list-inline-item">
                        Period:
                    </li>
                    <li v-for="(_, period) in PERIODS" class="list-inline-item">
                        <a href="#" class="btn btn-outline-primary" @click.prevent="setPeriod(period)">{{ period }}</a>
                    </li>
                    <li class="list-inline-item">
                        <a href="#" class="btn btn-outline-primary" @click.prevent="addPeriod({ months: -1 })">&lt;</a>
                    </li>
                    <li class="list-inline-item">
                        <a href="#" class="btn btn-outline-primary" @click.prevent="addPeriod({ months: 1 })">&gt;</a>
                    </li>
                </ul>
                <div class="input-group mb-3">
                    <span class="input-group-text">Start:</span>
                    <select v-model.number="startYear" class="form-control">
                        <option v-for="year in years" :value="year">
                            {{ year }}
                        </option>
                    </select>
                    <select v-model.number="startMonth" class="form-control">
                        <option v-for="(month, m) in MONTHS" :value="m">
                            {{ month }}
                        </option>
                    </select>
                    <span class="input-group-text">End:</span>
                    <select v-model.number="endYear" class="form-control">
                        <option v-for="year in years" :value="year">
                            {{ year }}
                        </option>
                    </select>
                    <select v-model.number="endMonth" class="form-control">
                        <option v-for="(month, m) in MONTHS" :value="m">
                            {{ month }}
                        </option>
                    </select>
                </div>
            </div>
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th>Username</th>
                        <th>Hours</th>
                        <th>Percentage</th>
                        <th>Transfer info</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(hours, username) in hoursSummary">
                        <th>
                            <LocaleLink locale="_" :link="`/@${username}`">
                                @{{ username }}
                            </LocaleLink>
                        </th>
                        <td>{{ hours }}</td>
                        <td>{{ hoursSum && timesheets[username].transfer !== 'skip' ? `${(100 * hours / hoursSum).toFixed(1)}%` : '—' }}</td>
                        <td>
                            <p><strong>{{ timesheets[username].transfer }}</strong></p>
                            <ul v-if="timesheets[username]">
                                <template v-for="(value, key) in timesheets[username].details">
                                    <li v-if="value" :key="key">
                                        <strong>{{ key }}:</strong> {{ value }}
                                    </li>
                                </template>
                            </ul>
                        </td>
                    </tr>
                    <tr>
                        <th>Sum</th>
                        <td>{{ hoursSumTotal }}</td>
                        <td></td>
                        <td></td>
                    </tr>
                </tbody>
            </table>
        </div>
    </Page>
</template>
