<script setup lang="ts">
import type { ToolbarType } from './types';

import { computed, ref, watch } from 'vue';

import { preferences, usePreferences } from '@easyflow/preferences';

import { Copyright } from '../basic/copyright';
import AuthenticationFormView from './form.vue';
import SloganIcon from './icons/slogan.vue';
import Toolbar from './toolbar.vue';

interface Props {
  appName?: string;
  logo?: string;
  logoDark?: string;
  pageTitle?: string;
  pageDescription?: string;
  sloganImage?: string;
  toolbar?: boolean;
  copyright?: boolean;
  toolbarList?: ToolbarType[];
  clickLogo?: () => void;
}

const props = withDefaults(defineProps<Props>(), {
  appName: '',
  copyright: true,
  logo: '',
  logoDark: '',
  pageDescription: '',
  pageTitle: '',
  sloganImage: '',
  toolbar: true,
  toolbarList: () => ['color', 'language', 'layout', 'theme'],
  clickLogo: () => {},
});

const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
  usePreferences();

const isSloganLoadError = ref(false);

/**
 * @zh_CN 根据主题选择合适的 logo 图标
 */
const logoSrc = computed(() => {
  if (isDark.value && props.logoDark) {
    return props.logoDark;
  }
  return props.logo;
});

watch(
  () => props.sloganImage,
  () => {
    isSloganLoadError.value = false;
  },
);

function handleSloganError() {
  isSloganLoadError.value = true;
}
</script>

<template>
  <div
    :class="[isDark ? 'dark' : '']"
    class="auth-shell relative flex min-h-full flex-1 select-none overflow-x-hidden"
  >
    <template v-if="toolbar">
      <slot name="toolbar">
        <Toolbar :toolbar-list="toolbarList" />
      </slot>
    </template>

    <AuthenticationFormView
      v-if="authPanelLeft"
      class="auth-panel-form min-h-full w-full flex-1 lg:w-[42%] lg:flex-initial"
      data-side="left"
    >
      <template v-if="copyright" #copyright>
        <slot name="copyright">
          <Copyright
            v-if="preferences.copyright.enable"
            v-bind="preferences.copyright"
          />
        </slot>
      </template>
    </AuthenticationFormView>

    <slot name="logo">
      <div
        v-if="logoSrc || appName"
        class="absolute left-0 top-0 z-20 flex flex-1"
        @click="clickLogo"
      >
        <div
          class="text-foreground ml-4 mt-4 flex flex-1 items-center sm:left-6 sm:top-6"
        >
          <img
            v-if="logoSrc"
            :key="logoSrc"
            :alt="appName"
            :src="logoSrc"
            class="mr-2"
            width="120"
          />
        </div>
      </div>
    </slot>

    <div
      v-if="!authPanelCenter"
      class="auth-hero relative hidden min-h-full w-0 flex-1 overflow-hidden lg:block"
    >
      <div class="auth-hero-base absolute inset-0"></div>
      <div class="auth-orb auth-orb-left"></div>
      <div class="auth-orb auth-orb-right"></div>
      <div class="auth-orb auth-orb-bottom"></div>

      <div
        :key="authPanelLeft ? 'left' : authPanelRight ? 'right' : 'center'"
        class="auth-hero-content flex-col-center relative h-full px-12"
        :class="{
          'enter-x': authPanelLeft,
          '-enter-x': authPanelRight,
        }"
      >
        <div class="auth-hero-visual">
          <template v-if="sloganImage && !isSloganLoadError">
            <img
              :alt="appName"
              :src="sloganImage"
              class="auth-hero-image"
              @error="handleSloganError"
            />
          </template>
          <SloganIcon v-else :alt="appName" class="auth-hero-fallback" />
        </div>

        <div class="auth-page-title text-foreground">
          {{ pageTitle }}
        </div>
        <div class="auth-page-desc text-muted-foreground">
          {{ pageDescription }}
        </div>
      </div>
    </div>

    <div v-if="authPanelCenter" class="auth-center relative w-full">
      <div class="auth-hero-base absolute inset-0"></div>
      <div class="auth-orb auth-orb-left"></div>
      <div class="auth-orb auth-orb-right"></div>
      <AuthenticationFormView
        class="auth-center-card shadow-float w-full rounded-3xl pb-20 md:w-2/3 lg:w-1/2 xl:w-[36%]"
        data-side="bottom"
      >
        <template v-if="copyright" #copyright>
          <slot name="copyright">
            <Copyright
              v-if="preferences.copyright.enable"
              v-bind="preferences.copyright"
            />
          </slot>
        </template>
      </AuthenticationFormView>
    </div>

    <AuthenticationFormView
      v-if="authPanelRight"
      class="auth-panel-form min-h-full w-full flex-1 lg:w-[42%] lg:flex-initial"
      data-side="right"
    >
      <template v-if="copyright" #copyright>
        <slot name="copyright">
          <Copyright
            v-if="preferences.copyright.enable"
            v-bind="preferences.copyright"
          />
        </slot>
      </template>
    </AuthenticationFormView>
  </div>
</template>

<style scoped>
.auth-shell {
  background: linear-gradient(180deg, #f8fbff 0%, #f1f6ff 100%);
}

.auth-panel-form {
  backdrop-filter: blur(6px);
}

.auth-hero {
  border-inline: 1px solid rgb(29 108 255 / 6%);
}

.auth-hero-base {
  background:
    radial-gradient(circle at 22% 18%, rgb(56 131 255 / 14%) 0, transparent 42%),
    radial-gradient(circle at 82% 16%, rgb(88 179 255 / 12%) 0, transparent 35%),
    radial-gradient(circle at 70% 86%, rgb(112 146 255 / 10%) 0, transparent 40%),
    linear-gradient(145deg, #eef5ff 0%, #f4f8ff 45%, #eef4ff 100%);
}

.auth-hero-content {
  z-index: 2;
}

.auth-hero-visual {
  width: min(860px, 90%);
  max-width: 920px;
}

.auth-hero-image {
  width: 100%;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 24px 48px rgb(24 78 173 / 10%));
}

.auth-hero-fallback {
  width: 100%;
  height: auto;
}

.auth-page-title {
  margin-top: 1.2rem;
  font-size: clamp(1.9rem, 2.5vw, 2.45rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-align: center;
}

.auth-page-desc {
  margin-top: 0.9rem;
  max-width: 42rem;
  font-size: clamp(0.96rem, 1.1vw, 1.12rem);
  line-height: 1.7;
  text-align: center;
}

.auth-center {
  align-items: center;
  display: flex;
  justify-content: center;
  overflow: hidden;
}

.auth-center-card {
  position: relative;
  z-index: 2;
}

.auth-orb {
  border-radius: 9999px;
  position: absolute;
  z-index: 1;
}

.auth-orb-left {
  background: rgb(101 149 255 / 18%);
  height: 18rem;
  left: -4rem;
  top: 4.5rem;
  width: 18rem;
}

.auth-orb-right {
  background: rgb(124 188 255 / 16%);
  height: 10rem;
  right: 3rem;
  top: 5rem;
  width: 10rem;
}

.auth-orb-bottom {
  background: rgb(93 154 255 / 12%);
  bottom: 2rem;
  height: 14rem;
  right: 5rem;
  width: 14rem;
}

.dark.auth-shell {
  background: linear-gradient(180deg, #05080f 0%, #070b14 100%);

  .auth-hero {
    border-inline: 1px solid rgb(125 168 255 / 10%);
  }

  .auth-hero-base {
    background:
      radial-gradient(circle at 20% 18%, rgb(63 115 255 / 22%) 0, transparent 45%),
      radial-gradient(circle at 82% 16%, rgb(56 149 255 / 18%) 0, transparent 38%),
      radial-gradient(circle at 72% 86%, rgb(96 124 255 / 20%) 0, transparent 42%),
      linear-gradient(150deg, #0a1326 0%, #091022 45%, #0b1529 100%);
  }

  .auth-page-desc {
    color: rgb(181 194 226 / 82%);
  }

  .auth-hero-image {
    filter: drop-shadow(0 26px 52px rgb(8 19 42 / 48%));
  }

  .auth-orb-left {
    background: rgb(81 126 255 / 24%);
  }

  .auth-orb-right {
    background: rgb(59 140 248 / 22%);
  }

  .auth-orb-bottom {
    background: rgb(94 105 239 / 20%);
  }
}
</style>
