<script setup lang="ts">
import {
    onBeforeMount,
    ref,
    watch,
    computed,
    nextTick,
} from "vue";
import type { Task } from "@/types";
import { CopyIcon, TrashIcon, SaveIcon, XIcon } from "@lucide/vue";
import { updateTask } from "@/api/tasks";
import CronInput from "@/components/CronInput.vue";
import {
    isTemporary,
    taskCompleted,
    taskFutureReset,
    taskNextReset,
} from "@/lib/tasks";
import { relativeTime } from "@/lib/dates";
import { useAlertStore } from "@/stores/alerts";
import { useI18n } from "vue-i18n";
import { isOneTime } from "@/lib/recurrence";

const emit =
    defineEmits<(e: "clone" | "delete" | "updated", task: Task) => void>();

const task = defineModel<Task>({ required: true });
defineProps<{
    showLastChecked: boolean;
    showNextReset: boolean;
    showMissed: boolean;
}>();

const editMode = ref<boolean>(false);
const editName = ref<string>("");
const editCron = ref<string | null>(null);
const refreshKey = ref<number>(0);
const editNameInput = ref<HTMLInputElement | null>(null);

const checked = computed<boolean>(() => taskCompleted(task.value));
const nextReset = computed<Date | null>(() => taskNextReset(task.value));
const futureReset = computed<Date | null>(() => taskFutureReset(task.value));
const missed = computed<boolean>(
    () =>
        !checked.value &&
        futureReset.value !== null &&
        futureReset.value.getTime() < new Date().getTime(),
);

const i18n = useI18n();

const { alertSuccess, alertError } = useAlertStore();

async function onOpen() {
    if (!isTemporary(task.value)) {
        editMode.value = true;
        await nextTick();
        editNameInput.value?.focus();
    }
}

function onClose() {
    editName.value = task.value.name;
    editCron.value = task.value.reset_cron;
    editMode.value = false;
}

function onSave() {
    if (editName.value.trim()) {
        const data = {
            name: editName.value.trim(),
            reset_cron: editCron.value,
        };
        task.value.name = editName.value.trim();
        task.value.reset_cron = editCron.value;
        editMode.value = false;
        updateTask(task.value.id, data)
            .then((newTask) => {
                task.value = newTask;
                emit("updated", newTask);
                alertSuccess(i18n.t("alerts.task_updated"));
            })
            .catch(() => {
                alertError(i18n.t("alerts.task_update_error"));
            });
    }
}

function onCheck() {
    if (!isTemporary(task.value)) {
        if (!checked.value) {
            if (isOneTime(task.value.reset_cron)) {
                emit("delete", task.value);
            } else {
                const data = {
                    check_date: new Date().toISOString(),
                    previous_check_date: task.value.check_date?.toISOString(),
                };
                task.value.previous_check_date = task.value.check_date;
                task.value.check_date = new Date();
                updateTask(task.value.id, data)
                    .then((data) => {
                        task.value = data;
                        emit("updated", data);
                    })
                    .catch(() => {
                        alertError(i18n.t("alerts.task_update_error"));
                    });
            }
        } else {
            const data = {
                check_date: null,
                previous_check_date: task.value.check_date?.toISOString(),
            };
            task.value.previous_check_date = task.value.check_date;
            task.value.check_date = null;
            updateTask(task.value.id, data)
                .then((data) => {
                    task.value = data;
                    emit("updated", data);
                })
                .catch(() => {
                    alertError(i18n.t("alerts.task_update_error"));
                });
        }
    }
}

function onClone() {
    if (!isTemporary(task.value)) {
        emit("clone", task.value);
    }
}

function onDelete() {
    if (!isTemporary(task.value)) {
        emit("delete", task.value);
    }
}

onBeforeMount(() => {
    editName.value = task.value.name;
    editCron.value = task.value.reset_cron;
    setInterval(() => {
        refreshKey.value++;
    }, 60000);
});

watch(task, () => {
    if (!editMode.value && task.value.name !== editName.value) {
        editName.value = task.value.name;
    }
    if (!editMode.value && task.value.reset_cron !== editCron.value) {
        editCron.value = task.value.reset_cron;
    }
});
</script>

<template>
    <div class="list-row text-left">
        <template v-if="!editMode">
            <div class="content-center">
                <input
                    :id="refreshKey.toFixed(0)"
                    type="checkbox"
                    class="checkbox"
                    :checked="checked"
                    @click="onCheck"
                />
            </div>
            <div
                class="cursor-pointer text-lg select-none"
                :class="showMissed && missed ? 'text-error' : ''"
                @click.prevent="onOpen"
            >
                <div>{{ task.name }}</div>
                <div
                    v-if="showLastChecked && !checked && task.check_date"
                    class="font-light text-xs italic"
                >
                    {{ $t("checked") }}
                    {{ relativeTime(task.check_date, $i18n.locale) }}
                </div>
                <div
                    v-if="showNextReset && checked && nextReset"
                    class="font-light text-xs italic"
                >
                    {{ $t("resets") }}
                    {{ relativeTime(nextReset, $i18n.locale) }}
                </div>
            </div>
        </template>
        <template v-else>
            <div class="list-col-grow flex flex-col gap-2">
                <div class="flex justify-evenly">
                    <button
                        class="btn btn-square me-1"
                        :title="$t('cancel_button')"
                        @click="onClose"
                    >
                        <x-icon />
                    </button>
                    <button
                        class="btn btn-square me-1"
                        :class="
                            editName.trim().length === 0 ? 'btn-disabled' : ''
                        "
                        :title="$t('save_button')"
                        @click="onSave"
                    >
                        <save-icon />
                    </button>
                    <button
                        class="btn btn-square me-1"
                        :title="$t('clone_button')"
                        @click="onClone"
                    >
                        <copy-icon />
                    </button>
                    <button
                        class="btn btn-square"
                        :title="$t('delete_button')"
                        @click="onDelete"
                    >
                        <trash-icon />
                    </button>
                </div>
                <input
                    ref="editNameInput"
                    v-model="editName"
                    type="text"
                    class="input w-full"
                    @keyup.enter="onSave"
                />
                <cron-input v-model="editCron" :edit-mode="editMode" />
            </div>
        </template>
    </div>
</template>
