<script setup lang="ts">
import type { Recordable } from '@easyflow/types';

import type { EasyFlowFormSchema } from '@easyflow-core/form-ui';

import type { AuthenticationProps } from './types';

import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';

import { $t } from '@easyflow/locales';

import { useEasyFlowForm } from '@easyflow-core/form-ui';
import { EasyFlowButton, EasyFlowCheckbox } from '@easyflow-core/shadcn-ui';

import Title from './auth-title.vue';
import ThirdPartyLogin from './third-party-login.vue';

interface Props extends AuthenticationProps {
  formSchema?: EasyFlowFormSchema[];
}

defineOptions({
  name: 'AuthenticationLogin',
});

const props = withDefaults(defineProps<Props>(), {
  codeLoginPath: '/auth/code-login',
  forgetPasswordPath: '/auth/forget-password',
  formSchema: () => [],
  loading: false,
  qrCodeLoginPath: '/auth/qrcode-login',
  registerPath: '/auth/register',
  showCodeLogin: false,
  showForgetPassword: false,
  showHeader: true,
  showQrcodeLogin: false,
  showRegister: false,
  showRememberMe: false,
  showThirdPartyLogin: false,
  submitButtonText: '',
  subTitle: '',
  title: '',
});

const emit = defineEmits<{
  submit: [Recordable<any>];
}>();

const [Form, formApi] = useEasyFlowForm(
  reactive({
    commonConfig: {
      hideLabel: true,
      hideRequiredMark: true,
    },
    schema: computed(() => props.formSchema),
    showDefaultActions: false,
  }),
);
const router = useRouter();

const REMEMBER_ME_KEY = `REMEMBER_ME_ACCOUNT_${location.hostname}`;
const localAccount = localStorage.getItem(REMEMBER_ME_KEY) || '';
const rememberMe = ref(!!localAccount);

async function handleSubmit() {
  const { valid } = await formApi.validate();
  const values = await formApi.getValues();
  if (valid) {
    localStorage.setItem(
      REMEMBER_ME_KEY,
      rememberMe.value ? (values?.account ?? '') : '',
    );
    emit('submit', values);
  }
}

function handleGo(path: string) {
  router.push(path);
}

onMounted(() => {
  if (localAccount) {
    formApi.setFieldValue('account', localAccount);
  }
});

defineExpose({
  getFormApi: () => formApi,
});
</script>

<template>
  <div class="auth-login" @keydown.enter.prevent="handleSubmit">
    <template v-if="showHeader">
      <slot name="title">
        <Title>
          <slot name="title">
            {{ title || $t('authentication.welcomeBack') }}
          </slot>
          <template v-if="subTitle || $t('authentication.loginSubtitle')" #desc>
            <span class="text-muted-foreground">
              <slot name="subTitle">
                {{ subTitle || $t('authentication.loginSubtitle') }}
              </slot>
            </span>
          </template>
        </Title>
      </slot>
    </template>

    <div class="auth-form-group">
      <Form />
    </div>

    <div
      v-if="showRememberMe || showForgetPassword"
      class="auth-login-options mt-1 flex items-center justify-between gap-3"
    >
      <EasyFlowCheckbox
        v-if="showRememberMe"
        v-model="rememberMe"
        class="auth-checkbox"
        name="rememberMe"
      >
        {{ $t('authentication.rememberMe') }}
      </EasyFlowCheckbox>

      <button
        v-if="showForgetPassword"
        class="auth-inline-action"
        type="button"
        @click="handleGo(forgetPasswordPath)"
      >
        {{ $t('authentication.forgetPassword') }}
      </button>
    </div>

    <EasyFlowButton
      :class="{ 'cursor-wait': loading }"
      :loading="loading"
      aria-label="login"
      class="auth-submit-button auth-brand-submit mt-6 h-11 w-full rounded-xl text-base font-medium"
      @click="handleSubmit"
    >
      {{ submitButtonText || $t('common.login') }}
    </EasyFlowButton>

    <slot name="overlay"></slot>

    <div
      v-if="showCodeLogin || showQrcodeLogin"
      class="auth-alt-modes mt-5 grid gap-3 sm:grid-cols-2"
    >
      <EasyFlowButton
        v-if="showCodeLogin"
        class="auth-secondary-button h-11 w-full rounded-xl"
        variant="outline"
        @click="handleGo(codeLoginPath)"
      >
        {{ $t('authentication.mobileLogin') }}
      </EasyFlowButton>
      <EasyFlowButton
        v-if="showQrcodeLogin"
        class="auth-secondary-button h-11 w-full rounded-xl"
        variant="outline"
        @click="handleGo(qrCodeLoginPath)"
      >
        {{ $t('authentication.qrcodeLogin') }}
      </EasyFlowButton>
    </div>

    <slot name="third-party-login">
      <ThirdPartyLogin v-if="showThirdPartyLogin" />
    </slot>

    <slot name="to-register">
      <div
        v-if="showRegister"
        class="auth-footer-copy mt-5 text-center text-sm"
      >
        {{ $t('authentication.accountTip') }}
        <button
          class="auth-inline-action"
          type="button"
          @click="handleGo(registerPath)"
        >
          {{ $t('authentication.createAccount') }}
        </button>
      </div>
    </slot>
  </div>
</template>

<style scoped>
.auth-login {
  position: relative;
}

.auth-form-group :deep(.easyflow-form-ui + .easyflow-form-ui) {
  margin-top: 0.95rem;
}

.auth-form-group :deep(.easyflow-form-ui .text-destructive) {
  margin-top: 0.45rem;
  font-size: 0.84rem;
}

.auth-login-options {
  min-height: 1.5rem;
}

.auth-checkbox {
  font-size: 0.92rem;
  color: hsl(var(--text-muted));
}

.auth-inline-action {
  font-size: 0.92rem;
  font-weight: 500;
  color: hsl(var(--nav-item-active-foreground));
  transition: opacity 0.18s ease;
}

.auth-inline-action:hover {
  opacity: 0.76;
}

.auth-secondary-button {
  background: hsl(var(--surface-elevated));
  border-color: hsl(var(--line-subtle));
}

.auth-brand-submit {
  color: rgb(255 255 255);
  background: linear-gradient(
    120deg,
    rgb(11 111 211) 0%,
    rgb(22 159 200) 38%,
    rgb(38 199 193) 62%,
    rgb(11 111 211) 100%
  );
  background-size: 200% 200%;
  border: none;
  box-shadow:
    0 22px 34px -22px rgb(11 111 211 / 56%),
    inset 0 1px 0 rgb(255 255 255 / 24%);
  transition:
    transform 180ms ease,
    box-shadow 180ms ease,
    filter 180ms ease;
  animation: auth-brand-gradient 6s ease infinite;
}

.auth-brand-submit:hover {
  box-shadow:
    0 24px 38px -22px rgb(11 111 211 / 62%),
    inset 0 1px 0 rgb(255 255 255 / 28%);
  filter: saturate(1.04);
  transform: translateY(-1px);
}

.auth-brand-submit:active {
  transform: translateY(0);
}

.auth-brand-submit:focus-visible {
  outline: 2px solid rgb(78 176 255 / 80%);
  outline-offset: 2px;
}

.auth-footer-copy {
  color: hsl(var(--text-muted));
}

@keyframes auth-brand-gradient {
  0% {
    background-position: 0% 50%;
  }

  50% {
    background-position: 100% 50%;
  }

  100% {
    background-position: 0% 50%;
  }
}
</style>
