<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
  <q-page class="login-page bg-surface-dark">
    <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 key="flow" class="flow-screen">
        <q-form
          ref="loginForm"
          autocapitalize="off"
          autocomplete="off"
          autocorrect="off"
          class="flow-form"
          spellcheck="false"
          @submit="onSubmit"
          @validation-error="onValidationError"
        >
          <q-scroll-area
            ref="flowContentRef"
            class="flow-scroll"
          >
            <div class="flow-screen-content">
              <div v-if="!showSubStep" class="flow-header row items-center">
                <q-btn
                  v-if="showBackButton"
                  class="flow-back-btn"
                  color="primary"
                  dense
                  flat
                  round
                  icon="mdi-arrow-left"
                  @click="goBack"
                />
              </div>

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

              <div
                class="flow-content"
                :class="{
                  'flow-content--centered': steps <= 2 && !showSubStep,
                  'flow-content--email-only':
                    steps === 1 && !smsEnabled && !showSubStep,
                }"
              >
                <LoginStep1Panel
                  v-if="steps === 1"
                  v-model:email="email"
                  v-model:phone="phone"
                  :sms-enabled="smsEnabled"
                />

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

                <LoginStep3Panel
                  v-else-if="steps === 3"
                  ref="stepThreeRef"
                  v-model="stepThreeForm"
                />

                <LoginStep4Panel
                  v-else-if="steps === 4"
                  ref="stepFourRef"
                  v-model="stepFourForm"
                  @update:show-sub-step="showSubStep = $event"
                />

                <LoginStep5Panel
                  v-else-if="steps === 5"
                  ref="stepFiveRef"
                  v-model="stepFiveForm"
                />

                <LoginStep6Panel
                  v-else-if="steps === 6"
                  ref="stepSixRef"
                  v-model="stepSixForm"
                />
              </div>
            </div>
          </q-scroll-area>

          <div v-if="!showSubStep" class="flow-footer">
            <q-btn
              class="full-width"
              color="primary-button"
              padding="8px 16px"
              rounded
              type="submit"
              :label="actionLabel"
              :loading="loading"
            >
              <template #loading>
                <q-spinner />
              </template>
            </q-btn>
          </div>
        </q-form>

      </div>
    </Transition>
  </q-page>
</template>

<script setup>
import { computed, nextTick, onMounted, provide, ref, watch } from "vue";
import { createUserAndProvider, sendCode, validateCode } from "src/api/user";
import { getServiceConfiguration } from "src/api/serviceConfiguration";
import { useAuth } from "src/composables/useAuth";
import { useI18n } from "vue-i18n";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { useScroll } from "src/composables/useScroll";
import { useSubmitHandler } from "src/composables/useSubmitHandler";

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 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 LoginStep5Panel from "src/components/login/LoginStep5Panel.vue";
import LoginStep6Panel from "src/components/login/LoginStep6Panel.vue";

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

const {
  loading,
  serverErrors,
  execute: submitForm,
} = useSubmitHandler();

const clearServerError = (field) => {
  serverErrors.value[field] = null;
};

provide("serverErrors", serverErrors);
provide("clearServerError", clearServerError);

const FIELD_TO_STEP = {
  name: 3, email: 3, phone: 3, rg: 3, document: 3, birth_date: 3, gender: 3,
  zip_code: 3, address: 3, number: 3, district: 3, city: 3, state: 3,
  complement: 3, nickname: 3, instructions: 3, address_type: 3,
  selfie: 4, document_front: 4, document_back: 4,
  daily_price_8h: 5, daily_price_6h: 5, daily_price_4h: 5, daily_price_2h: 5,
  working_days: 6,
};

watch(serverErrors, () => {
  const firstErrorField = Object.keys(serverErrors.value).find(
    (field) => !!serverErrors.value[field] && FIELD_TO_STEP[field],
  );

  if (!firstErrorField) return;

  const targetStep = FIELD_TO_STEP[firstErrorField];

  if (targetStep !== steps.value) {
    steps.value = targetStep;
  }

  nextTick(() => {
    const panelRef =
      targetStep === 3 ? stepThreeRef
      : targetStep === 4 ? stepFourRef
      : targetStep === 5 ? stepFiveRef
      : targetStep === 6 ? stepSixRef
      : null;

    const fieldRef = panelRef?.value?.getFieldRef?.(firstErrorField);

    if (fieldRef) {
      scrollToComponent(fieldRef, flowContentRef);
    }
  });
}, { deep: true });

const clicked = ref(false);
const code = ref("");
const email = ref("");
const isLogin = ref(false);
const loginForm = ref(null);
const phone = ref("");
const showSubStep = ref(false);
const smsEnabled = ref(false);

const createInitialStepFiveForm = () => ({
  daily_price_2h: null,
  daily_price_4h: null,
  daily_price_6h: null,
  daily_price_8h: null,
  services_types_ids: [],
});

const createInitialStepFourForm = () => ({
  document_back: null,
  document_front: null,
  selfie: null,
});

const createInitialStepSixForm = () => ({
  account_check_digit: "",
  account_number: "",
  account_type: "checking",
  bank: "",
  branch_check_digit: "",
  branch_number: "",
  working_days: {},
});

const createInitialStepThreeForm = () => ({
  address: "",
  address_type: "home",
  birth_date: "",
  city: "",
  complement: "",
  document: "",
  district: "",
  email: "",
  gender: "",
  instructions: "",
  latitude: null,
  longitude: null,
  name: "",
  nickname: "Principal",
  number: "",
  phone: "",
  rg: "",
  state: "",
  zip_code: "",
});

const stepFiveForm = ref(createInitialStepFiveForm());
const stepFourForm = ref(createInitialStepFourForm());
const stepSixForm = ref(createInitialStepSixForm());
const stepThreeForm = ref(createInitialStepThreeForm());

const steps = ref(1);

const flowContentRef = ref(null);
const stepThreeRef = ref(null);
const stepFourRef = ref(null);
const stepFiveRef = ref(null);
const stepSixRef = ref(null);

const actionLabel = computed(() => {
  if (steps.value === 1) return t("provider.login.steps.step_1.action");
  if (steps.value === 2) return t("provider.login.steps.step_2.action");
  if (steps.value === 6) return t("provider.login.steps.step_6.action");

  return t("provider.login.steps.step_3.action");
});

const FIRST_NAVIGABLE_STEP = 3;

const showBackButton = computed(() => steps.value > FIRST_NAVIGABLE_STEP);

const goToStep = async (target) => {
  steps.value = target;

  await nextTick();

  loginForm.value?.resetValidation();
  flowContentRef.value?.setScrollPosition("vertical", 0);
};

const goBack = async () => {
  if (steps.value <= FIRST_NAVIGABLE_STEP) return;

  await goToStep(steps.value - 1);
};

//

const hasWorkingDaySelected = () => mapWorkingDays().length > 0;

const hasCoordinateValue = (value) =>
  value !== null && value !== undefined && String(value).trim() !== "";

//

const loadServiceConfiguration = async () => {
  try {
    const configuration = await getServiceConfiguration();

    smsEnabled.value = configuration?.sms_enabled === true;
  } catch (error) {
    smsEnabled.value = false;
    console.error("Erro ao carregar configuração dos serviços:", error);
  }

  if (!smsEnabled.value) {
    phone.value = "";
  }
};

const mapWorkingDays = () => {
  const mapped = [];

  const workingDays = stepSixForm.value.working_days || {};

  Object.entries(workingDays).forEach(([dayKey, periods]) => {
    if (periods?.morning) {
      mapped.push({ day: Number(dayKey), period: "morning" });
    }

    if (periods?.afternoon) {
      mapped.push({ day: Number(dayKey), period: "afternoon" });
    }
  });

  return mapped;
};

const onValidationError = async (field) => {
  await nextTick();
  scrollToComponent(field, flowContentRef);
};

const onSubmit = async () => {
  if (showSubStep.value) return;

  const isValid = await loginForm.value.validate();

  if (!isValid) return;

  loading.value = true;

  try {
    switch (steps.value) {
      case 1: {
        const response = await sendValidationCode();

        isLogin.value = response?.data?.payload?.isLogin === true;

        break;
      }

      case 2:
        await validateCodeInput();

        break;

      case 3: {
        if (await validateCurrentStep()) {
          await goToStep(4);
        }

        break;
      }

      case 4: {
        if (await validateCurrentStep()) {
          await goToStep(5);
        }

        break;
      }

      case 5: {
        if (await validateCurrentStep()) {
          await goToStep(6);
        }

        break;
      }

      case 6: {
        if (await validateCurrentStep()) {
          await submitForm(registerUserAndProvider);
        }

        break;
      }

      default:
        break;
    }
  } catch (error) {
    console.error(error);

    const msg =
      error?.response?.data?.message ??
      error?.message ??
      "Erro ao concluir cadastro. Tente novamente.";

    $q.notify({ message: msg, type: "negative" });
  } finally {
    loading.value = false;
  }
};

const registerUserAndProvider = async () => {
  const workingDays = mapWorkingDays();

  const form = new FormData();

  const hasValue = (val) =>
    val !== null && val !== undefined && String(val).trim() !== "";

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

    if (typeof val === "boolean") {
      form.append(key, val ? "1" : "0");
    } else {
      form.append(key, val);
    }
  };

  const appendIfFilled = (key, val) => {
    if (!hasValue(val)) return;

    form.append(key, val);
  };

  const appendCoordinate = (key, val) => {
    if (!hasCoordinateValue(val)) return;

    form.append(key, String(val));
  };

  append("name", stepThreeForm.value.name);
  append("email", stepThreeForm.value.email || email.value);
  append("phone", stepThreeForm.value.phone || phone.value);
  append("code", code.value);
  append("rg", stepThreeForm.value.rg);
  append("document", stepThreeForm.value.document);
  append("birth_date", toISODate(stepThreeForm.value.birth_date));
  append("gender", stepThreeForm.value.gender);
  append("zip_code", stepThreeForm.value.zip_code);
  append("address", stepThreeForm.value.address);
  append("number", stepThreeForm.value.number);
  append("district", stepThreeForm.value.district);
  append("has_complement", true);
  append("complement", stepThreeForm.value.complement);

  append("nickname", stepThreeForm.value.nickname);
  append("instructions", stepThreeForm.value.instructions);
  append("city", stepThreeForm.value.city);
  append("state", stepThreeForm.value.state);
  appendCoordinate("latitude", stepThreeForm.value.latitude);
  appendCoordinate("longitude", stepThreeForm.value.longitude);
  append("address_type", stepThreeForm.value.address_type);

  append("daily_price_8h", Number(stepFiveForm.value.daily_price_8h));
  append("daily_price_6h", Number(stepFiveForm.value.daily_price_6h));
  append("daily_price_4h", Number(stepFiveForm.value.daily_price_4h));
  append("daily_price_2h", Number(stepFiveForm.value.daily_price_2h));

  (stepFiveForm.value.services_types_ids ?? []).forEach((id) => {
    form.append("services_types_ids[]", id);
  });

  workingDays.forEach((workingDay, index) => {
    form.append(`working_days[${index}][day]`, workingDay.day);
    form.append(`working_days[${index}][period]`, workingDay.period);
  });

  form.append("selfie", stepFourForm.value.selfie);
  form.append("document_front", stepFourForm.value.document_front);
  form.append("document_back", stepFourForm.value.document_back);

  append("recipient_name", stepThreeForm.value.name);
  append("recipient_email", stepThreeForm.value.email || email.value);
  append("recipient_document", stepThreeForm.value.document);
  append("recipient_type", "individual");

  const hasBankAccountData = [
    stepSixForm.value.bank,
    stepSixForm.value.branch_number,
    stepSixForm.value.account_number,
    stepSixForm.value.account_check_digit,
  ].every(hasValue);

  if (hasBankAccountData) {
    append("recipient_payment_mode", "bank_transfer");
    append(
      "recipient_default_bank_account[type]",
      stepSixForm.value.account_type,
    );

    append("recipient_default_bank_account[bank]", stepSixForm.value.bank);

    append(
      "recipient_default_bank_account[branch_number]",
      stepSixForm.value.branch_number,
    );

    appendIfFilled(
      "recipient_default_bank_account[branch_check_digit]",
      stepSixForm.value.branch_check_digit,
    );

    append(
      "recipient_default_bank_account[account_number]",
      stepSixForm.value.account_number,
    );

    append(
      "recipient_default_bank_account[account_check_digit]",
      stepSixForm.value.account_check_digit,
    );

    append(
      "recipient_default_bank_account[holder_name]",
      stepThreeForm.value.name,
    );

    append(
      "recipient_default_bank_account[holder_document]",
      stepThreeForm.value.document,
    );

    append("recipient_default_bank_account[holder_type]", "individual");
  }

  const response = await createUserAndProvider(form);

  if (response?.status >= 200 && response.status < 300) {
    await setAuthDataFromPayload(response.data.payload);

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

  return response;
};

const sendValidationCode = async () => {
  const response = await sendCode(email.value, phone.value);

  if (response.status === 201) {
    steps.value = 2;
  }

  return response;
};

const toISODate = (value) => {
  const matches = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(value || "");

  if (!matches) return null;

  return `${matches[3]}-${matches[2]}-${matches[1]}`;
};

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

  if (response.status === 200) {
    if (isLogin.value === true) {
      await setAuthDataFromPayload(response.data.payload);

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

      return;
    }

    stepThreeForm.value.email = email.value;
    stepThreeForm.value.phone = phone.value;

    await goToStep(3);
  }
};

const validateCurrentStep = async () => {
  const isValid = await loginForm.value?.validate();

  if (!isValid) return false;

  if (steps.value === 3 && !stepThreeForm.value.gender) {
    $q.notify({
      message: t("provider.login.steps.step_3.gender_required"),
      type: "negative",
    });

    return false;
  }

  if (steps.value === 4) {
    const hasDocumentBack = !!stepFourForm.value.document_back;
    const hasDocumentFront = !!stepFourForm.value.document_front;
    const hasSelfie = !!stepFourForm.value.selfie;

    if (!hasSelfie || !hasDocumentFront || !hasDocumentBack) {
      $q.notify({
        message: t("provider.login.steps.step_4.upload_all_photos"),
        type: "negative",
      });

      return false;
    }
  }

  if (steps.value === 6 && !hasWorkingDaySelected()) {
    $q.notify({
      message: t("provider.login.steps.step_6.select_at_least_one"),
      type: "negative",
    });

    return false;
  }

  return true;
};

onMounted(() => {
  loadServiceConfiguration();

  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;
    }
  }
}

.flow-screen {
  width: 100%;
  max-width: 500px;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  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;
  padding-left: max(4px, env(safe-area-inset-left));
}

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

.flow-logo {
  display: flex;
  justify-content: center;
  width: 100%;
  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);
}

</style>
