<script setup>
import { computed, ref } from "vue";
import { Button } from "@/Components/ui/button";
import { RangeCalendar } from "@/Components/ui/range-calendar";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/Components/ui/popover";
import { cn } from "@/lib/utils";
import { CalendarIcon } from "lucide-vue-next";
import { format } from "date-fns";
import { sl } from "date-fns/locale";
import { CalendarDate } from "@internationalized/date";
import { DateFormatter, getLocalTimeZone } from "@internationalized/date";

const props = defineProps({
  modelValue: {
    type: [Object, null],
    default: null,
  },
  placeholder: {
    type: String,
    default: "Izberi datumski obseg",
  },
  format: {
    type: String,
    default: "dd.MM.yyyy",
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  id: {
    type: String,
    default: undefined,
  },
  error: {
    type: [String, Array],
    default: undefined,
  },
});

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

// Convert string dates to CalendarDate objects
const toCalendarDate = (val) => {
  if (!val) return null;
  if (val instanceof Date) {
    return new CalendarDate(
      val.getFullYear(),
      val.getMonth() + 1,
      val.getDate()
    );
  }
  if (typeof val === "string") {
    if (/^\d{4}-\d{2}-\d{2}$/.test(val)) {
      const [year, month, day] = val.split("-").map(Number);
      return new CalendarDate(year, month, day);
    }
    const dateObj = new Date(val);
    if (!isNaN(dateObj.getTime())) {
      return new CalendarDate(
        dateObj.getFullYear(),
        dateObj.getMonth() + 1,
        dateObj.getDate()
      );
    }
  }
  return null;
};

// Convert CalendarDate to ISO string (YYYY-MM-DD)
const fromCalendarDate = (calendarDate) => {
  if (!calendarDate) return null;
  return `${String(calendarDate.year).padStart(4, "0")}-${String(calendarDate.month).padStart(2, "0")}-${String(calendarDate.day).padStart(2, "0")}`;
};

// Convert ISO string range to DateRange (CalendarDate objects)
const toDateRange = (value) => {
  if (!value) return { start: null, end: null };
  const start = toCalendarDate(value.start);
  const end = toCalendarDate(value.end);
  // Always return an object, even if both are null
  return { start: start || null, end: end || null };
};

// Convert DateRange to ISO string range
const fromDateRange = (dateRange) => {
  if (!dateRange || (!dateRange.start && !dateRange.end)) return null;
  const start = fromCalendarDate(dateRange.start);
  const end = fromCalendarDate(dateRange.end);
  // Return null if both dates are null/empty
  if (!start && !end) return null;
  return {
    start: start || null,
    end: end || null,
  };
};

// Date formatter for display
const df = new DateFormatter("sl-SI", {
  dateStyle: "short",
});

const dateRange = computed({
  get: () => {
    const range = toDateRange(props.modelValue);
    // RangeCalendar expects an object with start and end, not null
    return range || { start: null, end: null };
  },
  set: (value) => {
    // Only emit if value has actual dates, otherwise emit null
    if (value && (value.start || value.end)) {
      const isoRange = fromDateRange(value);
      emit("update:modelValue", isoRange);
    } else {
      emit("update:modelValue", null);
    }
  },
});

// Format for display using DateRange (CalendarDate objects)
const formattedDateRange = computed(() => {
  const range = dateRange.value;
  if (!range || (!range.start && !range.end)) {
    return props.placeholder;
  }
  
  try {
    if (range.start && range.end) {
      // Use DateFormatter if available, otherwise fall back to date-fns
      try {
        const startStr = df.format(range.start.toDate(getLocalTimeZone()));
        const endStr = df.format(range.end.toDate(getLocalTimeZone()));
        return `${startStr} - ${endStr}`;
      } catch {
        // Fallback to date-fns
        const formatDate = (calendarDate) => {
          if (!calendarDate) return "";
          const dateObj = new Date(
            calendarDate.year,
            calendarDate.month - 1,
            calendarDate.day
          );
          const formatMap = {
            "dd.MM.yyyy": "dd.MM.yyyy",
            "yyyy-MM-dd": "yyyy-MM-dd",
          };
          const dateFormat = formatMap[props.format] || "dd.MM.yyyy";
          return format(dateObj, dateFormat, { locale: sl });
        };
        return `${formatDate(range.start)} - ${formatDate(range.end)}`;
      }
    }
    if (range.start) {
      try {
        return df.format(range.start.toDate(getLocalTimeZone()));
      } catch {
        const dateObj = new Date(
          range.start.year,
          range.start.month - 1,
          range.start.day
        );
        return format(dateObj, props.format || "dd.MM.yyyy", { locale: sl });
      }
    }
    if (range.end) {
      try {
        return df.format(range.end.toDate(getLocalTimeZone()));
      } catch {
        const dateObj = new Date(
          range.end.year,
          range.end.month - 1,
          range.end.day
        );
        return format(dateObj, props.format || "dd.MM.yyyy", { locale: sl });
      }
    }
    
    return props.placeholder;
  } catch {
    return props.placeholder;
  }
});

const open = ref(false);
</script>

<template>
  <Popover v-model:open="open">
    <PopoverTrigger as-child>
      <Button
        :id="id"
        variant="outline"
        :class="
          cn(
            'w-full justify-start text-left font-normal',
            (!props.modelValue?.start && !props.modelValue?.end) && 'text-muted-foreground',
            error && 'border-red-500 focus:border-red-500 focus:ring-red-500'
          )
        "
        :disabled="disabled"
      >
        <CalendarIcon class="mr-2 h-4 w-4" />
        <template v-if="dateRange?.start">
          <template v-if="dateRange.end">
            {{ formattedDateRange }}
          </template>
          <template v-else>
            {{ formattedDateRange }}
          </template>
        </template>
        <template v-else>
          {{ props.placeholder }}
        </template>
      </Button>
    </PopoverTrigger>
    <PopoverContent class="w-auto p-0" align="start">
      <RangeCalendar
        v-model="dateRange"
        :disabled="disabled"
        :initial-focus="true"
        :number-of-months="2"
      />
    </PopoverContent>
  </Popover>
  <p v-if="error" class="mt-1 text-sm text-red-600">
    {{ Array.isArray(error) ? error[0] : error }}
  </p>
</template>
