<template>
  <div
    class="bookaro-booking-grid"
    :class="{ 'is-compact': compact, 'is-expanded': !compact }"
  >
    <div class="bookaro-booking-col bookaro-booking-col--calendar">
      <div class="step-header">
        <h3>
          {{ i18n.book_label }}
          <span v-if="service_label"> {{ service_label }}</span>
        </h3>
      </div>

      <!-- Month navigation -->
      <div class="month-nav cst_bk_n">
        <button
            @click="$emit('advance', { currentMonth: currentMonth.subtract(1, 'month') })"
        >
          {{ i18n.prev_month }}
        </button>
        <span>{{ monthLabel }}</span>
        <button
            @click="$emit('advance', { currentMonth: currentMonth.add(1, 'month') })"
        >
          {{ i18n.next_month }}
        </button>
      </div>

      <!-- Days of week headers -->
      <div class="month-grid">
        <div class="dow" v-for="d in i18n.weekdays_short" :key="d">{{ d }}</div>
        <button
            v-for="day in monthDays"
            :key="day.format('YYYY-MM-DD')"
            class="date-pill"
            :class="{
            today:       day.isSame(dayjs(), 'day'),
            selected:    isDateSelected(day),
            'range-start': isRangeStart(day),
            'range-end':   isRangeEnd(day),
            'in-range':    isInRange(day),
            unavailable: isDateDisabled(day),
            other:       !day.isSame(currentMonth, 'month')
          }"
            @click="onDateClick(day)"
        >
          {{ day.date() }}
          <div
              v-if="isDateSelected(day) && isDayInterval"
              class="slots-tooltip"
          >
            {{ slotsRemainingForDay(day) }} {{ i18n.available_slots_label }}
          </div>
        </button>
      </div>

      <slot name="after-calendar" />
    </div>

    <div class="bookaro-booking-col bookaro-booking-col--times">
      <div v-if="error" class="error">{{ error }}</div>

      <div
          v-if="isDayInterval && selected_date && !selected_date_to && !isFixedRange"
          class="range-hint"
      >
        {{ i18n.select_end_date }}
      </div>

      <!-- Available time slots -->
      <div v-if="available_times.length && !isDayInterval" class="slot-grid">
        <button
            v-for="t in available_times"
            :key="t"
            @click="onTimeClick(t)"
            :class="['slot-pill', { selected: selected_time === t }]"
        >
          {{ formatDisplayTime(t) }}
          <div v-if="selected_time === t" class="slots-tooltip">
            {{ slotsRemainingForTime(t) }} {{ i18n.available_slots_label }}
          </div>
        </button>
      </div>

      <slot name="before-confirm" />

      <div
          v-if="showConfirm && (isDayInterval ? (selected_date && selected_date_to) : (selected_date && selected_time))"
          class="bookaro-booking-actions"
      >
        <button
            @click="advanceStep()"
            class="bookaro-booking-btn bk-continue"
        >
          {{ i18n.confirm_time }}
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import dayjs from 'dayjs';

export default {
  name: 'DateTimeStep',
  props: {
    i18n:            { type: Object, required: true },
    service_label:   { type: String, required: true },
    currentMonth:    { type: Object, required: true }, // a dayjs instance
    monthDays:       { type: Array,  required: true }, // array of dayjs objects
    availability:    { type: Object, required: true },
    availLoading:    { type: Boolean, required: true },
    selected_date:   { type: String, required: true },
    selected_time:   { type: String, required: true },
    selected_date_to:{ type: String, required: true },
    available_times: { type: Array,  required: true },
    service_duration:{ type: [Number, String], required: false },
    error:           { type: String, required: false },
    showConfirm:     { type: Boolean, required: false, default: true },
    compact:         { type: Boolean, default: false }
  },
  computed: {
    dayjs() {
      return dayjs;
    },
    monthLabel() {
      const idx = this.currentMonth.month();
      const fullMonth = Array.isArray(this.i18n.months) ? this.i18n.months[idx] : '';
      const shortMonth = Array.isArray(this.i18n.months_short) ? this.i18n.months_short[idx] : '';
      const year = this.currentMonth.format('YYYY');
      const format = this.i18n.month_year_format || 'MMMM YYYY';
      let label = format;
      if (format.includes('MMMM')) {
        label = label.replace('MMMM', fullMonth || '');
      } else if (format.includes('MMM')) {
        label = label.replace('MMM', shortMonth || '');
      }
      label = label.replace('YYYY', year);
      return label.trim();
    },
    isDayInterval() {
      return Array.isArray(this.availability.timeslots) &&
        this.availability.timeslots.some(t => Number(t.interval_m) === 1440);
    },
    durationDays() {
      const duration = Number(this.service_duration) || 0;
      if (!this.isDayInterval || duration <= 0) {
        return 0;
      }
      return Math.max(1, Math.ceil(duration / 1440));
    },
    isFixedRange() {
      return this.isDayInterval && this.durationDays > 0;
    }
  },
  methods: {
    formatDisplayTime(timeStr) {
      const [h, m] = timeStr.split(':').map(Number);
      const hour = h % 12 === 0 ? 12 : h % 12;
      const minute = m < 10 ? '0' + m : m;
      const period = h < 12 ? (this.i18n.am) : (this.i18n.pm);
      return `${hour}:${minute} ${period}`;
    },
    slotsRemainingForDay(day) {
      if (this.isDateDisabled(day)) return 0;
      const capacity = Number(this.availability.slots) || 1;
      const ds = day.format('YYYY-MM-DD');
      const booked = this.availability.bookedSlots?.[ds] || [];
      const remaining = capacity - booked.length;
      return remaining > 0 ? remaining : 0;
    },
    slotsRemainingForTime(timeStr) {
      const capacity = Number(this.availability.slots) || 1;
      const booked = this.availability.bookedSlots?.[this.selected_date] || [];
      const count = booked.filter(t => t === timeStr).length;
      const remaining = capacity - count;
      return remaining > 0 ? remaining : 0;
    },
    isDateDisabled(day) {
      const dStr = day.format('YYYY-MM-DD');
      // a) past
      if (day.isBefore(this.dayjs(), 'day')) return true;
      // b) still loading
      if (this.availLoading) return true;
      if (this.isFixedRange && this.isInRange(day)) return false;
      // c) exception closed
      if (Number(this.availability.exceptions?.[dStr]) === 0) return true;
      // d) weekday not open
      if (Number(this.availability.weekly?.[day.day()]) === 0) return true;
      // e) no free slots
      const free = this.availability.available?.[dStr] || [];
      return free.length === 0;
    },

    // Verify that all days between start and end (inclusive) are available
    isSequentialRange(startDay, endDay) {
      if (endDay.isBefore(startDay, 'day')) return false;
      let current = startDay.add(1, 'day');
      while (current.isSame(endDay, 'day') || current.isBefore(endDay, 'day')) {
        if (this.isDateDisabled(current)) return false;
        current = current.add(1, 'day');
      }
      return true;
    },

    onDateClick(day) {
      if (this.isDateDisabled(day)) {
        this.$emit('advance', {
          selected_date: '',
          selected_date_to: '',
          selected_time: '',
          available_times: [],
          error: ''
        });
        return;
      }
      const ds   = day.format('YYYY-MM-DD');
      const free = this.availability.available?.[ds] || [];

      if (this.isDayInterval) {
        if (this.isFixedRange) {
          if (this.isDateDisabled(day)) {
            this.$emit('advance', {
              selected_date: '',
              selected_date_to: '',
              selected_time: '',
              available_times: [],
              error: ''
            });
            return;
          }
          const end = day.add(this.durationDays - 1, 'day');
          this.$emit('advance', {
            selected_date: ds,
            selected_date_to: end.format('YYYY-MM-DD'),
            selected_time: '',
            available_times: [],
            error: ''
          });
          return;
        }
        const start = this.selected_date ? this.dayjs(this.selected_date) : null;
        const end   = this.selected_date_to ? this.dayjs(this.selected_date_to) : null;

        // Start a fresh range if no start exists or user clicked before the start
        if (!start || day.isBefore(start, 'day')) {
          this.$emit('advance', {
            selected_date: ds,
            selected_date_to: '',
            selected_time: '',
            available_times: [],
            error: ''
          });
          return;
        }

        // Establish or extend the range without requiring individual clicks
        if (!end || day.isAfter(end, 'day')) {
          const rangeStart = end || start;

          if (!this.isSequentialRange(rangeStart, day)) {
            const unavailableMsg = this.i18n.range_unavailable;
            if (this.error === unavailableMsg) {
              this.$emit('advance', {
                selected_date: '',
                selected_date_to: '',
                selected_time: '',
                available_times: [],
                error: ''
              });
            } else {
              this.$emit('advance', { error: unavailableMsg });
            }
            return;
          }

          this.$emit('advance', { selected_date_to: ds, error: '' });
          return;
        }

        // If user clicks inside the current range, start a new range from that day
        this.$emit('advance', {
          selected_date: ds,
          selected_date_to: '',
          selected_time: '',
          available_times: [],
          error: ''
        });
      } else {
        this.$emit('advance', {
          selected_date:   ds,
          selected_time:   '',  // reset any prior time
          available_times: free,
          error:            free.length
              ? ''
              : (this.i18n.no_slots)
        });
      }
    },

    onTimeClick(timeStr) {
      // Emit selected_time to parent so parent.selected_time is set
      this.$emit('advance', { selected_time: timeStr });
    },

    isRangeStart(day) {
      return this.isDayInterval && this.selected_date &&
        day.isSame(this.dayjs(this.selected_date), 'day');
    },

    isRangeEnd(day) {
      return this.isDayInterval && this.selected_date_to &&
        day.isSame(this.dayjs(this.selected_date_to), 'day');
    },

    isDateSelected(day) {
      if (this.isDayInterval) {
        return this.isRangeStart(day) || this.isRangeEnd(day);
      }
      return this.selected_date &&
        day.isSame(this.dayjs(this.selected_date), 'day');
    },

    isInRange(day) {
      if (!this.isDayInterval || !this.selected_date || !this.selected_date_to) {
        return false;
      }
      const start = this.dayjs(this.selected_date);
      const end   = this.dayjs(this.selected_date_to);
      return day.isAfter(start, 'day') && day.isBefore(end, 'day');
    },

    advanceStep() {
      this.$emit('advance', {});
    }
  }
};
</script>

<style scoped>
/* copy over your .date-pill, .slot-pill, etc. from booking-base.css */
.range-hint {
  margin: 0.5rem 0;
}
.cst_bk_n > span,
.cst_bk_n > button {
  flex: 1;
}

.cst_bk_n > button:nth-child(1) {
  text-align: left;
}

.cst_bk_n > button:nth-child(3) {
   text-align: right;
}

.cst_bk_n > span:nth-child(2) {
  text-align: center;
}
</style>
