<script setup>
// Add a server, edit one, or log into it — one dialog, because for a server you
// have just typed in they are the same act: an address is only worth keeping
// once something has answered at it.
import { ref, computed } from "vue";
import {
  DEFAULT_API_BASE,
  HOME_ID,
  addServer,
  updateServer,
  removeServer,
  isConnected,
  displayName,
} from "../servers";
import { connect, disconnect } from "../auth";
import { t } from "../i18n";
import { askConfirm } from "../lib/confirm.js";
import Modal from "./Modal.vue";

const props = defineProps({
  // An existing server to edit/connect to, or null to add a new one.
  server: { type: Object, default: null },
});
const emit = defineEmits(["done", "close"]);

const isNew = !props.server;
const isHome = props.server?.id === HOME_ID;
const connected = computed(() => !!props.server && isConnected(props.server.id));

const name = ref(props.server?.name || "");
const url = ref(props.server?.url || "");
const email = ref("");
const password = ref("");
const showPassword = ref(false);
const busy = ref(false);
const error = ref("");

const title = computed(() =>
  isNew ? t("servers.addTitle") : displayName(props.server)
);

async function submit() {
  busy.value = true;
  error.value = "";
  // Keep the id of a server added in this attempt, so a second try after a bad
  // password edits that entry instead of stacking up duplicates.
  let target = props.server;
  try {
    if (isNew) target = addServer({ name: name.value, url: url.value });
    else updateServer(target.id, { name: name.value, url: url.value });

    if (connected.value) emit("done");
    else {
      await connect(target.id, email.value.trim(), password.value);
      emit("done");
    }
  } catch (e) {
    error.value = e.message || t("login.failed");
    // A server that never answered is not worth keeping in the list.
    if (isNew && target) {
      removeServer(target.id);
      target = null;
    }
  } finally {
    busy.value = false;
  }
}

function onDisconnect() {
  disconnect(props.server.id);
  emit("done");
}

async function onRemove() {
  if (!(await askConfirm(t("servers.removeConfirm", { name: displayName(props.server) })))) return;
  removeServer(props.server.id);
  emit("done");
}
</script>

<template>
  <Modal :title="title" @close="emit('close')">
    <form class="space-y-4" @submit.prevent="submit">
      <p v-if="error" class="rounded-control bg-danger-soft px-3 py-2 text-sm font-medium text-danger">{{ error }}</p>

      <div>
        <label class="dh-label">{{ t("servers.name") }}</label>
        <input v-model="name" type="text" :placeholder="t('servers.namePlaceholder')" class="dh-input" />
      </div>

      <div>
        <label class="dh-label">{{ t("servers.url") }}</label>
        <input
          v-model="url"
          type="text"
          :placeholder="isHome ? DEFAULT_API_BASE : 'https://garage.example.com'"
          autocomplete="off"
          spellcheck="false"
          class="dh-input data"
        />
        <p class="mt-1 text-xs text-muted">{{ isHome ? t("servers.urlHomeHint") : t("servers.urlHint") }}</p>
      </div>

      <!-- Credentials only while this server has no session: each server is its
           own PocketBase, so signing in happens once per server. -->
      <template v-if="!connected">
        <div class="border-t border-subtle pt-4">
          <label class="dh-label">{{ t("login.email") }}</label>
          <input v-model="email" type="email" required autocomplete="off" class="dh-input" />
        </div>
        <div>
          <label class="dh-label">{{ t("login.password") }}</label>
          <div class="relative">
            <input
              v-model="password"
              :type="showPassword ? 'text' : 'password'"
              required
              autocomplete="off"
              class="dh-input pr-10"
            />
            <button
              type="button"
              class="absolute inset-y-0 right-0 flex items-center px-3 text-muted transition-colors hover:text-strong"
              :aria-label="showPassword ? t('login.hidePassword') : t('login.showPassword')"
              @click="showPassword = !showPassword"
            >
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5">
                <path v-if="showPassword" stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" />
                <template v-else>
                  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
                  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
                </template>
              </svg>
            </button>
          </div>
        </div>
      </template>

      <div class="flex items-center gap-2 pt-1">
        <button type="submit" :disabled="busy" class="dh-btn dh-btn-primary">
          {{ busy ? t("servers.connecting") : connected ? t("common.save") : t("servers.connect") }}
        </button>
        <button type="button" class="dh-btn dh-btn-ghost" @click="emit('close')">{{ t("common.cancel") }}</button>
        <span class="flex-1"></span>
        <button
          v-if="connected"
          type="button"
          class="dh-btn !px-3 !py-1.5 !text-xs text-muted hover:bg-sunken"
          @click="onDisconnect"
        >
          {{ t("servers.signOut") }}
        </button>
        <button
          v-if="!isNew && !isHome"
          type="button"
          class="dh-btn !px-3 !py-1.5 !text-xs text-danger hover:bg-danger-soft"
          @click="onRemove"
        >
          {{ t("common.remove") }}
        </button>
      </div>
    </form>
  </Modal>
</template>
