<template>
  <q-card-section class="no-padding">
    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("provider.login.steps.step_3.full_name") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.name"
      v-model="form.name"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      no-error-icon
      outlined
      rounded
      :error="!!serverErrors.name"
      :error-message="serverErrors.name"
      :placeholder="$t('provider.login.steps.step_3.full_name')"
      :rules="[inputRules.required]"
      @update:model-value="clearServerError('name')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.terms.phone") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.phone"
      v-model="form.phone"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      mask="(##) #####-####"
      no-error-icon
      outlined
      placeholder="(00) 00000-0000"
      rounded
      :error="!!serverErrors.phone"
      :error-message="serverErrors.phone"
      :rules="[inputRules.required]"
      @update:model-value="clearServerError('phone')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.terms.email") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.email"
      v-model="form.email"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      no-error-icon
      outlined
      placeholder="nome@email.com"
      readonly
      rounded
      type="email"
      :error="!!serverErrors.email"
      :error-message="serverErrors.email"
      :rules="[inputRules.required, inputRules.email]"
      @update:model-value="clearServerError('email')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("provider.login.steps.step_3.rg") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.rg"
      v-model="form.rg"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      mask="##.###.###-#"
      no-error-icon
      outlined
      placeholder="00.000.000-0"
      rounded
      type="tel"
      :error="!!serverErrors.rg"
      :error-message="serverErrors.rg"
      :rules="[inputRules.required, validateRG]"
      @update:model-value="clearServerError('rg')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.terms.cpf") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.document"
      v-model="form.document"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      mask="###.###.###-##"
      no-error-icon
      outlined
      placeholder="000.000.000-00"
      rounded
      type="tel"
      :error="!!serverErrors.document"
      :error-message="serverErrors.document"
      :rules="[inputRules.required, inputRules.cpf]"
      @update:model-value="clearServerError('document')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("provider.login.steps.step_3.birth_date") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.birth_date"
      v-model="form.birth_date"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      mask="##/##/####"
      no-error-icon
      outlined
      rounded
      :error="!!serverErrors.birth_date"
      :error-message="serverErrors.birth_date"
      :placeholder="$t('provider.login.steps.step_3.birth_date_placeholder')"
      :rules="[inputRules.required, validateBirthDate]"
      @update:model-value="clearServerError('birth_date')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.gender") }}
      </span>
    </div>

    <q-option-group
      :ref="fieldRefs.gender"
      v-model="form.gender"
      class="gender-options font12 q-mb-md q-mt-sm text-text"
      color="primary"
      type="radio"
      :options="translatedGenderOptions"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.terms.cep") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.zip_code"
      v-model="form.zip_code"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      mask="#####-###"
      no-error-icon
      outlined
      placeholder="00000-000"
      rounded
      type="tel"
      :error="!!serverErrors.zip_code"
      :error-message="serverErrors.zip_code"
      :loading="loadingCep"
      :rules="[inputRules.required, inputRules.cep]"
      @update:model-value="(val) => { clearServerError('zip_code'); onCepChange(val) }"
    />

    <q-btn
      class="full-width q-mb-md"
      color="primary-button"
      padding="8px 12px"
      rounded
      :label="$t('provider.login.steps.step_3.use_location')"
      :loading="loadingLocation"
      @click="useLocation"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.terms.address") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.address"
      v-model="form.address"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      no-error-icon
      outlined
      readonly
      rounded
      :error="!!serverErrors.address"
      :error-message="serverErrors.address"
      :placeholder="`${$t('common.terms.address')}...`"
      :rules="[inputRules.required]"
      @update:model-value="clearServerError('address')"
    />

    <div class="row q-col-gutter-sm">
      <div class="col-4">
        <div class="text-text">
          <span class="font12 fontbold">
            {{ $t("common.terms.address_number") }}
          </span>
        </div>

        <q-input
          :ref="fieldRefs.number"
          v-model="form.number"
          class="bg-surface q-mb-md q-mt-sm"
          hide-bottom-space
          input-class="font12 fontmedium text-text"
          lazy-rules
          no-error-icon
          outlined
          placeholder="0000"
          rounded
          :error="!!serverErrors.number"
          :error-message="serverErrors.number"
          :rules="[inputRules.required]"
          @update:model-value="clearServerError('number')"
        />
      </div>

      <div class="col-8">
        <div class="text-text">
          <span class="font12 fontbold">
            {{ $t("common.terms.district") }}
          </span>
        </div>

        <q-input
          :ref="fieldRefs.district"
          v-model="form.district"
          class="bg-surface q-mb-md q-mt-sm"
          hide-bottom-space
          input-class="font12 fontmedium text-text"
          lazy-rules
          no-error-icon
          outlined
          readonly
          rounded
          :error="!!serverErrors.district"
          :error-message="serverErrors.district"
          :placeholder="`${$t('common.terms.district')}...`"
          :rules="[inputRules.required]"
          @update:model-value="clearServerError('district')"
        />
      </div>
    </div>

    <div class="row q-col-gutter-sm">
      <div class="col-8">
        <div class="text-text">
          <span class="font12 fontbold">
            {{ $t("common.terms.city") }}
          </span>
        </div>

        <q-input
          :ref="fieldRefs.city"
          v-model="form.city"
          class="bg-surface q-mb-md q-mt-sm"
          hide-bottom-space
          input-class="font12 fontmedium text-text"
          lazy-rules
          no-error-icon
          outlined
          readonly
          rounded
          :error="!!serverErrors.city"
          :error-message="serverErrors.city"
          :rules="[inputRules.required]"
          @update:model-value="clearServerError('city')"
        />
      </div>

      <div class="col-4">
        <div class="text-text">
          <span class="font12 fontbold">
            {{ $t("common.terms.state") }}
          </span>
        </div>

        <q-input
          :ref="fieldRefs.state"
          v-model="form.state"
          class="bg-surface q-mb-md q-mt-sm"
          hide-bottom-space
          input-class="font12 fontmedium text-text"
          lazy-rules
          no-error-icon
          outlined
          readonly
          rounded
          :error="!!serverErrors.state"
          :error-message="serverErrors.state"
          :rules="[inputRules.required]"
          @update:model-value="clearServerError('state')"
        />
      </div>
    </div>

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("common.terms.complement") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.complement"
      v-model="form.complement"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      no-error-icon
      outlined
      rounded
      :error="!!serverErrors.complement"
      :error-message="serverErrors.complement"
      :placeholder="$t('provider.login.steps.step_3.complement_placeholder')"
      :rules="[inputRules.required]"
      @update:model-value="clearServerError('complement')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("provider.login.steps.step_3.address_nickname") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.nickname"
      v-model="form.nickname"
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      no-error-icon
      outlined
      rounded
      :error="!!serverErrors.nickname"
      :error-message="serverErrors.nickname"
      :placeholder="`${$t('common.ui.misc.example')}: Casa`"
      @update:model-value="clearServerError('nickname')"
    />

    <div class="text-text">
      <span class="font12 fontbold">
        {{ $t("provider.login.steps.step_3.address_instructions") }}
      </span>
    </div>

    <q-input
      :ref="fieldRefs.instructions"
      v-model="form.instructions"
      autogrow
      class="bg-surface q-mb-md q-mt-sm"
      hide-bottom-space
      input-class="font12 fontmedium text-text"
      lazy-rules
      no-error-icon
      outlined
      rounded
      rows="3"
      type="textarea"
      :error="!!serverErrors.instructions"
      :error-message="serverErrors.instructions"
      @update:model-value="clearServerError('instructions')"
    />

    <div :ref="fieldRefs.address_type" class="row q-gutter-sm q-mt-xs">
      <q-chip
        v-for="type in addressTypes"
        :key="type.value"
        :icon="type.icon"
        :icon-selected="type.icon"
        :outline="form.address_type !== type.value"
        :selected="form.address_type === type.value"
        clickable
        color="primary"
        text-color="surface"
        @click="form.address_type = type.value"
      >
        {{ $t(type.label) }}
      </q-chip>
    </div>
  </q-card-section>
</template>

<script setup>
import axios from "axios";
import { computed, inject, ref } from "vue";
import { genderOptions } from "src/helpers/genderOptions";
import { useGeolocation } from "src/composables/useGeolocation";
import { useI18n } from "vue-i18n";
import { useInputRules } from "src/composables/useInputRules";
import { useQuasar } from "quasar";

import LocationMapDialog from "src/components/shared/LocationMapDialog.vue";

const form = defineModel({
  required: true,
  type: Object,
});

const { requestPermission, getCurrentPosition } = useGeolocation();
const { inputRules } = useInputRules();
const { t } = useI18n();

const $q = useQuasar();

const loadingCep = ref(false);
const loadingLocation = ref(false);

const serverErrors = inject("serverErrors", ref({}));
const clearServerError = inject("clearServerError", () => {});

const fieldRefs = {
  address: ref(null),
  birth_date: ref(null),
  city: ref(null),
  complement: ref(null),
  district: ref(null),
  document: ref(null),
  email: ref(null),
  gender: ref(null),
  instructions: ref(null),
  name: ref(null),
  nickname: ref(null),
  number: ref(null),
  phone: ref(null),
  rg: ref(null),
  state: ref(null),
  zip_code: ref(null),
  address_type: ref(null),
};

defineExpose({
  getFieldRef: (field) => fieldRefs[field],
});

const translatedGenderOptions = computed(() =>
  genderOptions.map((option) => ({
    ...option,
    label: t(option.label),
  })),
);

const addressTypes = [
  {
    icon: "mdi-home-outline",
    label: "provider.login.steps.step_3.address_type_home",
    value: "home",
  },
  {
    icon: "mdi-briefcase-variant-outline",
    label: "provider.login.steps.step_3.address_type_commercial",
    value: "commercial",
  },
  {
    icon: "mdi-map-marker-outline",
    label: "provider.login.steps.step_3.address_type_other",
    value: "other",
  },
];

const clearCepFields = () => {
  form.value.address = "";
  form.value.district = "";
  form.value.city = "";
  form.value.state = "";
  form.value.latitude = null;
  form.value.longitude = null;
};

const fetchCep = async (rawCep) => {
  const cleaned = rawCep.replace(/\D/g, "");

  if (cleaned.length !== 8) {
    return;
  }

  loadingCep.value = true;

  try {
    const { data } = await axios.get(
      `https://viacep.com.br/ws/${cleaned}/json/`,
    );

    if (!data.erro) {
      fillAddressFields({
        address: data.logradouro,
        district: data.bairro,
        city: data.localidade,
        state: data.uf,
      });
    } else {
      clearCepFields();
    }
  } catch {
    clearCepFields();
  } finally {
    loadingCep.value = false;
  }
};

const fillAddressFields = (data) => {
  const hasField = (field) => Object.prototype.hasOwnProperty.call(data, field);

  form.value.address = data.address ?? "";
  form.value.number = data.number || form.value.number || "";
  form.value.district = data.district ?? "";
  form.value.city = data.city ?? "";
  form.value.state = data.state ?? "";
  form.value.zip_code = data.zip_code || form.value.zip_code || "";

  if (hasField("lat") || hasField("latitude")) {
    form.value.latitude = data.lat ?? data.latitude;
  }

  if (hasField("lng") || hasField("longitude")) {
    form.value.longitude = data.lng ?? data.longitude;
  }
};

const onCepChange = (value) => {
  const cleaned = value?.replace(/\D/g, "") || "";

  if (cleaned.length === 8) {
    form.value.latitude = null;
    form.value.longitude = null;
    fetchCep(value);
  } else {
    clearCepFields();
  }
};

const useLocation = async () => {
  loadingLocation.value = true;

  try {
    const granted = await requestPermission();

    if (!granted) {
      $q.notify({
        message: t("provider.login.steps.step_3.location_permission_denied"),
        type: "warning",
      });

      return;
    }

    const position = await getCurrentPosition();

    $q.dialog({
      component: LocationMapDialog,
      componentProps: {
        initialLat: position.lat,
        initialLng: position.lng,
      },
    }).onOk((geoData) => {
      fillAddressFields(geoData);
      form.value.latitude = geoData.lat ?? geoData.latitude ?? position.lat;
      form.value.longitude = geoData.lng ?? geoData.longitude ?? position.lng;
    });
  } catch (err) {
    const isPermissionError =
      err?.code === 1 || err?.message?.toLowerCase().includes("denied");

    $q.notify({
      message: isPermissionError
        ? t("provider.login.steps.step_3.location_permission_denied")
        : t("provider.login.steps.step_3.location_error"),
      type: "warning",
    });
  } finally {
    loadingLocation.value = false;
  }
};

const validateBirthDate = (value) => {
  if (!value) {
    return t("validation.rules.required");
  }

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

  if (!matches) {
    return t("provider.login.steps.step_3.date_invalid");
  }

  const day = Number(matches[1]);
  const month = Number(matches[2]);
  const year = Number(matches[3]);

  const date = new Date(year, month - 1, day);

  const isValidDate =
    date.getFullYear() === year &&
    date.getMonth() === month - 1 &&
    date.getDate() === day;

  if (!isValidDate) {
    return t("provider.login.steps.step_3.date_invalid");
  }

  if (date > new Date()) {
    return t("provider.login.steps.step_3.date_invalid");
  }

  return true;
};

const validateRG = (value) => {
  const cleanedValue = value?.replace(/\D/g, "") || "";

  return (
    cleanedValue.length >= 8 || t("provider.login.steps.step_3.rg_invalid")
  );
};
</script>

<style lang="scss" scoped>
.gender-options {
  :deep(.q-radio) {
    margin-bottom: 4px;
  }

  :deep(.q-radio__inner--falsy) {
    color: rgba(0, 0, 0, 0.62);
  }
}
</style>
