<template>
  <q-dialog ref="dialogRef" maximized transition-show="slide-up" transition-hide="slide-down">
    <div class="dialog-root">

      <div class="dialog-header row items-center q-px-md q-pt-md q-pb-sm bg-white">
        <q-btn v-close-popup flat round dense icon="mdi-chevron-left" color="primary" />
        <div class="col text-center text-subtitle1 text-weight-bold text-primary">
          {{ $t('scheduling_page.title') }}
        </div>
        <div style="width: 36px" />
      </div>

      <div class="dialog-body">

        <div class="q-px-md q-pt-md">
          <div class="info-banner card-border q-pa-md">
            <div class="text-body2 text-weight-medium text-primary">
              {{ $t('scheduling_page.order_summary.info_text') }}
            </div>
            <div class="text-caption text-primary q-mt-xs" style="opacity: 0.75;">
              {{ $t('scheduling_page.order_summary.info_note') }}
            </div>
          </div>
        </div>

        <div class="q-px-md q-pt-md">
          <div class="text-h6 text-weight-bold gradient-diarista q-mb-sm">
            {{ $t('scheduling_page.order_summary.title') }}
          </div>

          <q-card
            v-for="(booking, idx) in bookings"
            :key="idx"
            :flat="false"
            class="card-border bg-surface q-mb-sm shadow-card"
          >
            <q-card-section class="q-pa-md row items-center no-wrap">
              <div class="col">
                <div class="text-body2 text-text">
                  <span class="text-weight-bold">{{ $t('scheduling_page.order_summary.service_label') }}</span>
                  <span class="text-weight-bold">{{ ` ${booking.serviceType.label} (${booking.serviceType.hours})` }}</span>
                </div>
                <div class="text-body2 text-weight-bold text-text">{{ formatDate(booking.date) }}</div>
                <div class="text-body2 text-text">
                  {{ $t('scheduling_page.order_summary.time_range', { start: booking.slot.startHour, end: booking.slot.endHour }) }}
                </div>
              </div>
              <q-btn
                flat round dense
                icon="mdi-minus-circle-outline"
                color="grey-5"
                @click="confirmRemove(idx)"
              />
            </q-card-section>
          </q-card>

          <q-btn
            unelevated rounded no-caps
            :label="$t('scheduling_page.order_summary.send_btn')"
            color="secondary"
            class="full-width q-mt-sm"
            @click="submitOrder"
          />

          <q-btn
            outline rounded no-caps
            :label="$t('scheduling_page.order_summary.add_date_btn')"
            color="primary"
            class="full-width q-mt-xs"
            :disable="showCalendar"
            @click="showCalendar = true"
          />
        </div>

        <div v-if="showCalendar" class="q-px-md q-pt-lg q-pb-xl">
          <div v-if="loadingAvailability" class="row items-center justify-center q-py-lg">
            <q-spinner-dots color="primary" size="36px" />
          </div>
          <div v-else class="calendar-wrapper shadow-card">
            <q-date
              v-model="addDateValue"
              square
              class="full-width"
              :first-day-of-week="0"
              :options="dateOptions"
              minimal
              @update:model-value="onAddDateSelected"
            />
          </div>
        </div>
      </div>
    </div>
  </q-dialog>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import { useDialogPluginComponent, useQuasar } from 'quasar';
import { date } from 'quasar';
import { useI18n } from 'vue-i18n';
import { getProviderWorkingDays, getProviderBlockedDays } from 'src/api/providerAvailability';
import { getAddresses } from 'src/api/address';
import { createSchedule, getClientProviderBlocks } from 'src/api/schedule';
import { userStore } from 'src/stores/user';
import ServiceSelectionSheet from './ServiceSelectionSheet.vue';
import ServiceTimeSelectionDialog from './ServiceTimeSelectionDialog.vue';
import { useRouter } from 'vue-router';

const props = defineProps({
  provider:       { type: Object, required: true },
  initialBooking: { type: Object, required: true },
});

defineEmits([...useDialogPluginComponent.emits]);

const { dialogRef, onDialogOK } = useDialogPluginComponent();
const $q = useQuasar();
const { t, locale } = useI18n();
const store = userStore();

const bookings = ref([props.initialBooking]);
const submitting = ref(false);
const primaryAddress = ref(null);
const router = useRouter();
const showCalendar = ref(false);
const addDateValue = ref(null);
const loadingAvailability = ref(false);
const workingDays = ref([]);
const blockedDays = ref([]);
const providerClientBlocks = ref({
  existing_schedules: [],
  fully_blocked_weeks: [],
});

const normalizeDate = (d) => d.replace(/\//g, '-');

const getWeekStart = (dateStr) => {
  const d = new Date(normalizeDate(dateStr) + 'T12:00:00');
  d.setDate(d.getDate() - d.getDay());
  return d.toISOString().slice(0, 10);
};

const blockedWeekStartSet = computed(() =>
  new Set(providerClientBlocks.value.fully_blocked_weeks ?? [])
);

const getServerWeekCount = (newDateStr) => {
  const newWeek = getWeekStart(newDateStr);
  return (providerClientBlocks.value.existing_schedules ?? []).filter(
    (schedule) => getWeekStart(schedule.date) === newWeek
  ).length;
};

const getLocalWeekCount = (newDateStr) => {
  const newWeek = getWeekStart(newDateStr);
  return bookings.value.filter((booking) => getWeekStart(booking.date) === newWeek).length;
};

const wouldExceedWeekLimit = (newDateStr) => {
  const count = getServerWeekCount(newDateStr) + getLocalWeekCount(newDateStr);
  return count >= 2;
};

const availableWeekDays = computed(() =>
  [...new Set(workingDays.value.map(wd => wd.day))]
);

const blockedDateSet = computed(() =>
  new Set(blockedDays.value.filter(bd => bd.period === 'all').map(bd => bd.date))
);

const dateOptions = (d) => {
  const today = date.formatDate(new Date(), 'YYYY/MM/DD');
  if (d < today) return false;
  if (wouldExceedWeekLimit(d)) return false;
  const raw = normalizeDate(d);
  const parsed = new Date(`${raw}T12:00:00`);
  const dayOfWeek = parsed.getDay();
  const isWorking = availableWeekDays.value.includes(dayOfWeek);
  const isBlocked = blockedDateSet.value.has(raw);
  const isWeekBlocked = blockedWeekStartSet.value.has(getWeekStart(raw));
  return isWorking && !isBlocked && !isWeekBlocked;
};

const loadAvailability = async () => {
  loadingAvailability.value = true;
  try {
    const clientId = store.user?.client_id;
    const defaultClientBlocks = { existing_schedules: [], fully_blocked_weeks: [] };

    const [wd, bd, clientBlocks] = await Promise.all([
      getProviderWorkingDays(props.provider.provider_id),
      getProviderBlockedDays(props.provider.provider_id),
      clientId
        ? getClientProviderBlocks(clientId, props.provider.provider_id)
        : Promise.resolve(defaultClientBlocks),
    ]);
    workingDays.value = wd ?? [];
    blockedDays.value = bd ?? [];
    providerClientBlocks.value = clientBlocks ?? defaultClientBlocks;
  } catch {
    workingDays.value = [];
    blockedDays.value = [];
    providerClientBlocks.value = { existing_schedules: [], fully_blocked_weeks: [] };
  } finally {
    loadingAvailability.value = false;
  }
};

const loadPrimaryAddress = async () => {
  try {
    const clientId = store.user?.client_id;
    if (!clientId) return;
    const addresses = await getAddresses('client', clientId);
    primaryAddress.value = (addresses ?? []).find(a => a.is_primary) ?? null;
  } catch {
    primaryAddress.value = null;
  }
};

onMounted(() => Promise.all([loadAvailability(), loadPrimaryAddress()]));

const formatHour = (h) => `${String(h).padStart(2, '0')}:00`;

const onAddDateSelected = (val) => {
  if (!val) return;
  addDateValue.value = null;
  const valFormatted = normalizeDate(val);

  const blocksOfDate = blockedDays.value.filter(
    bd => bd.date === valFormatted && bd.period !== 'all'
  );

  const dayOfWeek = new Date(`${valFormatted}T12:00:00`).getDay();
  const dayPeriods = workingDays.value
    .filter(wd => wd.day === dayOfWeek)
    .map(wd => wd.period);

  const workingDayBlocks = [];
  if (!dayPeriods.includes('afternoon')) {
    workingDayBlocks.push({ init_hour: '14:00:00', end_hour: '20:00:00' });
  }
  if (!dayPeriods.includes('morning')) {
    workingDayBlocks.push({ init_hour: '7:00:00', end_hour: '13:00:00' });
  }

  const existingBookingBlocks = bookings.value
    .filter(b => b.date.replace(/\//g, '-') === valFormatted)
    .map(b => ({
      init_hour: `${b.slot.startHour}:00:00`,
      end_hour:  `${b.slot.endHour}:00:00`,
    }));

  const serverBookingBlocks = (providerClientBlocks.value.existing_schedules ?? [])
    .filter((schedule) => schedule.date === valFormatted)
    .map((schedule) => ({
      init_hour: schedule.start_time,
      end_hour: schedule.end_time,
    }));

  const partialBlocks = [...blocksOfDate, ...workingDayBlocks, ...existingBookingBlocks, ...serverBookingBlocks];

  $q.dialog({
    component: ServiceSelectionSheet,
    componentProps: { provider: props.provider, selectedDate: val, partialBlocks },
  }).onOk(({ serviceType, date: date_, provider: prov }) => {
    $q.dialog({
      component: ServiceTimeSelectionDialog,
      componentProps: { serviceType, selectedDate: date_, provider: prov, partialBlocks },
    }).onOk((booking) => {
      if (wouldExceedWeekLimit(booking.date)) {
        $q.notify({ type: 'negative', message: t('scheduling_page.order_summary.week_limit_error') });
        return;
      }
      bookings.value.push(booking);
      showCalendar.value = false;
    });
  });
};

const confirmRemove = (idx) => {
  $q.dialog({
    title: t('scheduling_page.order_summary.remove_confirm_title'),
    cancel: { label: t('scheduling_page.order_summary.remove_confirm_cancel'), flat: true, color: 'grey-6' },
    ok:     { label: t('scheduling_page.order_summary.remove_confirm_ok'), unelevated: true, color: 'primary', rounded: true, noCaps: true },
    persistent: true,
  }).onOk(() => {
    bookings.value.splice(idx, 1);
  });
};

const formatDate = (dateStr) => {
  const d = new Date(normalizeDate(dateStr) + 'T12:00:00');
  const localeMap = { pt: 'pt-BR', en: 'en-US', es: 'es-ES' };
  const loc = localeMap[locale.value] ?? 'pt-BR';
  const weekday = new Intl.DateTimeFormat(loc, { weekday: 'long' }).format(d);
  const dateFormatted = new Intl.DateTimeFormat(loc, { day: '2-digit', month: '2-digit', year: 'numeric' }).format(d);
  return `${weekday.charAt(0).toUpperCase() + weekday.slice(1)}, ${dateFormatted}`;
};

const submitOrder = async () => {
  if (!primaryAddress.value) {
    $q.notify({ type: 'warning', message: t('scheduling_page.order_summary.no_primary_address') });
    return;
  }

  const payload = {
    client_id:     store.user.client_id,
    provider_id:   props.provider.provider_id,
    address_id:    primaryAddress.value.id,
    schedule_type: 'default',
    schedules: bookings.value.map(b => ({
      date:         normalizeDate(b.date),
      period_type:  b.serviceType.hoursCount,
      start_time:   formatHour(b.slot.startHour),
      end_time:     formatHour(b.slot.endHour),
      total_amount: b.serviceType.price,
      offers_meal:  b.meal === 'offer' ? true : b.meal === 'no_offer' ? false : null,
    })),
  };

  submitting.value = true;
  try {
    await createSchedule(payload);
    $q.notify({ type: 'positive', message: t('scheduling_page.order_summary.submit_success') });
    onDialogOK();
  } catch (err) {
    const msg = err?.response?.data?.message
      ?? err?.message
      ?? t('scheduling_page.order_summary.submit_error');
    $q.notify({ type: 'negative', message: msg });
  } finally {
    submitting.value = false;
    router.push({ name: 'DashboardPage' });
  }
};
</script>

<style scoped lang="scss">
.dialog-root {
  width: 100vw;
  max-width: 100vw;
  height: 100vh;
  max-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #F9FAFB;
}

.dialog-header {
  flex-shrink: 0;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.dialog-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: clip;
}

.info-banner {
  background: rgba(139, 92, 246, 0.08);
  border: 1px solid rgba(139, 92, 246, 0.2);
}

.calendar-wrapper {
  border-radius: 20px;
  overflow: hidden;
  background: white;

  :deep(.q-date) { background: white; width: 100%; }
  :deep(.q-date__main),
  :deep(.q-date__content),
  :deep(.q-date__calendar) { background: white !important; }

  :deep(.q-date__calendar-item .q-btn) {
    font-size: 13px !important;
    min-width: 0 !important;
    padding: 6px 2px !important;
  }
  :deep(.q-date__calendar-item .q-btn.disabled),
  :deep(.q-date__calendar-item .q-btn[disabled]) { opacity: 1 !important; }
  :deep(.q-date__calendar-item .q-btn.disabled .q-btn__content),
  :deep(.q-date__calendar-item .q-btn[disabled] .q-btn__content) { color: #CBD5E1 !important; }

  :deep(.q-date__calendar-days .q-btn__content) { font-weight: 500; color: #1E293B; }
  :deep(.q-date__calendar-weekdays > div) { color: #6366F1; font-weight: 700; opacity: 0.8; }
  :deep(.q-date__navigation) {
    .q-btn { color: #6366F1 !important; }
    .q-btn__content { color: #6366F1 !important; }
  }
  :deep(.q-date__event) { bottom: 4px; height: 6px; width: 6px; border-radius: 50%; }
  :deep(.q-date__today .q-btn__content) { color: #7c4dff !important; background: #7c4dff15; border-radius: 50%; }
  :deep(.q-date__selected .q-btn__content) {
    background: #6366F1 !important;
    color: white !important;
    border-radius: 50%;
    box-shadow: 0 4px 10px rgba(99, 102, 241, 0.4);
  }
}
</style>
