<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-pb-sm bg-white shadow-profile bg-surface dialog-safe-header"
      >
        <q-btn
          v-close-popup
          color="primary"
          dense
          flat
          icon="mdi-chevron-left"
          round
        />

        <q-space />

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

        <q-space />

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

      <q-card-section class="col q-px-md q-py-lg">
        <div class="text-text">
          <div class="gradient-diarista font16 fontbold">
            {{ $t("profile.address.address_subtitle") }}
          </div>

          <div class="text-grey-7 q-mb-lg font12">
            {{ $t("profile.address.address_description") }}
          </div>

          <q-card
            class="q-pa-lg bg-white shadow-card"
            style="border-radius: 25px"
            :flat="false"
          >
            <q-input
              v-model="search"
              class="q-mb-md bg-white card-border"
              dense
              input-class="text-text"
              outlined
              :placeholder="$t('profile.address.search_placeholder')"
            >
              <template #append>
                <q-icon color="grey-7" name="mdi-magnify" />
              </template>
            </q-input>

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

            <div class="text-text q-mb-xs font14 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>

            <div class="q-mb-xs text-text font14 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 font14 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 font14 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 font14 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 font14 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 font14 fontbold">
                  {{ $t("profile.address.state_label") }}
                </div>

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

            <div v-if="missingCoords" class="q-mb-md">
              <q-banner class="bg-orange-1 text-warning q-mb-sm" 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 q-mb-md"
                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 16px"
              rounded
              unelevated
              :disable="!hasUpdatedFields"
              :label="$t('profile.address.update_address')"
              :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,
  getAddresses,
  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 { dialogRef, onDialogOK } = useDialogPluginComponent();
const { geocodeFullAddress } = useGeocodingApi();
const { requestPermission, getCurrentPosition } = useGeolocation();
const { t } = useI18n();
const $q = useQuasar();

const user = userStore();

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

const providerId = user.user.provider.id;

const { form, getUpdatedFields, hasUpdatedFields, setUpdateFormAsOriginal } =
  useFormUpdateTracker({
    address: "",
    address_type: "home",
    city: null,
    city_id: null,
    complement: "",
    district: "",
    latitude: null,
    longitude: null,
    number: "",
    source: "provider",
    source_id: providerId,
    state: null,
    state_id: null,
    zip_code: "",
  });

const missingCoords = computed(
  () =>
    addressId.value !== null &&
    (form.latitude == null || form.longitude == null),
);

const applyGeoData = async (geoData) => {
  form.latitude = geoData.lat;
  form.longitude = geoData.lng;
  form.address = geoData.address || form.address;
  form.number = geoData.number || form.number;
  form.district = geoData.district || form.district;

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

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

      if (addressData) {
        form.city_id = addressData.city_id;
        form.state_id = addressData.state_id;
        form.city = addressData.city;
        form.state = addressData.state;
      }
    } catch {
      // Mantém cidade/estado atual se o lookup falhar.
    }
  }
};

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

  loadingCep.value = true;

  try {
    const data = await searchAddressByCEP(value);

    if (data) {
      form.address = data.address;
      form.district = data.district;
      form.city_id = data.city_id;
      form.state_id = data.state_id;
      form.city = data.city;
      form.state = data.state;
      form.latitude = null;
      form.longitude = null;
    } else {
      $q.notify({
        message: "CEP não encontrado",
        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(
        "geocodeFullAddress falhou, usando coordenada default:",
        error,
      );
    } finally {
      geocodingCep.value = false;
    }
  }

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

  $q.dialog({
    component: LocationMapDialog,
    componentProps: dialogProps,
  }).onOk(applyGeoData);
};

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

  try {
    const granted = await requestPermission();

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

      return;
    }

    const position = await getCurrentPosition();

    $q.dialog({
      component: LocationMapDialog,
      componentProps: {
        initialLat: position.lat,
        initialLng: position.lng,
      },
    }).onOk(applyGeoData);
  } catch (error) {
    const isPermissionError =
      error?.code === 1 || error?.message?.toLowerCase().includes("denied");

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

//

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

  try {
    let response;

    if (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);
  } finally {
    saving.value = false;
  }
};

onMounted(async () => {
  const providersAddresses = await getAddresses("provider", providerId);

  if (providersAddresses && providersAddresses.length > 0) {
    const current = providersAddresses[0];

    addressId.value = current.id;

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

    Object.assign(form, initialData);

    setUpdateFormAsOriginal();
  }
});
</script>

<style scoped></style>
