<script setup lang="ts">
import { ref, onBeforeMount, computed } from "vue";
import type { Task } from "@/types";
import { getTasks, createTask, deleteTask } from "@/api/tasks";
import {
    CirclePlusIcon,
    CircleCheckBigIcon,
    CheckCheckIcon,
    SearchIcon,
    Share2Icon,
} from "@lucide/vue";
import TaskItem from "@/components/TaskItem.vue";
import ListOptions from "@/components/ListOptions.vue";
import { taskCompleted, sortTasks, newTemporaryTask } from "@/lib/tasks";
import { SortType } from "@/enums";
import { booleanCookieRef, enumCookieRef } from "@/lib/cookies";
import { useAlertStore } from "@/stores/alerts";
import { useI18n } from "vue-i18n";
import { onBeforeRouteLeave, onBeforeRouteUpdate, useRoute } from "vue-router";
import { shareLink } from "@/lib/share";
import { useListStore } from "@/stores/lists";

const route = useRoute();

const list = ref<string | null>(null);
const loading = ref<boolean>(true);
const taskInput = ref<string>("");
const tasks = ref<Task[]>([]);
const refreshTimeout = ref<number>(0);

const sortType = enumCookieRef<SortType>("sSortType", SortType.CREATED_AT);
const sortReverse = booleanCookieRef("sortReverse", false);
const showLastChecked = booleanCookieRef("showLastChecked", false);
const showNextReset = booleanCookieRef("showNextReset", false);
const separateCompleted = booleanCookieRef("separateCompleted", true);
const showMissed = booleanCookieRef("showMissed", true);

const completedCount = computed<number>(
    () => tasks.value.filter(taskCompleted).length,
);
const taskCount = computed<number>(() => tasks.value.length);
const hasCompleted = computed<boolean>(() => completedCount.value > 0);
const empty = computed<boolean>(() => taskCount.value === 0);
const allCompleted = computed<boolean>(
    () => taskCount.value === completedCount.value,
);

const i18n = useI18n();

const { alertSuccess, alertError, alertWarning } = useAlertStore();
const { addList } = useListStore();

function fetchTasks(requestedList: string) {
    const initialList = list.value;
    if (list.value === requestedList) {
        getTasks(list.value)
            .then((data: Task[]) => {
                if (list.value === initialList) {
                    tasks.value = data;
                    reSortTasks(true);
                    loading.value = false;
                    refreshTimeout.value = setTimeout(() => {
                        fetchTasks(list.value ?? "");
                    }, 10000);
                }
            })
            .catch(() => {
                if (tasks.value.length !== 0) {
                    alertWarning(i18n.t("alerts.task_refresh_error"));
                } else {
                    alertError(i18n.t("alerts.task_fetch_error"));
                }
            });
    }
}

function reSortTasks(update = false) {
    tasks.value = sortTasks(tasks.value, sortType.value, sortReverse.value);
    if (update) {
        updateTitle();
        if (tasks.value.length && list.value) {
            addList(list.value);
        }
    }
}

function onNewTask() {
    if (taskInput.value.trim() && list.value && !loading.value) {
        const data = {
            name: taskInput.value.trim(),
            reset_cron: null,
        };
        const task = newTemporaryTask(data);
        tasks.value.push(task);
        reSortTasks(true);
        createTask(list.value, data)
            .then((data: Task) => {
                task.id = data.id;
                alertSuccess(i18n.t("alerts.task_created"));
            })
            .catch(() => {
                alertError(i18n.t("alerts.task_create_error"));
            })
            .finally(() => {
                taskInput.value = "";
            });
    }
}

function onUpdateTask() {
    reSortTasks(true);
}

function onCloneTask(task: Task) {
    if (list.value) {
        const data = {
            name: task.name,
            reset_cron: task.reset_cron,
        };
        const newTask = newTemporaryTask(data);
        tasks.value.push(newTask);
        reSortTasks(true);
        createTask(list.value, data)
            .then((data: Task) => {
                task.id = data.id;
                reSortTasks(true);
                alertSuccess(i18n.t("alerts.task_cloned"));
            })
            .catch(() => {
                alertError(i18n.t("alerts.task_create_error"));
            });
    }
}

function onDeleteTask(task: Task) {
    tasks.value.splice(tasks.value.indexOf(task), 1);
    reSortTasks(true);
    deleteTask(task.id)
        .then(() => {
            alertSuccess(i18n.t("alerts.task_deleted"));
        })
        .catch(() => {
            alertError(i18n.t("alerts.task_delete_error"));
        });
}

function onShare() {
    if (!empty.value) {
        shareLink(
            `Tout Doux - ${list.value ?? ""}`,
            i18n.t("share_text"),
            `${document.location.href.split("?")[0] ?? ""}?lang=${i18n.locale.value}`,
        )
            .then((viaShare) => {
                if (!viaShare) {
                    alertSuccess(i18n.t("alerts.share_clipboard"));
                }
            })
            .catch(() => {
                alertError(i18n.t("alerts.share_error"));
            });
    }
}

function updateTitle() {
    if (list.value !== null) {
        document.title = `Tout Doux - ${list.value} (${completedCount.value.toFixed(0)}/${taskCount.value.toFixed(0)})`;
    }
}

onBeforeMount(() => {
    list.value = (route.params.list as string).slice(0, 128);
    fetchTasks(list.value);
});

onBeforeRouteUpdate((to) => {
    list.value = (to.params.list as string).slice(0, 128);
    fetchTasks(list.value);
});

onBeforeRouteLeave(() => {
    clearTimeout(refreshTimeout.value);
});
</script>

<template>
    <div
        class="list-row italic text-sm font-extralight self-center"
        :class="!empty ? 'cursor-pointer hover:underline' : ''"
        :title="!empty ? $t('share_button') : ''"
        @click="onShare"
    >
        {{ list }}
        <span v-if="!empty"
            >({{ completedCount }} / {{ taskCount }})&nbsp;<share-2-icon
                class="inline"
                :size="16"
                :stroke-width="1"
        /></span>
    </div>
    <div
        v-if="!loading && empty"
        class="mt-4 mb-4 italic text-xl font-extralight"
    >
        <search-icon class="inline" />
        <span v-html="$t('empty_hint')"></span>
    </div>
    <div
        v-else-if="!loading && allCompleted && separateCompleted"
        class="mt-4 mb-4 italic text-xl font-extralight"
    >
        <check-check-icon class="inline" />
        <span v-html="$t('all_completed_hint')"></span>
    </div>
    <ul v-else class="list">
        <template v-for="(task, i) in tasks" :key="task.id">
            <li v-if="tasks[i] && (!separateCompleted || !taskCompleted(task))">
                <task-item
                    v-model="tasks[i]"
                    :show-last-checked="showLastChecked"
                    :show-next-reset="showNextReset"
                    :show-missed="showMissed"
                    @updated="onUpdateTask"
                    @clone="onCloneTask"
                    @delete="onDeleteTask"
                />
            </li>
        </template>
    </ul>
    <div
        v-if="separateCompleted && hasCompleted"
        class="collapse collapse-arrow mb-4"
    >
        <input id="completed-dropdown p-0" type="checkbox" />
        <div class="collapse-title p-0 content-center">
            <circle-check-big-icon class="inline" :size="24" />
            {{ $t("completed") }} ({{ completedCount }})
        </div>
        <div class="collapse-content p-0 -mb-4">
            <ul class="list">
                <template
                    v-for="(task, i) in tasks"
                    :key="`${task.id}-completed`"
                >
                    <li v-if="tasks[i] && taskCompleted(task)">
                        <task-item
                            v-model="tasks[i]"
                            :show-last-checked="showLastChecked"
                            :show-next-reset="showNextReset"
                            :show-missed="showMissed"
                            @clone="onCloneTask"
                            @delete="onDeleteTask"
                        />
                    </li>
                </template>
            </ul>
        </div>
    </div>
    <div class="flex gap-2">
        <input
            v-model="taskInput"
            type="text"
            :placeholder="$t('new_task_hint')"
            class="input grow"
            @keyup.enter="onNewTask"
        />
        <button
            class="btn btn-square"
            :disabled="loading || taskInput.trim().length === 0"
            :title="$t('add_button')"
            @click="onNewTask"
        >
            <circle-plus-icon />
        </button>
    </div>
    <list-options
        v-if="!empty"
        v-model:sort-type="sortType"
        v-model:sort-reverse="sortReverse"
        v-model:show-last-checked="showLastChecked"
        v-model:show-next-reset="showNextReset"
        v-model:separate-completed="separateCompleted"
        v-model:show-missed="showMissed"
        class="mt-4 -mb-4"
        @change-sort="reSortTasks"
    />
</template>
