<template>
  <q-page class="bg-surface-dark login-page">
    <Transition
      mode="out-in"
      name="fade-slide"
    >
      <div
        v-if="!clicked"
        key="splash"
        class="splash-screen"
        @click="clicked = true"
      >
        <img
          class="splash-layer splash-layer--bg"
          :src="BackgroundLogin"
        />

        <img
          class="splash-layer splash-layer--photo"
          :src="FotoDiarista"
        />

        <img
          class="splash-layer splash-layer--logo"
          :src="LogoLogin"
        />
      </div>

      <div
        v-else-if="steps === 5"
        key="step5"
        class="splash-screen"
      >
        <img
          class="splash-layer splash-layer--bg"
          :src="BackgroundLogin"
        />

        <img
          class="splash-layer splash-layer--photo"
          :src="FotoDiarista"
        />

        <img
          class="splash-layer splash-layer--logo-small"
          :src="LogoLogin"
        />

        <div class="step4-card-wrapper">
          <LoginStep4Panel
            @back="goBack"
            @cep-resolved="onCepResolved"
            @device-location="onDeviceLocation"
          />
        </div>
      </div>

      <div
        v-else
        key="flow"
        class="flow-screen"
      >
        <q-form
          ref="loginForm"
          autocapitalize="off"
          autocomplete="off"
          autocorrect="off"
          class="flow-form"
          spellcheck="false"
          @submit="onSubmit"
          @validation-error="scrollToInvalidField"
        >
          <q-scroll-area
            ref="flowScrollArea"
            class="flow-scroll"
          >
            <div class="flow-screen-content">
              <div class="flow-header items-center row">
                <q-btn
                  v-if="steps >= 4"
                  class="flow-back-btn"
                  color="primary"
                  dense
                  flat
                  icon="mdi-arrow-left"
                  round
                  @click="goBack"
                />
              </div>

              <div class="flow-logo q-my-xl">
                <q-img
                  :src="LogoDiariaCampos"
                  style="max-width: 180px"
                />
              </div>

              <div
                v-if="steps === 3"
                class="register-later-row"
              >
                <q-btn
                  align="right"
                  class="register-later-btn"
                  color="primary"
                  flat
                  icon-right="mdi-chevron-right-circle-outline"
                  no-caps
                  :label="$t('auth.register_later')"
                  @click="goToLocationStep"
                />
              </div>

              <div
                ref="flowContent"
                class="flow-content"
                :class="{ 'flow-content--centered': steps < 3, 'flow-content--email-only': steps === 1 && !smsEnabled }"
              >
                <LoginStep1Panel
                  v-if="steps === 1"
                  v-model:email="email"
                  v-model:phone="phone"
                  :server-errors="serverErrors"
                  :sms-enabled="smsEnabled"
                />

                <LoginStep2Panel
                  v-else-if="steps === 2"
                  v-model:code="code"
                  :server-errors="serverErrors"
                />

                <LoginStep3Panel
                  v-else-if="steps === 3"
                  v-model="stepThreeForm"
                  :server-errors="serverErrors"
                />

                <LoginStepAvatarPanel
                  v-else-if="steps === 4"
                  v-model="stepAvatarForm"
                />
              </div>
            </div>
          </q-scroll-area>

          <div class="flow-footer">
            <q-btn
              class="full-width"
              color="primary-button"
              padding="8px 12px"
              rounded
              type="submit"
              :label="$t('auth.continue')"
              :loading="loading"
            >
              <template #loading>
                <q-spinner />
              </template>
            </q-btn>
          </div>
        </q-form>
      </div>
    </Transition>
  </q-page>
</template>

<script setup>
import BackgroundLogin from "src/assets/background-login.svg";
import FotoDiarista from "src/assets/foto_diarista_login.svg";
import LogoDiariaCampos from "src/assets/logo_diaria_campos_login.svg";
import LogoLogin from "src/assets/logo_diaria_login.svg";

import {
  createUserAndClient,
  sendCode,
  updateMe,
  validateCode,
} from "src/api/user";

import { getServicesConfig } from "src/api/services";
import { nextTick, onMounted, provide, ref, watch } from "vue";
import { useAuth } from "src/composables/useAuth";
import { useI18n } from "vue-i18n";
import { useQuasar } from "quasar";
import { useRegistrationFlowStore } from "src/stores/registrationFlow";
import { useRouter } from "vue-router";
import { useScroll } from "src/composables/useScroll";
import { useSubmitHandler } from "src/composables/useSubmitHandler";
import { userStore } from "src/stores/user";

import LoginStep1Panel from "src/components/login/LoginStep1Panel.vue";
import LoginStep2Panel from "src/components/login/LoginStep2Panel.vue";
import LoginStep3Panel from "src/components/login/LoginStep3Panel.vue";
import LoginStep4Panel from "src/components/login/LoginStep4Panel.vue";
import LoginStepAvatarPanel from "src/components/login/LoginStepAvatarPanel.vue";

const { setAuthDataFromPayload } = useAuth();
const { t } = useI18n();
const router = useRouter();
const $q = useQuasar();

const flowStore = useRegistrationFlowStore();

const clicked = ref(false);
const code = ref("");
const email = ref("");
const isLogin = ref(false);

const loginForm = ref(null);
const flowContent = ref(null);
const flowScrollArea = ref(null);

const phone = ref("");

const smsEnabled = ref(false);

const stepAvatarForm = ref({
  avatar: null,
});

const steps = ref(1);

const stepThreeForm = ref({
  address: "",
  address_type: "home",
  city: "",
  complement: "",
  district: "",
  document: "",
  instructions: "",
  latitude: null,
  longitude: null,
  name: "",
  nickname: "",
  no_complement: false,
  number: "",
  phone: "",
  state: "",
  zip_code: "",
});

const { loading, serverErrors, execute } = useSubmitHandler();
const { scrollToComponent } = useScroll();

provide("clearServerError", (field) => {
  serverErrors.value[field] = null;
});

const goBack = () => {
  if (steps.value === 4) {
    steps.value = 3;
  } else if (steps.value === 5) {
    steps.value = 3;
  }
};

const goToLocationStep = () => {
  saveRegistrationData();

  steps.value = 5;
};

const loadServicesConfig = async () => {
  try {
    const config = await getServicesConfig();

    smsEnabled.value = config?.sms_enabled === true;
  } catch (error) {
    console.error("Failed to load services config", error);

    smsEnabled.value = false;
  }
};

const navigateToMap = (lat, lng) => {
  saveRegistrationData();
  flowStore.setInitialLocation(lat, lng);
  router.push({ name: "LocationMapPage" });
};

const onCepResolved = (geoData) => {
  navigateToMap(geoData.lat, geoData.lng);
};

const onDeviceLocation = ({ lat, lng }) => {
  navigateToMap(lat, lng);
};

const onSubmit = async () => {
  try {
    switch (steps.value) {
      case 1: {
        let response;

        await execute(async () => {
          response = await sendCode(email.value, phone.value);
        });

        if (Object.keys(serverErrors.value).length === 0) {
          isLogin.value = response?.data?.payload?.isLogin === true;
          steps.value = 2;
        }

        break;
      }

      case 2: {
        let response;

        await execute(async () => {
          response = await validateCode(
            email.value,
            phone.value,
            code.value,
            isLogin.value,
          );
        });

        if (
          Object.keys(serverErrors.value).length === 0 &&
          response?.status === 200
        ) {
          if (isLogin.value === true) {
            await setAuthDataFromPayload(response.data.payload);

            router.push({ name: "DashboardPage" });
          } else {
            stepThreeForm.value.phone = phone.value;
            steps.value = 3;
          }
        }

        break;
      }

      case 3:
        steps.value = 4;
        break;

      case 4:
        await registerUserAndClient();

        if (Object.keys(serverErrors.value).length > 0) {
          steps.value = 3;
        }

        break;

      default:
        break;
    }
  } catch (error) {
    console.error("Login flow error", error);

    $q.notify({
      type: "negative",
      message: t("auth.register_error"),
    });
  }
};

const registerUserAndClient = async () => {
  const payload = {};

  const append = (key, value) => {
    if (value === null || value === undefined || value === "") {
      return;
    }

    payload[key] = value;
  };

  Object.entries(stepThreeForm.value).forEach(([key, value]) => {
    if (key === "no_complement" || key === "complement") {
      return;
    }

    append(key, value);
  });

  payload.complement = stepThreeForm.value.complement || "";

  append("code", code.value);
  append("email", email.value);
  append("has_complement", true);
  append("phone", stepThreeForm.value.phone || phone.value);

  await execute(async () => {
    const response = await createUserAndClient(payload);

    await setAuthDataFromPayload(response.data.payload);

    if (stepAvatarForm.value.avatar) {
      const user = await updateMe({
        avatar_base64: await fileToBase64(stepAvatarForm.value.avatar),
      });

      userStore().setUser(user);
    }

    router.push({ name: "DashboardPage" });
  });
};

//

const fileToBase64 = (file) =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(reader.error);
    reader.readAsDataURL(file);
  });

const saveRegistrationData = () => {
  const registrationPhone = stepThreeForm.value.phone || phone.value;

  flowStore.setCredentials(email.value, registrationPhone, code.value);

  flowStore.setRegistrationData({
    document: stepThreeForm.value.document,
    name: stepThreeForm.value.name,
    phone: registrationPhone,
  });
};

const scrollToInvalidField = async (field) => {
  await nextTick();

  const target = field ?? flowContent.value?.querySelector(".q-field--error");

  if (target && flowScrollArea.value) {
    scrollToComponent(target, flowScrollArea);
  }
};

watch(
  [steps, () => Object.values(serverErrors.value).some(Boolean)],
  ([, hasErrors]) => {
    if (hasErrors) {
      scrollToInvalidField();
    }
  },
  { flush: "post" },
);

onMounted(() => {
  loadServicesConfig();

  setTimeout(() => {
    clicked.value = true;
  }, 1500);
});
</script>

<style lang="scss" scoped>
.fade-slide-enter-active,
.fade-slide-leave-active {
  transition:
    opacity 0.35s ease,
    transform 0.35s ease;
}

.fade-slide-enter-from {
  opacity: 0;
  transform: translateY(6px);
}

.fade-slide-leave-to {
  opacity: 0;
  transform: translateY(-6px);
}

.login-page {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  background: var(--q-surface-dark);
}

.splash-screen {
  position: relative;
  width: 100vw;
  min-height: 100vh;
  overflow: hidden;
  cursor: pointer;

  .splash-layer {
    position: absolute;

    &--bg {
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    &--photo {
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      opacity: 0.15;
      mix-blend-mode: multiply;
    }

    &--logo {
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 180px;
      z-index: 1;
    }

    &--logo-small {
      top: 18%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 100px;
      z-index: 1;
    }
  }
}

.step4-card-wrapper {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -30%);
  z-index: 2;
  width: 90%;
  max-width: 360px;
}

.flow-screen {
  width: 100%;
  max-width: 500px;
  height: 100vh;
  height: 100dvh;
  background: var(--q-surface-dark);
}

.flow-screen-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding: 16px 20px 0;
  background: var(--q-surface-dark);
}

.flow-header {
  min-height: 36px;
  display: flex;
  align-items: center;
  padding-left: max(4px, env(safe-area-inset-left));
}

.flow-back-btn {
  margin-left: -4px;
}

.flow-logo {
  display: flex;
  justify-content: center;
  padding: 12px 0 20px;
}

.flow-form {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.flow-scroll {
  flex: 1;
  height: 0;
  min-height: 0;

  :deep(.q-scrollarea__content) {
    display: flex;
    flex-direction: column;
  }
}

.flow-content {
  flex: 1;

  &--centered {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  &--email-only {
    align-items: flex-start;
    justify-content: flex-start;
    padding-top: clamp(96px, 16vh, 140px);
  }
}

.flow-footer {
  flex-shrink: 0;
  padding: 8px 20px calc(12px + env(safe-area-inset-bottom));
  background: var(--q-surface-dark);
}

.register-later-row {
  display: flex;
  justify-content: flex-end;
  margin-top: -14px;
  padding-bottom: 18px;
}

.register-later-btn {
  justify-content: flex-end;
}
</style>
