<template>
  <Stack gap="6">
    <PageHeader :title="t('profileAddresses.form.title')" />

    <Stack gap="4">
      <Input
        v-model="newAddress.name"
        :label="t('profileAddresses.form.name.label')"
        :placeholder="t('profileAddresses.form.name.placeholder')"
      />

      <!-- Address search with Mapbox -->
      <div class="form-control">
        <label class="label">
          <span class="label-text">{{ t('profileAddresses.form.address.label') }}</span>
        </label>
        <div ref="searchBoxContainer" class="w-full" />
        <input
          v-if="newAddress.address"
          type="hidden"
          :value="newAddress.address"
        />
      </div>

      <!-- Mapbox map for selecting coordinates -->
      <div class="form-control">
        <label class="label">
          <span class="label-text">{{ t('profileAddresses.form.mapLabel') }}</span>
        </label>
        <div class="h-80 rounded-lg overflow-hidden border border-base-300">
          <MapboxMap
            ref="mapComponentRef"
            :map-id="'address-picker'"
            style="width: 100%; height: 100%"
            :options="{
              style: 'mapbox://styles/mapbox/streets-v12',
              center: [newAddress.longitude || 37.6173, newAddress.latitude || 55.7558],
              zoom: 10
            }"
            @mb-click="onMapClick"
            @mb-created="onMapCreated"
          >
            <MapboxDefaultMarker
              v-if="newAddress.latitude && newAddress.longitude"
              :marker-id="'selected-location'"
              :lnglat="[newAddress.longitude, newAddress.latitude]"
              color="#3b82f6"
            />
          </MapboxMap>
        </div>
        <label class="label" v-if="newAddress.latitude && newAddress.longitude">
          <span class="label-text-alt text-success">
            {{ newAddress.latitude.toFixed(6) }}, {{ newAddress.longitude.toFixed(6) }}
          </span>
        </label>
      </div>

      <Stack direction="row" gap="3">
        <Button @click="createAddress" :disabled="isCreating || !newAddress.latitude">
          {{ isCreating ? t('profileAddresses.form.saving') : t('profileAddresses.form.save') }}
        </Button>
        <Button variant="outline" :as="NuxtLink" :to="localePath('/clientarea/addresses')">
          {{ t('common.cancel') }}
        </Button>
      </Stack>
    </Stack>
  </Stack>
</template>

<script setup lang="ts">
import { NuxtLink } from '#components'
import type { MapMouseEvent, Map as MapboxMapType } from 'mapbox-gl'

definePageMeta({
  middleware: ['auth-oidc']
})

const { mutate } = useGraphQL()
const { t } = useI18n()
const localePath = useLocalePath()
const config = useRuntimeConfig()

const isCreating = ref(false)
const searchBoxContainer = ref<HTMLElement | null>(null)
const mapInstance = ref<MapboxMapType | null>(null)
const searchBoxRef = ref<any>(null)

const newAddress = reactive({
  name: '',
  address: '',
  latitude: null as number | null,
  longitude: null as number | null,
  countryCode: null as string | null
})

const onMapCreated = (map: MapboxMapType) => {
  mapInstance.value = map
}

// Reverse geocode: get address by coordinates (local language)
const reverseGeocode = async (lat: number, lng: number): Promise<{ address: string | null; countryCode: string | null }> => {
  try {
    const token = config.public.mapboxAccessToken
    const response = await fetch(
      `https://api.mapbox.com/geocoding/v5/mapbox.places/${lng},${lat}.json?access_token=${token}`
    )
    const data = await response.json()
    const feature = data.features?.[0]
    if (!feature) return { address: null, countryCode: null }

    // Extract country code from context
    const countryContext = feature.context?.find((c: any) => c.id?.startsWith('country.'))
    const countryCode = countryContext?.short_code?.toUpperCase() || null

    return { address: feature.place_name, countryCode }
  } catch {
    return { address: null, countryCode: null }
  }
}

const onMapClick = async (event: MapMouseEvent) => {
  const lat = event.lngLat.lat
  const lng = event.lngLat.lng

  newAddress.latitude = lat
  newAddress.longitude = lng

  // Reverse geocode: load address by coordinates
  const result = await reverseGeocode(lat, lng)
  if (result.address) {
    newAddress.address = result.address
    newAddress.countryCode = result.countryCode
    // Update SearchBox input
    if (searchBoxRef.value) {
      searchBoxRef.value.value = result.address
    }
  }
}

// Initialize Mapbox SearchBox
onMounted(async () => {
  if (!searchBoxContainer.value) return

  const { MapboxSearchBox } = await import('@mapbox/search-js-web')

  const searchBox = new MapboxSearchBox()
  searchBox.accessToken = config.public.mapboxAccessToken as string
  searchBox.options = {
    // Without language: uses local country language
  }
  searchBox.placeholder = t('profileAddresses.form.address.placeholder')

  searchBox.addEventListener('retrieve', (event: any) => {
    const feature = event.detail.features?.[0]
    if (feature) {
      const [lng, lat] = feature.geometry.coordinates
      newAddress.address = feature.properties.full_address || feature.properties.name
      newAddress.latitude = lat
      newAddress.longitude = lng

      // Extract country code from context
      const countryContext = feature.properties.context?.country
      newAddress.countryCode = countryContext?.country_code?.toUpperCase() || null

      // Fly to selected location
      if (mapInstance.value) {
        mapInstance.value.flyTo({
          center: [lng, lat],
          zoom: 15
        })
      }
    }
  })

  searchBoxRef.value = searchBox
  searchBoxContainer.value.appendChild(searchBox as unknown as Node)
})

const createAddress = async () => {
  if (!newAddress.name || !newAddress.address || !newAddress.latitude) return

  isCreating.value = true
  try {
    const { CreateTeamAddressDocument } = await import('~/composables/graphql/team/teams-generated')
    const result = await mutate(CreateTeamAddressDocument, {
      input: {
        name: newAddress.name,
        address: newAddress.address,
        latitude: newAddress.latitude,
        longitude: newAddress.longitude,
        countryCode: newAddress.countryCode,
        isDefault: false
      }
    }, 'team', 'teams')

    if (result.createTeamAddress?.success) {
      // Address is created asynchronously via workflow
      // Redirect to list; address will appear after sync
      navigateTo(localePath('/clientarea/addresses'))
    } else {
      console.error('Failed to create address:', result.createTeamAddress?.message)
    }
  } catch (e) {
    console.error('Failed to create address', e)
  } finally {
    isCreating.value = false
  }
}
</script>

<style>
/* Mapbox SearchBox styling */
mapbox-search-box {
  width: 100%;
}

mapbox-search-box::part(input) {
  height: 3rem;
  padding: 0.5rem 1rem;
  font-size: 1rem;
  border: 1px solid oklch(var(--bc) / 0.2);
  border-radius: var(--rounded-btn, 0.5rem);
  background-color: oklch(var(--b1));
  color: oklch(var(--bc));
}

mapbox-search-box::part(input):focus {
  outline: 2px solid oklch(var(--p));
  outline-offset: 2px;
}

mapbox-search-box::part(results-list) {
  background-color: oklch(var(--b1));
  border: 1px solid oklch(var(--bc) / 0.2);
  border-radius: var(--rounded-btn, 0.5rem);
  margin-top: 0.25rem;
}

mapbox-search-box::part(result-item) {
  padding: 0.75rem 1rem;
  color: oklch(var(--bc));
}

mapbox-search-box::part(result-item):hover {
  background-color: oklch(var(--b2));
}
</style>
