﻿<script setup>
import { ref, onMounted, onUnmounted, computed } from "vue";
import { v7 } from "uuid";
import { useClient } from "@/plugins/api.js";
import { useI18n } from 'vue-i18n';
import config from '@/config';
import { mdiCheckCircle, mdiCloseCircle } from '@mdi/js';

const props = defineProps({
  name: {
    required: true
  },
  creatorNameReservationId: {
    required: true
  },
  originalSlug: {
    type: String,
    default: null
  }
});

const emits = defineEmits([
  'update:name',
  'update:creatorNameReservationId'
]);

const name = ref(props.name);
const { t } = useI18n();

const isOperationPending = ref(false);
const reservationState = ref(null);
const validationError = ref('');

// Use the reservationId from props if provided, otherwise generate a new one
const reservationId = ref(props.creatorNameReservationId || v7());

// Check if the current name is the same as the original slug
const isCurrentSlug = computed(() => {
  return props.originalSlug && name.value === props.originalSlug;
});

// Base URL for display
const baseUrl = computed(() => `${config.baseUrl}/@`);

// Validation function for the slug
const validateSlug = (slug) => {
  if (!slug) {
    validationError.value = t('creator.name.errors.required');
    return false;
  }

  // Only allow letters, numbers, and hyphens
  const validSlugRegex = /^[a-zA-Z0-9-]+$/;
  if (!validSlugRegex.test(slug)) {
    validationError.value = t('creator.name.errors.invalid');
    return false;
  }

  validationError.value = '';
  return true;
};

// Ensure we emit the reservationId on mount if we generated a new one
onMounted(() => {
  if (!props.creatorNameReservationId) {
    emits('update:creatorNameReservationId', reservationId.value);
  }

  // If the name is the same as the original slug, set the reservation state to "reserved"
  if (isCurrentSlug.value) {
    reservationState.value = "reserved";
  }
});

// Request handling
let currentController = null;
let timeout = null;
let lastProcessedName = '';

const cancelCurrentRequest = () => {
  if (currentController) {
    currentController.abort();
    currentController = null;
  }
};

const handleInput = () => {
  clearTimeout(timeout);
  timeout = setTimeout(() => {
    const currentName = name.value;
    if (currentName === lastProcessedName) {
      return; // Skip if we've already processed this exact name
    }

    // Validate the slug
    if (!validateSlug(currentName)) {
      reservationState.value = "unavailable";
      return;
    }

    // If the name is the same as the original slug, set reservation state to "reserved"
    if (props.originalSlug && currentName === props.originalSlug) {
      reservationState.value = "reserved";
      lastProcessedName = currentName;
      emits('update:name', currentName);
      return;
    }

    checkNameAvailability(currentName);
  }, 200);
};

const client = useClient();
const checkNameAvailability = async (nameToCheck) => {
  if (!nameToCheck || nameToCheck.trim() === "") {
    reservationState.value = null;
    lastProcessedName = nameToCheck;
    return;
  }

  // Cancel any ongoing request
  cancelCurrentRequest();

  try {
    isOperationPending.value = true;
    reservationState.value = "loading";

    // Create a new request with cancellation token
    const controller = new AbortController();
    currentController = controller;

    await client.post(
      `/api/creators/@${encodeURIComponent(nameToCheck)}/reserve`,
      { reservationId: reservationId.value },
      { signal: controller.signal }
    );

    // Only process the response if this is still the current request
    if (currentController === controller) {
      reservationState.value = "reserved";
      lastProcessedName = nameToCheck;
      emits('update:name', nameToCheck);
    }
  } catch (error) {
    // Only process the error if this is still the current request and it's not an abort error
    if (currentController && error.name !== 'AbortError') {
      reservationState.value = "unavailable";
      lastProcessedName = nameToCheck;
    }
  } finally {
    if (currentController) {
      isOperationPending.value = false;
    }
  }
};

// Cleanup on component unmount
onUnmounted(() => {
  cancelCurrentRequest();
  clearTimeout(timeout);
});

</script>

<template>
  <v-text-field variant="outlined" :label="t('creator.name.label')" v-model="name" @input="handleInput"
    :error-messages="validationError">
    <template #prepend-inner>
      <span class="text-nowrap font-sans text-gray-400">{{ baseUrl }}</span>
    </template>

    <template #append-inner>
      <v-progress-circular v-if="reservationState === 'loading'" indeterminate size="24" width="3"
        color="grey"></v-progress-circular>

      <v-icon v-else-if="reservationState === 'reserved'" color="green" :icon="mdiCheckCircle" />
      <v-icon v-else-if="reservationState === 'unavailable'" color="red" :icon="mdiCloseCircle" />
    </template>
  </v-text-field>
</template>

<style scoped></style>

<i18n>
{
  "en": {
    "creator": {
      "name": {
        "label": "Your creator handle",
        "errors": {
          "required": "Creator handle is required",
          "invalid": "Only letters, numbers, and hyphens are allowed"
        }
      }
    }
  },
  "fr": {
    "creator": {
      "name": {
        "label": "Votre identifiant de créateur",
        "errors": {
          "required": "L'identifiant est requis",
          "invalid": "Seules les lettres, chiffres et tirets sont autorisés"
        }
      }
    }
  },
  "es": {
    "creator": {
      "name": {
        "label": "Tu identificador de creador",
        "errors": {
          "required": "El identificador es obligatorio",
          "invalid": "Solo se permiten letras, números y guiones"
        }
      }
    }
  }
}
</i18n>
