<template>
  <div
    v-if="show"
    class="bookaro-booking-modal"
    @click.self="close"
  >
    <div
      class="bookaro-booking-wrapper bookaro-reschedule-wrapper bookaro-card"
      :class="{ 'is-compact': isCompact, 'is-expanded': !isCompact }"
    >
      <div v-if="availLoading || saving" class="modal-loader">
        <div class="spinner"></div>
      </div>

      <button class="modal-close-button" @click="close">&times;</button>

      <div class="step-header">
        <h3 class="step-title">{{ modalTitle }}</h3>
      </div>

      <template v-if="!hasOutcome">
        <div class="bookaro-reschedule-summary">
          <div class="bookaro-reschedule-row">
            <span class="bookaro-reschedule-label">{{ i18n.service_name }}</span>
            <span class="bookaro-reschedule-value">
              {{ booking && booking.service_label ? booking.service_label : i18n.placeholder_dash }}
            </span>
          </div>
          <div class="bookaro-reschedule-row">
            <span class="bookaro-reschedule-label">{{ i18n.current_date }}</span>
            <span class="bookaro-reschedule-value">
              {{ formatDateRange(booking ? booking.booking_date : '', booking ? booking.booking_date_to : '') }}
            </span>
          </div>
          <div v-if="bookingStatusLabel" class="bookaro-reschedule-row">
            <span class="bookaro-reschedule-label">{{ i18n.action_status_label || 'Current status' }}</span>
            <span class="bookaro-reschedule-value">{{ bookingStatusLabel }}</span>
          </div>
        </div>

        <section
          v-if="showPolicy"
          class="bookaro-policy-panel"
          :class="{ 'is-blocked': !policy.allowed }"
        >
          <h4 class="details-section-title">{{ i18n.policy_status_title || i18n.policy_title || 'Action windows' }}</h4>
          <p v-if="policy.summary" class="bookaro-policy-summary">{{ policy.summary }}</p>
          <div v-if="policy.why" class="bookaro-policy-copy">
            <span class="bookaro-policy-copy__label">{{ i18n.policy_why_label || 'Why it matters' }}</span>
            <span>{{ policy.why }}</span>
          </div>
          <div v-if="policy.next" class="bookaro-policy-copy">
            <span class="bookaro-policy-copy__label">{{ i18n.policy_next_label || 'What to do next' }}</span>
            <span>{{ policy.next }}</span>
          </div>
        </section>

        <DateTimeStep
          v-if="policy.allowed"
          :i18n="i18n"
          :service_label="booking && booking.service_label ? booking.service_label : ''"
          :currentMonth="currentMonth"
          :monthDays="monthDays"
          :availability="availability"
          :availLoading="availLoading"
          :selected_date="selected_date"
          :selected_date_to="selected_date_to"
          :selected_time="selected_time"
          :available_times="available_times"
          :service_duration="service_duration"
          :error="error"
          :show-confirm="false"
          :compact="isCompact"
          @advance="handleAdvance"
        >
          <template #before-confirm>
            <div v-if="showRescheduleActions" class="reschedule-actions">
              <button
                @click="close"
                class="bookaro-btn bookaro-btn--outline"
                type="button"
              >
                {{ i18n.close }}
              </button>
              <button
                @click="submitReschedule"
                :disabled="saving || !ready"
                class="bookaro-btn bookaro-btn--primary"
                type="button"
              >
                <span v-if="saving">{{ i18n.saving }}</span>
                <span v-else>{{ i18n.reschedule_confirm || i18n.reschedule }}</span>
              </button>
            </div>
          </template>
        </DateTimeStep>

        <div v-else class="reschedule-actions">
          <button
            @click="close"
            class="bookaro-btn bookaro-btn--primary"
            type="button"
          >
            {{ i18n.action_close || i18n.close }}
          </button>
        </div>
      </template>

      <template v-else>
        <section class="bookaro-policy-panel is-success">
          <h4 class="details-section-title">{{ i18n.action_outcome_title || 'What changed' }}</h4>
          <p v-if="outcome.summary" class="bookaro-policy-summary">{{ outcome.summary }}</p>
          <ul v-if="outcome.details.length" class="details-policy-list">
            <li v-for="(line, idx) in outcome.details" :key="`reschedule-outcome-${idx}`">
              {{ line }}
            </li>
          </ul>
        </section>

        <div class="reschedule-actions">
          <button
            @click="close"
            class="bookaro-btn bookaro-btn--primary"
            type="button"
          >
            {{ i18n.action_done || i18n.close }}
          </button>
        </div>
      </template>
    </div>
  </div>
</template>

<script>
import $ from 'jquery';
import { restRequest } from '@bookaro-free/js/rest';
import { getActionPolicy, getOutcomeModel } from '@bookaro-free/utils/bookingPolicies.js';
import DateTimeStep from '../myListingBookingPopUp/DateTimeStep.vue';

export default {
  name: 'RescheduleModal',
  components: { DateTimeStep },
  props: {
    show: { type: Boolean, default: false },
    booking: { type: Object, default: null },
    i18n: { type: Object, default: () => ({}) }
  },
  data() {
    return {
      currentMonth: window.dayjs().startOf('month'),
      availability: {
        weekly: {},
        timeslots: [],
        exceptions: {},
        bookedSlots: {},
        available: {},
        slots: 1,
      },
      availLoading: false,
      selected_date: '',
      selected_date_to: '',
      selected_time: '',
      available_times: [],
      service_duration: 0,
      error: '',
      ready: false,
      saving: false,
      hasPickedDate: false,
      responsePayload: null
    };
  },
  computed: {
    monthDays() {
      const start = this.currentMonth.startOf('month').startOf('week');
      const end = this.currentMonth.endOf('month').endOf('week');
      const days = [];
      let cursor = start.clone();
      while (cursor.isBefore(end) || cursor.isSame(end, 'day')) {
        days.push(cursor.clone());
        cursor = cursor.add(1, 'day');
      }
      return days;
    }
    ,
    isDayInterval() {
      return Array.isArray(this.availability.timeslots) &&
        this.availability.timeslots.some(t => Number(t.interval_m) === 1440);
    },
    isCompact() {
      return !this.hasPickedDate || !this.selected_date;
    },
    showRescheduleActions() {
      if (this.availLoading) {
        return false;
      }
      if (this.isDayInterval) {
        return !this.isCompact && !!(this.selected_date && this.selected_date_to);
      }
      return !this.isCompact && Array.isArray(this.available_times) && this.available_times.length > 0;
    },
    policy() {
      return getActionPolicy(this.booking, 'reschedule');
    },
    showPolicy() {
      return !!(this.policy.summary || this.policy.why || this.policy.next);
    },
    outcome() {
      return getOutcomeModel(this.responsePayload);
    },
    hasOutcome() {
      return !!(this.outcome.title || this.outcome.summary || this.outcome.details.length);
    },
    modalTitle() {
      return this.hasOutcome
        ? (this.outcome.title || this.i18n.reschedule_title)
        : this.i18n.reschedule_title;
    },
    bookingStatusLabel() {
      const status = (this.booking?.policy_snapshot?.status_label || this.booking?.status || '').toString().trim();
      if (!status) {
        return '';
      }
      const normalized = status.toLowerCase();
      const map = {
        pending: this.i18n.status_pending || this.i18n.pending,
        approved: this.i18n.status_approved || this.i18n.approved,
        rejected: this.i18n.status_rejected || this.i18n.rejected,
        cancelled: this.i18n.status_cancelled || this.i18n.cancelled,
        completed: this.i18n.status_completed || this.i18n.completed,
        no_show: this.i18n.status_no_show || this.i18n.no_show
      };
      return map[normalized] || status;
    }
  },
  watch: {
    show(val) {
      if (val) {
        this.initialize();
      }
    },
    booking() {
      if (this.show) {
        this.initialize();
      }
    }
  },
  methods: {
    initialize() {
      if (!this.booking) {
        return;
      }
      this.error = '';
      this.ready = false;
      this.saving = false;
      this.hasPickedDate = false;
      this.responsePayload = null;
      this.service_duration = Number(this.booking.service_duration) || 0;

      const start = window.dayjs(this.booking.booking_date);
      this.selected_date = start.isValid() ? start.format('YYYY-MM-DD') : '';
      const timeFormat = this.i18n.time_format;
      this.selected_time = start.isValid() ? start.format(timeFormat) : '';

      const end = this.booking.booking_date_to
        ? window.dayjs(this.booking.booking_date_to)
        : null;
      this.selected_date_to = end && end.isValid() ? end.format('YYYY-MM-DD') : '';

      this.currentMonth = this.selected_date
        ? window.dayjs(this.selected_date).startOf('month')
        : window.dayjs().startOf('month');

      this.fetchAvailability();
      this.updateReady();
    },
    fetchAvailability() {
      if (!this.booking) {
        return;
      }
      if (!this.policy.allowed) {
        return;
      }
      this.availLoading = true;
      this.available_times = [];

      const from = window.dayjs().format('YYYY-MM-DD');
      let toDate = window.dayjs().add(3, 'month');
      const duration = Number(this.service_duration) || 0;
      if (duration > 0) {
        const extraDays = Math.max(0, Math.ceil(duration / 1440) - 1);
        if (extraDays > 0) {
          toDate = toDate.add(extraDays, 'day');
        }
      }
      const to = toDate.format('YYYY-MM-DD');
      const data = {
        from,
        to,
        exclude_booking_id: this.booking.id,
        listing_id: this.booking.listing_id
      };
      if (duration > 0) {
        data.duration = duration;
      }

      $.ajax({
        url: `${window.BookaroData.rest_url}bookaro/v1/provider/${this.booking.provider_id}/availability`,
        method: 'GET',
        data,
        beforeSend: (xhr) => {
          xhr.setRequestHeader('X-WP-Nonce', window.BookaroData.rest_nonce);
        }
      })
        .done((resp) => {
          // Bug 46: replace the whole `availability` object rather than
          // mutating its properties in place. The previous per-property
          // assignment didn't reliably propagate through to the
          // <DateTimeStep> child's :availability prop — the modal
          // received the response, but the calendar's isDateDisabled
          // kept reading the pre-fetch empty `available` map and marked
          // every day "unavailable". Forcing a new object reference
          // guarantees the prop binding re-runs and the child sees the
          // populated `available` keyed by date.
          this.availability = {
            weekly:      resp.weekly      || {},
            timeslots:   resp.timeslots   || [],
            exceptions:  resp.exceptions  || {},
            bookedSlots: resp.bookedSlots || {},
            available:   resp.available   || {},
            slots:       resp.slots ? parseInt(resp.slots, 10) : 1,
          };
          if (this.selected_date) {
            this.available_times = this.availability.available && this.availability.available[this.selected_date]
              ? this.availability.available[this.selected_date]
              : [];
          }
          this.updateReady();
        })
        .fail(() => {
          this.error = this.i18n.avail_load_error;
        })
        .always(() => {
          this.availLoading = false;
        });
    },
    handleAdvance(payload) {
      if (payload && Object.keys(payload).length > 0) {
        Object.keys(payload).forEach((key) => {
          this[key] = payload[key];
        });
        if (payload.selected_date || payload.selected_date_to) {
          this.hasPickedDate = true;
        }
        this.updateReady();
        return;
      }
      this.updateReady();
    },
    updateReady() {
      if (this.isDayInterval) {
        this.ready = !!(this.selected_date && this.selected_date_to);
        return;
      }
      this.ready = !!(this.selected_date && this.selected_time);
    },
    submitReschedule() {
      if (!this.booking) {
        return;
      }
      this.saving = true;
      this.error = '';

      const dateTime = this.selected_time
        ? `${this.selected_date} ${this.selected_time}`.trim()
        : this.selected_date;

      // Bug 48: selected_date_to is initialized from the original booking's
      // booking_date_to and only re-written by the day-interval range
      // picker. For a normal single-slot reschedule the user only picks a
      // new start date + time — selected_date_to stays at the old value
      // and we'd POST `{booking_date: new, booking_date_to: ORIGINAL}`.
      // The server currently saves us by recomputing the end from start +
      // service duration, but the request itself is wrong and a future
      // payload-sanitizer change could honor the stale field and corrupt
      // single-slot bookings into multi-day spans. Send booking_date_to
      // ONLY when this is a genuine day-interval range picked in this
      // session (isDayInterval AND start != end). Otherwise omit it and
      // let the server compute the end from start + duration.
      const payload = { booking_date: dateTime };
      if (
        this.isDayInterval &&
        this.selected_date_to &&
        this.selected_date_to !== this.selected_date
      ) {
        payload.booking_date_to = this.selected_date_to;
      }

      restRequest(`bookaro/v1/bookings/${this.booking.id}/reschedule`, {
        method: 'POST',
        data: payload
      })
        .then((response) => {
          this.responsePayload = response || {};
          this.$emit('rescheduled', response || {});
        })
        .catch((err) => {
          this.error = err?.message || this.i18n.generic_error;
        })
        .finally(() => {
          this.saving = false;
        });
    },
    close() {
      this.$emit('close');
    },
    formatDateRange(startStr, endStr) {
      if (!startStr) {
        return this.i18n.placeholder_dash;
      }
      const start = window.dayjs(startStr);
      const dateFormat = this.i18n.date_format;
      const dateTimeFormat = this.i18n.date_time_format;
      if (!endStr) {
        return start.format(dateTimeFormat);
      }
      const end = window.dayjs(endStr);
      const startLabel = start.format(dateFormat);
      const endLabel = end.format(dateFormat);
      return startLabel === endLabel
        ? start.format(dateTimeFormat)
        : `${startLabel} - ${endLabel}`;
    }
  }
};
</script>

<style scoped>
.bookaro-policy-panel {
  border: 1px solid var(--bookaro-booking-slot_border, #e5e7eb);
  border-radius: 16px;
  padding: 14px 16px;
  background: rgba(248, 250, 252, 0.9);
  display: grid;
  gap: 10px;
  margin-bottom: 16px;
}

.bookaro-policy-panel.is-blocked {
  border-color: rgba(220, 38, 38, 0.24);
  background: rgba(254, 242, 242, 0.92);
}

.bookaro-policy-panel.is-success {
  border-color: rgba(5, 150, 105, 0.24);
  background: rgba(236, 253, 245, 0.92);
}

.bookaro-policy-summary {
  margin: 0;
  font-weight: 600;
  color: #111827;
}

.bookaro-policy-copy {
  display: grid;
  gap: 4px;
  color: #374151;
  font-size: 0.92rem;
}

.bookaro-policy-copy__label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--bookaro-booking-secondary, #6b7280);
}

.bookaro-reschedule-summary {
  border: 1px solid var(--bookaro-booking-slot_border, #e5e7eb);
  border-radius: 16px;
  padding: 14px 16px;
  background: var(--bookaro-booking-modal_bg, #fff);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
  display: grid;
  gap: 8px;
  margin-bottom: 16px;
}

.bookaro-reschedule-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.9rem;
  color: #1f2937;
}

.bookaro-reschedule-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--bookaro-booking-secondary, #6b7280);
}

.bookaro-reschedule-value {
  font-weight: 600;
  color: #111827;
}

.reschedule-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
  width: 100%;
}

.reschedule-actions .bookaro-btn {
  width: 100%;
}

.bk-pr-clr {
  background: var(--bookaro-booking-accent);
}
</style>
