<template>
  <q-dialog
    ref="dialogRef"
    maximized
    persistent
    transition-hide="slide-right"
    transition-show="slide-left"
  >
    <div class="bg-page full-height no-shadow">
      <div
        class="row items-center q-px-md q-pt-md q-pb-sm bg-white shadow-profile bg-surface"
      >
        <q-btn
          v-close-popup
          class="header-back-btn"
          color="primary"
          dense
          flat
          icon="mdi-chevron-left"
          round
        />

        <q-space />

        <span
          class="gradient-diarista text-subtitle1 text-primary font16 fontbold"
        >
          {{ $t("profile.address.title") }}
        </span>

        <q-space />

        <div style="width: 32px"></div>
      </div>

      <div class="col column q-px-lg q-pt-lg overflow-auto">
        <span class="gradient-diarista q-mb-xs font16 fontbold">
          {{
            isEditing
              ? $t("profile.address.edit_address")
              : $t("profile.address.add_new_address")
          }}
        </span>

        <span
          class="text-grey-7 q-mb-lg font12 fontregular"
          style="line-height: 1.3"
        >
          {{
            isEditing
              ? $t("profile.address.manage_addresses")
              : $t("profile.address.add_new_address_label")
          }}
        </span>
      </div>

      <q-card-section class="col">
        <div class="text-text">
          <q-card
            class="q-pa-lg bg-white shadow-card"
            style="border-radius: 25px"
            :flat="false"
          >
            <div class="text-text q-mb-xs font12 fontbold">
              {{ $t("profile.address.cep") }}
            </div>

            <q-input
              v-model="form.zip_code"
              class="q-mb-md"
              dense
              input-class="text-text"
              mask="#####-###"
              outlined
              placeholder="00000-000"
              unmasked-value
              @update:model-value="onCepChange"
            >
              <template #append>
                <q-spinner
                  v-if="loadingCep"
                  color="primary"
                  size="xs"
                />
              </template>
            </q-input>

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

            <div class="q-mb-xs text-text font12 fontbold">
              {{ $t("profile.address.address_label") }}
            </div>

            <q-input
              v-model="form.address"
              class="q-mb-md"
              dense
              input-class="text-text"
              outlined
              :placeholder="$t('profile.address.address_placeholder')"
            />

            <div class="row q-col-gutter-sm q-mb-md">
              <div class="col-4">
                <div class="q-mb-xs text-text font12 fontbold">
                  {{ $t("profile.address.number") }}
                </div>

                <q-input
                  v-model="form.number"
                  dense
                  input-class="text-text"
                  outlined
                  placeholder="0000"
                />
              </div>

              <div class="col-8">
                <div class="q-mb-xs text-text font12 fontbold">
                  {{ $t("profile.address.complement") }}
                </div>

                <q-input
                  v-model="form.complement"
                  dense
                  input-class="text-text"
                  outlined
                  :placeholder="$t('profile.address.complement_placeholder')"
                />
              </div>
            </div>

            <div class="q-mb-xs text-text font12 fontbold">
              {{ $t("profile.address.district_label") }}
            </div>

            <q-input
              v-model="form.district"
              class="q-mb-md"
              dense
              input-class="text-text"
              outlined
            />

            <div class="row q-col-gutter-sm q-mb-lg">
              <div class="col-8">
                <div class="q-mb-xs text-text font12 fontbold">
                  {{ $t("profile.address.city_label") }}
                </div>

                <q-input
                  dense
                  input-class="text-text"
                  outlined
                  readonly
                  :model-value="form.city?.name"
                />
              </div>

              <div class="col-4">
                <div class="q-mb-xs text-text font12 fontbold">
                  {{ $t("profile.address.state_label") }}
                </div>

                <q-input
                  dense
                  input-class="text-text"
                  outlined
                  readonly
                  :model-value="form.state?.name"
                />
              </div>
            </div>

            <div class="q-mb-lg">
              <div class="row q-gutter-sm">
                <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>
            </div>

            <div
              v-if="missingCoords"
              class="q-mb-md"
            >
              <q-banner
                class="bg-orange-1 text-orange-9 q-mb-xl"
                dense
                rounded
              >
                <template #avatar>
                  <q-icon
                    color="orange-7"
                    name="mdi-map-marker-off"
                  />
                </template>

                {{ $t("profile.address.missing_coords") }}
              </q-banner>

              <q-btn
                class="full-width"
                color="primary"
                icon="mdi-map-marker"
                no-caps
                outline
                rounded
                unelevated
                :label="$t('profile.address.update_on_map')"
                :loading="geocodingCep"
                @click="openMapDialog"
              />
            </div>

            <q-btn
              class="full-width q-py-md"
              color="primary"
              no-caps
              padding="8px 12px"
              rounded
              unelevated
              :disable="!hasUpdatedFields"
              :label="$t('common.actions.save')"
              :loading="saving"
              @click="save"
            />
          </q-card>
        </div>

        <div class="q-pb-xl"></div>
      </q-card-section>
    </div>
  </q-dialog>
</template>

<script setup>
import { computed, onMounted, ref } from "vue";

import {
  createAddress,
  searchAddressByCEP,
  updateAddress,
} from "src/api/address";

import { useDialogPluginComponent, useQuasar } from "quasar";
import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
import { useGeocodingApi } from "src/composables/useGeocodingApi";
import { useGeolocation } from "src/composables/useGeolocation";
import { useI18n } from "vue-i18n";
import { userStore } from "src/stores/user";

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

defineEmits([...useDialogPluginComponent.emits]);

const props = defineProps({
  addressData: {
    default: null,
    type: Object,
  },
  isEditing: {
    default: false,
    type: Boolean,
  },
});

const $q = useQuasar();
const { t } = useI18n();
const { dialogRef, onDialogOK } = useDialogPluginComponent();
const { geocodeFullAddress } = useGeocodingApi();
const { getCurrentPosition, requestPermission } = useGeolocation();

const user = userStore();

const addressId = ref(null);
const geocodingCep = ref(false);
const loadingCep = ref(false);
const loadingLocation = ref(false);
const saving = ref(false);

const missingCoords = computed(
  () =>
    props.isEditing &&
    form.latitude == null &&
    form.longitude == null,
);

const clientId = user.user.client.id;

const initialFormData = {
  address: "",
  address_type: "home",
  city: null,
  city_id: null,
  complement: "",
  district: "",
  latitude: null,
  longitude: null,
  number: "",
  source: "client",
  source_id: clientId,
  state: null,
  state_id: null,
  zip_code: "",
};

const {
  form,
  getUpdatedFields,
  hasUpdatedFields,
  setUpdateFormAsOriginal,
} = useFormUpdateTracker(initialFormData);

const addressTypes = [
  {
    icon: "mdi-home-outline",
    label: "profile.address.type.home",
    value: "home",
  },
  {
    icon: "mdi-briefcase-variant-outline",
    label: "profile.address.type.commercial",
    value: "commercial",
  },
  {
    icon: "mdi-map-marker-outline",
    label: "profile.address.type.other",
    value: "other",
  },
];

const onCepChange = async (val) => {
  if (val?.length !== 8) {
    return;
  }

  loadingCep.value = true;

  try {
    const data = await searchAddressByCEP(val);

    if (data) {
      form.address = data.address;
      form.city = data.city;
      form.city_id = data.city_id;
      form.district = data.district;
      form.latitude = null;
      form.longitude = null;
      form.state = data.state;
      form.state_id = data.state_id;
    } else {
      $q.notify({
        message: t("profile.address.cep_not_found"),
        type: "negative",
      });
    }
  } finally {
    loadingCep.value = false;
  }
};

const openMapDialog = async () => {
  let initialLat = null;
  let initialLng = null;

  const hasAddress = form.address || form.zip_code;

  if (hasAddress) {
    geocodingCep.value = true;

    try {
      const geo = await geocodeFullAddress({
        address: form.address,
        city: form.city?.name,
        district: form.district,
        number: form.number,
        state: form.state?.name,
        zip_code: form.zip_code,
      });

      if (geo) {
        initialLat = geo.lat;
        initialLng = geo.lng;
      }
    } catch (error) {
      console.error("Failed to geocode address", error);
    } finally {
      geocodingCep.value = false;
    }
  }

  const dialogProps =
    initialLat !== null
      ? {
          initialLat,
          initialLng,
        }
      : {};

  showMapDialog(dialogProps);
};

const showMapDialog = (dialogProps = {}) => {
  $q.dialog({
    component: LocationMapDialog,
    componentProps: dialogProps,
  }).onOk(async (geoData) => {
    form.address = geoData.address || form.address;
    form.district = geoData.district || form.district;
    form.latitude = geoData.lat;
    form.longitude = geoData.lng;
    form.number = geoData.number || form.number;

    if (!geoData.zip_code) {
      return;
    }

    form.zip_code = geoData.zip_code.replace(/\D/g, "");

    try {
      const addressData = await searchAddressByCEP(form.zip_code);

      if (addressData) {
        form.city = addressData.city;
        form.city_id = addressData.city_id;
        form.state = addressData.state;
        form.state_id = addressData.state_id;
      }
    } catch {
      // Mantém cidade e estado atuais caso a busca falhe.
    }
  });
};

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

  try {
    const granted = await requestPermission();

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

      return;
    }

    const position = await getCurrentPosition();

    showMapDialog({
      initialLat: position.lat,
      initialLng: position.lng,
    });
  } catch (err) {
    const isPermissionError =
      err?.code === 1 ||
      err?.message?.toLowerCase().includes("denied");

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

//

const save = async () => {
  saving.value = true;

  try {
    let response;

    if (props.isEditing && addressId.value) {
      response = await updateAddress(
        getUpdatedFields.value,
        addressId.value,
      );
    } else {
      response = await createAddress({ ...form });
    }

    if (response) {
      setUpdateFormAsOriginal();
      onDialogOK(response);
    }
  } catch (error) {
    console.error("Erro ao salvar endereço:", error);

    $q.notify({
      message: t("profile.address.error_saving"),
      type: "negative",
    });
  } finally {
    saving.value = false;
  }
};

onMounted(() => {
  if (!props.isEditing || !props.addressData) {
    return;
  }

  addressId.value = props.addressData.id;

  const initialData = {
    address: props.addressData.address || "",
    address_type: props.addressData.address_type || "home",
    city: props.addressData.city || null,
    city_id: props.addressData.city_id || null,
    complement: props.addressData.complement || "",
    district: props.addressData.district || "",
    latitude: props.addressData.latitude ?? null,
    longitude: props.addressData.longitude ?? null,
    number: props.addressData.number || "",
    source: "client",
    source_id: clientId,
    state: props.addressData.state || null,
    state_id: props.addressData.state_id || null,
    zip_code: props.addressData.zip_code || "",
  };

  Object.assign(form, initialData);

  setUpdateFormAsOriginal();
});
</script>
