<template>
  <q-dialog ref="dialogRef" persistent maximized class="map-dialog-transparent" @show="initMap" @hide="onDialogHide">
    <div class="location-map-dialog">
      <div ref="mapRef" class="location-map-container" />

      <q-btn
        flat
        round
        color="white"
        icon="mdi-arrow-left"
        class="location-map-back-btn"
        @click="handleCancel"
      />

      <div class="location-map-bottom-card">
        <p class="font14 fontbold">{{ $t('common.terms.address') }}</p>
        <q-input
          :model-value="currentAddress"
          outlined
          dense
          readonly
          class="location-map-address-input q-mb-md"
          bg-color="white"
          input-class="text-text"
          :loading="reversing"
          :placeholder="reversing ? '' : $t('auth.geocoding_failed_short')"
        />
        <q-btn
          color="primary-button"
          :label="$t('auth.confirm_location')"
          rounded
          padding="14px 16px"
          class="full-width"
          :loading="reversing"
          :disable="!currentGeoData"
          @click="handleConfirm"
        />
      </div>
    </div>
  </q-dialog>
</template>

<script setup>
import { ref, nextTick, onUnmounted } from 'vue';
import { useDialogPluginComponent, useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { GoogleMap } from '@capacitor/google-maps';
import { useGeocodingApi } from 'src/composables/useGeocodingApi';

const props = defineProps({
  initialLat: {
    type: Number,
    default: -15.7801,
  },
  initialLng: {
    type: Number,
    default: -47.9292,
  },
});

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

const { dialogRef, onDialogOK, onDialogCancel } = useDialogPluginComponent();
const $q = useQuasar();
const { t } = useI18n();
const { reverseGeocode } = useGeocodingApi();

const mapRef = ref(null);
const reversing = ref(false);
const currentAddress = ref('');
const currentGeoData = ref(null);

let googleMap = null;
const markerId = ref(null);

let hiddenEls = [];

const applyMapTransparency = () => {
  document.documentElement.style.setProperty('background', 'transparent', 'important');
  document.body.style.setProperty('background', 'transparent', 'important');
  const qApp = document.getElementById('q-app');
  if (qApp) qApp.style.setProperty('background', 'transparent', 'important');

  hiddenEls = [];
  document
    .querySelectorAll('.q-layout, .q-dialog:not(.map-dialog-transparent)')
    .forEach((el) => {
      el.style.setProperty('visibility', 'hidden', 'important');
      hiddenEls.push(el);
    });
};

const removeMapTransparency = () => {
  document.documentElement.style.removeProperty('background');
  document.body.style.removeProperty('background');
  const qApp = document.getElementById('q-app');
  if (qApp) qApp.style.removeProperty('background');

  hiddenEls.forEach((el) => el.style.removeProperty('visibility'));
  hiddenEls = [];
};

const onDialogHide = () => {
  removeMapTransparency();
};

const handleCancel = async () => {
  removeMapTransparency();
  await destroyMap();
  onDialogCancel();
};

const handleConfirm = async () => {
  if (!currentGeoData.value) return;
  removeMapTransparency();
  await destroyMap();
  onDialogOK(currentGeoData.value);
};

const destroyMap = async () => {
  if (googleMap) {
    await googleMap.destroy();
    googleMap = null;
  }
};

const updateMarkerPosition = async (lat, lng) => {
  reversing.value = true;
  try {
    const geoData = await reverseGeocode(lat, lng);
    if (geoData) {
      currentGeoData.value = { ...geoData, lat, lng };
      const parts = [geoData.address, geoData.number, geoData.district, geoData.city, geoData.state].filter(Boolean);
      currentAddress.value = parts.join(', ');
    } else {
      currentGeoData.value = { lat, lng, address: '', number: '', district: '', city: '', state: '', zip_code: '' };
      currentAddress.value = '';
      $q.notify({ type: 'warning', message: t('auth.geocoding_failed') });
    }
  } catch {
    currentGeoData.value = { lat, lng, address: '', number: '', district: '', city: '', state: '', zip_code: '' };
    currentAddress.value = '';
    $q.notify({ type: 'warning', message: t('auth.geocoding_failed') });
  } finally {
    reversing.value = false;
  }
};

const moveMarkerTo = async (lat, lng) => {
  if (markerId.value) {
    await googleMap.removeMarker(markerId.value);
  }
  markerId.value = await googleMap.addMarker({
    coordinate: { lat, lng },
    draggable: true,
  });
};

const initMap = async () => {
  applyMapTransparency();
  await nextTick();
  await new Promise(resolve => setTimeout(resolve, 100));

  const apiKey = process.env.GOOGLE_MAPS_API_KEY;

  if (!apiKey) {
    $q.notify({ type: 'negative', message: 'API key do mapa não configurada.' });
    return;
  }

  try {
    googleMap = await GoogleMap.create({
      id: 'location-map-dialog',
      element: mapRef.value,
      apiKey,
      config: {
        center: { lat: props.initialLat, lng: props.initialLng },
        zoom: 17,
      },
    });
  } catch (err) {
    $q.notify({ type: 'negative', message: `Erro ao abrir o mapa: ${err?.message ?? err}` });
    return;
  }

  markerId.value = await googleMap.addMarker({
    coordinate: { lat: props.initialLat, lng: props.initialLng },
    draggable: true,
  });

  await updateMarkerPosition(props.initialLat, props.initialLng);

  await googleMap.setOnMarkerDragEndListener(async (event) => {
    const { latitude, longitude } = event;
    await updateMarkerPosition(latitude, longitude);
  });

  await googleMap.setOnMapClickListener(async (event) => {
    const { latitude, longitude } = event;
    await moveMarkerTo(latitude, longitude);
    await updateMarkerPosition(latitude, longitude);
  });
};

onUnmounted(async () => {
  removeMapTransparency();
  await destroyMap();
});
</script>

<style lang="scss">
.map-dialog-transparent .q-dialog__inner {
  background: transparent !important;
}
.map-dialog-transparent .q-dialog__backdrop {
  display: none !important;
}
</style>

<style lang="scss" scoped>
.location-map-dialog {
  position: relative;
  width: 100vw;
  height: 100dvh;
  overflow: hidden;
  background: transparent;
}

.location-map-container {
  width: 100%;
  height: 100%;
  background: transparent;
}

.location-map-back-btn {
  position: absolute;
  top: calc(16px + env(safe-area-inset-top));
  left: 16px;
  z-index: 10;
  background: rgba(0, 0, 0, 0.4);
  border-radius: 50%;
}

.location-map-bottom-card {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  background: white;
  border-radius: 24px 24px 0 0;
  padding: 20px 20px calc(20px + env(safe-area-inset-bottom));
  box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.12);
}

.location-map-address-label {
  color: var(--q-text);
  margin: 0 0 8px;
}

.location-map-address-input {
  border-radius: 8px;
}
</style>
