<script setup>
import { ref, reactive, onMounted, resolveComponent } from "vue";
import { useQuasar } from "quasar";
import { useHead } from "#imports";
import { getApiClient, changeExpiredPassword, login } from "@hostlink/light";
const api = getApiClient();
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const emits = defineEmits(["login"]);
const props = defineProps({
  company: { type: String, required: true },
  companyLogo: { type: String, required: true },
  twoFactorAuthentication: { type: Boolean, required: true },
  passwordBasedEnabled: { type: Boolean, required: true },
  googleClientId: { type: String, required: false },
  microsoftClientId: { type: String, required: false },
  microsoftTenantId: { type: String, required: false },
  facebookAppId: { type: String, required: false },
  forgetPasswordEnabled: { type: Boolean, required: true },
  webAuthnEnabled: { type: Boolean, required: true }
});
useHead({
  title: props.company
});
const form1 = ref(null);
const data = reactive({
  username: "",
  password: "",
  code: ""
});
const $q = useQuasar();
const passwordExpiredProcess = (username, password) => {
  $q.dialog({
    title: t("Password expired"),
    message: t("Your password has expired, please enter your new password"),
    prompt: {
      model: "",
      type: "password",
      required: true
    },
    cancel: true,
    persistent: true
  }).onOk(async (newPassword) => {
    try {
      await changeExpiredPassword(username, password, newPassword);
      $q.notify({
        message: t("Your password has been changed successfully, please login again"),
        color: "positive",
        icon: "sym_o_check"
      });
    } catch (e) {
      $q.notify({
        message: e.message,
        color: "negative",
        icon: "sym_o_error"
      });
      passwordExpiredProcess(username, password);
    }
  });
};
const loginWithCode = (username, password) => {
  $q.dialog({
    title: t("Enter your code"),
    message: t("Please enter your two factor authentication code (If you lost your authenticator, please contact your administrator)"),
    prompt: {
      model: "",
      type: "text",
      required: true
    },
    cancel: true,
    persistent: true
  }).onOk(async (code) => {
    data.username = username;
    data.password = password;
    data.code = code;
    submit();
  });
};
const loading = ref(false);
const submit = async () => {
  if (await form1.value.validate()) {
    try {
      loading.value = true;
      await login(data.username, data.password, data.code);
      emits("login");
    } catch (e) {
      data.code = "";
      const errorMessage = e instanceof Error ? e.message : String(e);
      if (errorMessage == "setup_2fa_required") {
        await $q.dialog({
          component: resolveComponent("l-setup-2fa-dialog"),
          componentProps: {
            username: data.username,
            password: data.password
          },
          persistent: true
        });
        return;
      }
      if (errorMessage == "two factor authentication code is required") {
        loginWithCode(data.username, data.password);
        return;
      }
      if (errorMessage == "password is expired") {
        passwordExpiredProcess(data.username, data.password);
        return;
      }
      $q.notify({
        message: errorMessage,
        color: "negative",
        icon: "sym_o_error"
      });
    } finally {
      loading.value = false;
    }
  }
};
const resetPassword = (jwt, code) => {
  $q.dialog({
    title: t("Reset password"),
    message: t("Please enter your new password"),
    prompt: {
      model: "",
      type: "password",
      isValid: (val) => {
        return val.length > 0;
      }
    },
    cancel: true,
    persistent: true
  }).onOk(async (password) => {
    try {
      await api.auth.resetPassword(jwt, password, code);
      $q.notify({
        message: t("Your password has been reset successfully"),
        color: "positive",
        icon: "sym_o_check"
      });
    } catch (e) {
      $q.notify({
        message: e.message,
        color: "negative",
        icon: "sym_o_error"
      });
      resetPassword(jwt, code);
    }
  });
};
const forgetPassword = async () => {
  $q.dialog({
    component: resolveComponent("l-forget-password-dialog")
  }).onOk(async (data2) => {
    $q.dialog({
      title: t("Enter your code"),
      message: t("Please enter the code sent to your email, your code will expire in 10 minutes"),
      prompt: {
        model: "",
        type: "text",
        required: true
      },
      cancel: true,
      persistent: true
    }).onOk(async (code) => {
      if (await api.auth.verifyCode(data2.jwt, code)) {
        resetPassword(data2.jwt, code);
      } else {
        $q.notify({
          message: t("Your code is invalid or expired"),
          color: "negative",
          icon: "sym_o_error"
        });
      }
    });
  });
};
const bioLogin = async () => {
  try {
    await api.auth.webAuthn.login();
    window.self.location.reload();
  } catch (e) {
    $q.notify({
      message: e.message,
      color: "negative",
      icon: "sym_o_error"
    });
  }
};
const handleGoogleCredentialResponse = async (response) => {
  try {
    await api.auth.google.login(response.credential);
    window.self.location.reload();
  } catch (e) {
    $q.notify({
      message: e.message,
      color: "negative",
      icon: "sym_o_error"
    });
  }
};
onMounted(() => {
  if (props.googleClientId) {
    if (!window.google) {
      $q.notify({
        message: "Google login is not available",
        //set script https://accounts.google.com/gsi/client in nuuxt.config.js
        color: "negative",
        icon: "sym_o_error"
      });
      return;
    }
    google.accounts.id.initialize({
      client_id: props.googleClientId,
      callback: handleGoogleCredentialResponse,
      use_fedcm_for_prompt: true
    });
    google.accounts.id.prompt();
    google.accounts.id.renderButton(
      document.getElementById("g_id_signin"),
      {
        type: "profile",
        shape: "pill",
        theme: "outline",
        text: "signin_with",
        size: "large",
        logo_alignment: "left"
      }
    );
  }
});
const microsoftLogin = async (resp) => {
  try {
    await api.auth.microsoft.login(resp.accessToken);
    emits("login");
  } catch (e) {
    $q.notify({
      message: e.message,
      color: "negative"
    });
  }
};
const facebookLogin = (accessToken) => {
  api.auth.facebook.login(accessToken).then(() => {
    emits("login");
  }).catch((e) => {
    $q.notify({
      message: e.message,
      color: "negative"
    });
  });
};
</script>

<template>
  <q-card bordered flat style="min-width:360px" class="fixed-center">
    <q-card-section>
      <q-img :src="companyLogo" class="full-width">
        <template v-slot:error>
          <q-img src="https://raw.githubusercontent.com/HostLink/.github/master/profile/logo.webp" class="full-width" />
        </template>
      </q-img>
      <div class="text-h6">
        {{ company }}
      </div>
      <q-form ref="form1" v-if="passwordBasedEnabled">
        <div class="q-gutter-sm">
          <l-input color="primary" v-model.trim="data.username" label="Username"
            :rules="[(v) => !!v || $t('Username is required')]" clearable :outlined="false" stackLabel
            autocomplete="username">
            <template v-slot:prepend>
              <q-icon name="sym_o_person" />
            </template>
          </l-input>
          <l-input color="primary" v-model="data.password" label="Password" type="password" clearable show-password
            stackLabel :rules="[(v) => !!v || $t('Password is required')]" @keydown.enter.prevent="submit"
            :outlined="false" autocomplete="off">
            <template v-slot:prepend>
              <q-icon name="sym_o_lock" />
            </template>
          </l-input>
          <l-input color="primary" v-if="twoFactorAuthentication" v-model="data.code" label="2FA code" type="text"
            clearable stackLabel :outlined="false">
            <template v-slot:prepend>
              <q-icon name="sym_o_key" />
            </template>
          </l-input>
        </div>
      </q-form>
    </q-card-section>
    <q-card-actions>
      <l-btn outline rounded color="primary" icon="sym_o_fingerprint" @click="bioLogin" v-if="webAuthnEnabled" />
      <l-btn label="Login" outline rounded color="primary" icon="sym_o_login" @click="submit"
        v-if="passwordBasedEnabled" />
      <l-btn label="Forget password" outline rounded color="primary" icon="sym_o_lock_reset" @click="forgetPassword"
        v-if="forgetPasswordEnabled" />
    </q-card-actions>
    <q-card-actions v-if="googleClientId">
      <div>
        <div id="g_id_signin"></div>
      </div>
    </q-card-actions>

    <q-card-actions v-if="microsoftClientId">
      <l-microsoft-button :client-id="microsoftClientId" :tenant-id="microsoftTenantId"
        @login="microsoftLogin"></l-microsoft-button>
    </q-card-actions>

    <q-card-actions v-if="facebookAppId">
      <l-facebook-button @login="facebookLogin" />
    </q-card-actions>
  </q-card>
</template>
