<template>
  <div class="space-y-2">
    <div class="relative">
      <UInput
        v-model="naturalInput"
        :placeholder="placeholder"
        :color="
          hasError && naturalInput.trim()
            ? 'error'
            : isValidParse && naturalInput.trim()
              ? 'success'
              : undefined
        "
        @input="parseNaturalInput"
        @blur="onBlur"
      >
        <template #trailing>
          <Icon
            v-if="isValidParse && naturalInput.trim()"
            name="heroicons:check-circle"
            class="w-5 h-5 text-candlelight-500"
          />
          <Icon
            v-else-if="hasError && naturalInput.trim()"
            name="heroicons:exclamation-circle"
            class="w-5 h-5 text-ember-500"
          />
        </template>
      </UInput>
    </div>

    <div
      v-if="parsedDate && isValidParse"
      class="text-sm text-candlelight-400 bg-candlelight-900/20 px-3 py-2 rounded-lg border border-candlelight-800"
    >
      <div class="flex items-center gap-2">
        <Icon name="heroicons:calendar" class="w-4 h-4" />
        <span>{{ formatParsedDate(parsedDate) }}</span>
      </div>
    </div>

    <div
      v-if="hasError && naturalInput.trim()"
      class="text-sm text-ember-400 bg-ember-900/20 px-3 py-2 rounded-lg border border-ember-800"
    >
      <div class="flex items-center gap-2">
        <Icon name="heroicons:exclamation-triangle" class="w-4 h-4" />
        <span>{{ errorMessage }}</span>
      </div>
    </div>

    <!-- Fallback datetime-local input -->
    <details class="text-sm">
      <summary class="cursor-pointer text-guild-400 hover:text-guild-100">
        Use traditional date picker
      </summary>
      <div class="mt-2">
        <UInput
          v-model="datetimeValue"
          type="datetime-local"
          @change="onDatetimeChange"
        />
      </div>
    </details>
  </div>
</template>

<script setup>
import * as chrono from "chrono-node";

const props = defineProps({
  modelValue: {
    type: String,
    default: "",
  },
  placeholder: {
    type: String,
    default: 'e.g., "tomorrow at 3pm", "next Friday at 9am", "in 2 hours"',
  },
  inputClass: {
    type: [String, Object],
    default: "",
  },
  required: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits(["update:modelValue"]);

const naturalInput = ref("");
const parsedDate = ref(null);
const isValidParse = ref(false);
const hasError = ref(false);
const errorMessage = ref("");
const datetimeValue = ref("");

// Initialize with current value
onMounted(() => {
  if (props.modelValue) {
    const date = new Date(props.modelValue);
    if (!isNaN(date.getTime())) {
      parsedDate.value = date;
      datetimeValue.value = formatForDatetimeLocal(date);
      isValidParse.value = true;
    }
  }
});

// Watch for external changes to modelValue
watch(
  () => props.modelValue,
  (newValue) => {
    if (newValue && newValue !== formatForDatetimeLocal(parsedDate.value)) {
      const date = new Date(newValue);
      if (!isNaN(date.getTime())) {
        parsedDate.value = date;
        datetimeValue.value = formatForDatetimeLocal(date);
        isValidParse.value = true;
        naturalInput.value = ""; // Clear natural input when set externally
      }
    } else if (!newValue) {
      reset();
    }
  },
);

const parseNaturalInput = () => {
  const input = naturalInput.value.trim();

  if (!input) {
    reset();
    return;
  }

  try {
    // Parse with chrono-node
    const results = chrono.parse(input);

    if (results.length > 0) {
      const result = results[0];
      const date = result.date();

      // Validate the parsed date
      if (date && !isNaN(date.getTime())) {
        parsedDate.value = date;
        isValidParse.value = true;
        hasError.value = false;
        datetimeValue.value = formatForDatetimeLocal(date);
        emit("update:modelValue", formatForDatetimeLocal(date));
      } else {
        setError("Could not parse this date format");
      }
    } else {
      setError(
        'Could not understand this date format. Try something like "tomorrow at 3pm" or "next Friday"',
      );
    }
  } catch (error) {
    setError("Error parsing date");
  }
};

const onBlur = () => {
  // If we have a valid parse but the input changed, try to parse again
  if (naturalInput.value.trim() && !isValidParse.value) {
    parseNaturalInput();
  }
};

const onDatetimeChange = () => {
  if (datetimeValue.value) {
    const date = new Date(datetimeValue.value);
    if (!isNaN(date.getTime())) {
      parsedDate.value = date;
      isValidParse.value = true;
      hasError.value = false;
      naturalInput.value = ""; // Clear natural input when using traditional picker
      emit("update:modelValue", datetimeValue.value);
    }
  } else {
    reset();
  }
};

const reset = () => {
  parsedDate.value = null;
  isValidParse.value = false;
  hasError.value = false;
  errorMessage.value = "";
  emit("update:modelValue", "");
};

const setError = (message) => {
  isValidParse.value = false;
  hasError.value = true;
  errorMessage.value = message;
  parsedDate.value = null;
};

const formatForDatetimeLocal = (date) => {
  if (!date) return "";
  // Format as YYYY-MM-DDTHH:MM for datetime-local input
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");
  return `${year}-${month}-${day}T${hours}:${minutes}`;
};

const formatParsedDate = (date) => {
  if (!date) return "";

  const now = new Date();
  const isToday = date.toDateString() === now.toDateString();
  const tomorrow = new Date(now);
  tomorrow.setDate(tomorrow.getDate() + 1);
  const isTomorrow = date.toDateString() === tomorrow.toDateString();

  const timeStr = date.toLocaleString("en-US", {
    hour: "numeric",
    minute: "2-digit",
    hour12: true,
  });

  if (isToday) {
    return `Today at ${timeStr}`;
  } else if (isTomorrow) {
    return `Tomorrow at ${timeStr}`;
  } else {
    return date.toLocaleString("en-US", {
      weekday: "long",
      year: "numeric",
      month: "long",
      day: "numeric",
      hour: "numeric",
      minute: "2-digit",
      hour12: true,
    });
  }
};
</script>
