<script setup lang="ts">
import { useConfigStore } from "@/stores/config";
import { useNodeStore } from "@/stores/node";
import { computed, nextTick, ref } from "vue";
import CONSTRAINTS from "@/shared/validation/constraints";
import ActionButton from "@/components/form/ActionButton.vue";
import type {
    Coordinates,
    EmailAddress,
    FastdKey,
    Hostname,
    MAC,
    Nickname,
    StoredNode,
} from "@/types";
import {
    ButtonSize,
    ComponentAlignment,
    ComponentVariant,
    hasOwnProperty,
} from "@/types";
import ErrorCard from "@/components/ErrorCard.vue";
import ButtonGroup from "@/components/form/ButtonGroup.vue";
import ValidationForm from "@/components/form/ValidationForm.vue";
import ValidationFormInput from "@/components/form/ValidationFormInput.vue";
import { route, RouteName } from "@/router";
import RouteButton from "@/components/form/RouteButton.vue";
import { ApiError } from "@/utils/Api";

const configStore = useConfigStore();
const nodeStore = useNodeStore();

const emit = defineEmits<{
    (e: "create", node: StoredNode): void;
}>();

const generalError = ref<boolean>(false);

const CONFLICT_MESSAGES: Record<string, string> = {
    hostname: "Der Knotenname ist bereits vergeben. Bitte wähle einen anderen.",
    key: "Für den VPN-Schlüssel gibt es bereits einen Eintrag.",
    mac: "Für die MAC-Adresse gibt es bereits einen Eintrag.",
};

const conflictErrorMessage = ref<string | undefined>(undefined);

const hostname = ref("" as Hostname);
const fastdKey = ref("" as FastdKey);
const mac = ref("" as MAC);
const coords = ref("" as Coordinates);
const nickname = ref("" as Nickname);
const email = ref("" as EmailAddress);
const monitoring = ref(false);

async function onSubmit() {
    generalError.value = false;
    conflictErrorMessage.value = undefined;

    // Make sure to re-render error message to trigger scrolling into view.
    await nextTick();

    try {
        const node = await nodeStore.create({
            hostname: hostname.value,
            key: fastdKey.value || undefined,
            mac: mac.value,
            coords: coords.value || undefined,
            nickname: nickname.value,
            email: email.value,
            monitoring: monitoring.value,
        });
        emit("create", node);
    } catch (error) {
        if (error instanceof ApiError) {
            console.error(error);

            const conflictingField = error.getConflictField();
            if (
                conflictingField !== undefined &&
                hasOwnProperty(CONFLICT_MESSAGES, conflictingField)
            ) {
                conflictErrorMessage.value =
                    CONFLICT_MESSAGES[conflictingField];
            } else {
                generalError.value = true;
            }
        } else {
            throw error;
        }
    }
}
</script>

<template>
    <ValidationForm novalidate="" ref="form" @submit="onSubmit">
        <h2>Neuen Knoten anmelden</h2>

        <div>
            <p>
                Damit Dein neuer Freifunk-Router erfolgreich ins Netz
                eingebunden werden kann, benötigen wir noch ein paar angaben von
                Dir. Sobald Du fertig bist, kannst Du durch einen Klick auf
                "Knoten anmelden" die Anmeldung abschließen.
            </p>
            <p>
                Und keine Sorge:
                <strong>Datenschutz ist uns genauso wichtig wie Dir.</strong>
            </p>

            <ErrorCard v-if="conflictErrorMessage">{{
                conflictErrorMessage
            }}</ErrorCard>
            <ErrorCard v-if="generalError">
                Beim Anlegen des Knotens ist ein Fehler aufgetreten. Bitte
                probiere es später nochmal. Sollte dieses Problem weiter
                bestehen, so wende dich bitte per E-Mail an
                <a :href="`mailto:${email}`">{{ email }}</a
                >.
            </ErrorCard>

            <fieldset>
                <h3>Knotendaten</h3>

                <ValidationFormInput
                    v-model="hostname"
                    label="Knotenname"
                    placeholder="z. B. Lisas-Freifunk"
                    :constraint="CONSTRAINTS.node.hostname"
                    help="Das ist der Name, der auch auf der Karte auftaucht."
                    validation-error="Knotennamen dürfen maximal 32 Zeichen lang sein und nur Klein- und Großbuchstaben, sowie Ziffern, - und _ enthalten."
                />
                <ValidationFormInput
                    v-model="fastdKey"
                    label="VPN-Schlüssel (bitte nur weglassen, wenn Du weisst, was Du tust)"
                    placeholder="Dein 64-stelliger VPN-Schlüssel"
                    :constraint="CONSTRAINTS.node.key"
                    help="Dieser Schlüssel wird verwendet, um die Verbindung Deines Routers zu den Gateway-Servern abzusichern."
                    validation-error="Knotennamen dürfen maximal 32 Zeichen lang sein und nur Klein- und Großbuchstaben, sowie Ziffern, - und _ enthalten."
                />
                <ValidationFormInput
                    v-model="mac"
                    label="MAC-Adresse"
                    placeholder="z. B. 12:34:56:78:9a:bc oder 123456789abc"
                    :constraint="CONSTRAINTS.node.mac"
                    help="Die MAC-Adresse (kurz „MAC“) steht üblicherweise auf dem Aufkleber auf der Unterseite deines Routers. Sie wird verwendet, um die Daten Deines Routers auf der Karte korrekt zuzuordnen."
                    validation-error="Die angegebene MAC-Adresse ist ungültig."
                />
            </fieldset>

            <h1>TODO: Standort</h1>

            <fieldset>
                <h3>Wie können wir Dich erreichen?</h3>

                <p class="help-block">
                    Deinen Namen und Deine E-Mail-Adresse verwenden wir
                    ausschließlich, um bei Problemen mit Deinem Router oder bei
                    wichtigen Änderungen Kontakt zu Dir aufzunehmen. Bitte trage
                    eine gültige E-Mail-Adresse ein, damit wir Dich im Zweifel
                    erreichen können. Deine persönlichen Daten sind
                    selbstverständlich
                    <strong>nicht öffentlich einsehbar</strong> und werden von
                    uns <strong>nicht weitergegeben</strong>
                    oder anderweitig verwendet. Versprochen!
                </p>

                <ValidationFormInput
                    v-model="nickname"
                    label="Nickname / Name"
                    placeholder="z. B. Lisa"
                    :constraint="CONSTRAINTS.node.nickname"
                    validation-error="Nicknames dürfen maximal 64 Zeichen lang sein und nur Klein- und Großbuchstaben, sowie Ziffern, - und _ enthalten. Umlaute sind erlaubt."
                />
                <ValidationFormInput
                    v-model="email"
                    type="email"
                    label="E-Mail-Adresse"
                    :placeholder="`z. B. lisa@${configStore.getConfig.community.domain}`"
                    :constraint="CONSTRAINTS.node.email"
                    validation-error="Die angegebene E-Mail-Adresse ist ungültig."
                />
            </fieldset>

            <h1>TODO: Monitoring</h1>

            <ButtonGroup
                :align="ComponentAlignment.RIGHT"
                :button-size="ButtonSize.SMALL"
            >
                <ActionButton
                    type="submit"
                    icon="dot-circle-o"
                    :variant="ComponentVariant.INFO"
                    :size="ButtonSize.SMALL"
                >
                    Knoten anmelden
                </ActionButton>
                <RouteButton
                    type="reset"
                    icon="times"
                    :variant="ComponentVariant.SECONDARY"
                    :size="ButtonSize.SMALL"
                    :route="route(RouteName.HOME)"
                >
                    Abbrechen
                </RouteButton>
            </ButtonGroup>
        </div>
    </ValidationForm>
</template>

<style lang="scss" scoped></style>