<script setup>

import { ref, onMounted } from 'vue';
import { marked } from 'marked';
import { Button, PasswordInput, TextInput, fetcher, FormGroup } from '@cloudron/pankow';
import { API_ORIGIN } from '../constants.js';
import PublicPageLayout from '../components/PublicPageLayout.vue';

const footer = marked.parse(window.cloudron.footer);
const cloudronName = window.cloudron.name;

const ready = ref(false);
const busy = ref(false);
const error = ref({});
const mode = ref('');
const resetToken = ref('');
const passwordResetIdentifier = ref('');
const newPassword = ref('');
const newPasswordRepeat = ref('');
const totpToken = ref('');

const MODE = {
  NEW_PASSWORD: 'newPassword',
  NEW_PASSWORD_DONE: 'newPasswordDone',
  RESET_PASSWORD: 'passwordReset',
  RESET_PASSWORD_DONE: 'passwordResetDone',
};

async function onPasswordReset() {
  busy.value = true;
  error.value = {};

  try {
    const res = await fetcher.post(`${API_ORIGIN}/api/v1/auth/password_reset_request`, { identifier: passwordResetIdentifier.value });
    if (res.status === 409) {
      error.value.generic = res.body.message;
    } else if (res.status === 202) {
      mode.value = MODE.RESET_PASSWORD_DONE;
    }
  } catch (error) {
    error.value.generic = error;
    console.error('Failed to reset password.', error);
  }

  busy.value = false;
}

async function onNewPassword() {
  if (newPassword.value !== newPasswordRepeat.value) return;

  busy.value = true;
  error.value = {};

  const data = {
    resetToken: resetToken.value,
    password: newPassword.value,
    totpToken: totpToken.value
  };

  try {
    const res = await fetcher.post(`${API_ORIGIN}/api/v1/auth/password_reset`, data);
    if (res.status === 400 || res.status === 401) {
      if (res.body.message.indexOf('totpToken') !== -1) {
        error.value.totpToken = res.body.message;
        totpToken.value = '';
      } else {
        error.value.generic = res.body.message;
        newPasswordRepeat.value = '';
      }
    } else if (res.status === 409) {
      error.value.generic = 'Ask your admin for an invite link first';
    } else if (res.status === 202) {
      // set token to autologin
      localStorage.token = res.body.accessToken;
      mode.value = MODE.NEW_PASSWORD_DONE;
    }
  } catch (error) {
    error.value.generic = 'Internal error';
    console.error('Failed to set new password.', error);
  }

  busy.value = false;
}

onMounted(async () => {
  const search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.indexOf('=') === -1 ? [item, true] : [item.slice(0, item.indexOf('=')), item.slice(item.indexOf('=')+1)]; }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});

  // Init into the correct view
  if (search.resetToken) {
    resetToken.value = search.resetToken;
    window.document.title = 'Set New Password';
    mode.value = MODE.NEW_PASSWORD;
    setTimeout(() => document.getElementById('inputNewPassword').focus(), 200);
  } else if (search.accessToken || search.access_token) { // auto-login feature
    localStorage.token = search.accessToken || search.access_token;
    window.location.href = '/';
  } else { // also search.passwordReset
    window.document.title = 'Password Reset Request';
    mode.value = MODE.RESET_PASSWORD;
    passwordResetIdentifier.value = '';
    setTimeout(() => document.getElementById('inputPasswordResetIdentifier').focus(), 200);
  }

  ready.value = true;
});

</script>

<template>
  <PublicPageLayout :footer-html="footer" :cloudron-name="cloudronName">
    <div v-if="ready">

      <div v-if="mode === MODE.RESET_PASSWORD">
        <h2>{{ $t('passwordReset.title') }}</h2>

        <p class="has-error" v-if="error.generic">{{ error.generic }}</p>

        <form name="passwordResetForm" @submit.prevent="onPasswordReset()">
          <input type="submit" style="display: none;"/>

          <FormGroup>
            <label for="inputPasswordResetIdentifier">{{ $t('passwordReset.usernameOrEmail') }}</label>
            <TextInput id="inputPasswordResetIdentifier" name="passwordResetIdentifier" v-model="passwordResetIdentifier" :disabled="busy" autofocus required />
          </FormGroup>

          <div class="actions">
            <Button @click="onPasswordReset()" :disabled="busy || !passwordResetIdentifier" :loading="busy">{{ $t('passwordReset.resetAction') }}</Button>
            <a class="login" href="/">{{ $t('passwordReset.backToLoginAction') }}</a>
          </div>
        </form>
      </div>

      <div v-if="mode === MODE.RESET_PASSWORD_DONE">
        <h2>{{ $t('passwordReset.emailSent.title') }}</h2>
        <Button href="/">{{ $t('passwordReset.backToLoginAction') }}</Button>
      </div>

      <div v-if="mode === MODE.NEW_PASSWORD">
        <h2>{{ $t('passwordReset.newPassword.title') }}</h2>

        <p class="has-error" v-if="error.generic">{{ error.generic }}</p>

        <form name="newPasswordForm" @submit.prevent="onNewPassword()">
          <input type="submit" style="display: none;"/>
          <input type="password" style="display: none;"/>

          <FormGroup :has-error="(newPasswordRepeat && newPassword !== newPasswordRepeat) ? true : null">
            <label for="inputNewPassword">{{ $t('passwordReset.newPassword.password') }}</label>
            <PasswordInput id="inputNewPassword" v-model="newPassword" autofocus required />
          </FormGroup>

          <FormGroup :has-error="(newPasswordRepeat && newPassword !== newPasswordRepeat) ? true : null">
            <label for="inputNewPasswordRepeat">{{ $t('passwordReset.newPassword.passwordRepeat') }}</label>
            <PasswordInput id="inputNewPasswordRepeat" v-model="newPasswordRepeat" required />
          </FormGroup>

          <FormGroup :has-error="error.totpToken">
            <label for="inputPasswordResetTotpToken">{{ $t('login.2faToken') }}</label>
            <TextInput id="inputPasswordResetTotpToken" v-model="totpToken" :disabled="busy" />
            <p class="has-error" v-if="error.totpToken">{{ error.totpToken }}</p>
          </FormGroup>

          <div class="actions">
            <Button @click="onNewPassword()" :disabled="busy || !newPassword || newPassword !== newPasswordRepeat" :loading="busy">{{ $t('passwordReset.passwordChanged.submitAction') }}</Button>
            <a href="/">{{ $t('passwordReset.backToLoginAction') }}</a>
          </div>
        </form>
      </div>

      <div v-if="mode === MODE.NEW_PASSWORD_DONE">
        <h2>{{ $t('passwordReset.success.title') }}</h2>
        <Button href="/">{{ $t('passwordReset.success.openDashboardAction') }}</Button>
      </div>
    </div>
  </PublicPageLayout>
</template>

<style scoped>

.actions {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.actions a {
  margin-top: 12px;
  font-size: 0.9em;
}

@media (max-width: 576px) {
  .actions {
    align-items: unset;
  }
}

</style>
