<template>
  <q-dialog
    ref="dialogRef"
    maximized
    transition-hide="slide-down"
    transition-show="slide-up"
  >
    <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
          class="header-back-btn"
          color="primary"
          dense
          flat
          icon="mdi-chevron-left"
          round
        />

        <div
          class="col text-center font16 fontbold text-primary gradient-diarista q-mb-xs"
        >
          {{ $t("scheduling_page.title") }}
        </div>

        <div style="width: 36px"></div>
      </div>

      <div class="dialog-body">
        <div class="q-px-md q-pt-md">
          <div class="font16 fontbold gradient-diarista q-mb-xs">
            {{ $t("scheduling_page.about_provider") }}
          </div>

          <q-card
            class="card-border shadow-card bg-surface text-text"
            :flat="false"
          >
            <q-card-section class="q-pa-md">
              <div class="row items-center no-wrap q-gutter-x-md">
                <div class="col-2">
                  <q-avatar
                    :style="
                      avatarColors[provider.provider_id % avatarColors.length]
                    "
                  >
                    <img
                      v-if="getProfileMediaUrl(provider)"
                      style="object-fit: cover; border-radius: 50%"
                      :src="getProfileMediaUrl(provider)"
                    />

                    <span v-else>
                      {{
                        getFirstName(provider.provider_name)
                          ?.slice(0, 2)
                          .toUpperCase() ?? "??"
                      }}
                    </span>
                  </q-avatar>
                </div>

                <div class="col-3 column">
                  <div class="font12 fontbold text-text">
                    {{ getFirstName(provider?.provider_name) ?? "—" }}
                  </div>

                  <div class="font10 fontmedium text-grey-7">
                    {{ provider?.district ?? "—" }}
                  </div>
                </div>

                <div class="col-3">
                  <div class="row items-center q-gutter-x-md q-mt-xs">
                    <div class="row items-center">
                      <q-icon
                        color="warning"
                        name="mdi-star"
                        size="12px"
                      />

                      <span class="font9 fontmedium q-ml-xs">
                        {{
                          (provider?.average_rating != null
                            ? Number(provider.average_rating).toFixed(1)
                            : "") +
                          " (" +
                          (provider?.total_reviews ?? 0) +
                          ")"
                        }}
                      </span>
                    </div>

                    <div class="row items-center">
                      <q-icon
                        color="secondary"
                        name="mdi-broom"
                        size="14px"
                      />

                      <span class="font9 fontmedium q-ml-xs">
                        {{ provider?.total_services ?? 0 }}
                      </span>
                    </div>
                  </div>
                </div>

                <div class="col-2 column items-center q-gutter-y-xs">
                  <q-btn
                    color="pink-4"
                    dense
                    flat
                    round
                    size="sm"
                    :icon="isFavorite ? 'mdi-heart' : 'mdi-heart-outline'"
                    :loading="favoriteLoading"
                    @click="toggleFavorite"
                  />

                  <q-btn
                    color="grey-5"
                    dense
                    flat
                    icon="mdi-information-outline"
                    round
                    size="sm"
                    @click.stop="openProviderInfo"
                  />
                </div>
              </div>
            </q-card-section>
          </q-card>
        </div>

        <div class="q-px-md q-pt-lg">
          <div class="font16 fontbold gradient-diarista q-mb-xs">
            {{ $t("scheduling_page.schedule_service") }}
          </div>

          <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-mb-md"
          >
            <q-date
              v-model="selectedDate"
              class="full-width"
              minimal
              square
              :first-day-of-week="0"
              :options="dateOptions"
              @update:model-value="onDateSelected"
            />
          </div>
        </div>

        <div class="q-px-md q-pt-sm q-pb-xl">
          <div class="row items-center justify-between q-mb-sm">
            <div class="font16 fontbold gradient-diarista">
              {{ $t("scheduling_page.reviews_title") }}
            </div>

            <span class="text-text cursor-pointer">
              {{ $t("scheduling_page.see_all") }}

              <q-icon
                class="text-text"
                name="mdi-chevron-right"
              />
            </span>
          </div>

          <div
            v-if="loadingReviews"
            class="row items-center justify-center q-py-md"
          >
            <q-spinner-dots
              color="primary"
              size="36px"
            />
          </div>

          <div
            v-else-if="reviews.length === 0"
            class="text-center text-grey-6 text-body2 q-py-md"
          >
            {{ $t("scheduling_page.no_reviews") }}
          </div>

          <div
            v-else
            class="reviews-scroll"
          >
            <q-card
              v-for="review in reviews"
              :key="review.id"
              :flat="false"
              class="review-card card-border bg-white q-mr-sm shadow-card"
            >
              <q-card-section class="q-pa-sm">
                <div class="row items-center no-wrap q-gutter-x-sm q-mb-xs">
                  <q-avatar
                    :style="
                      avatarColors[
                        review.schedule?.client?.id % avatarColors.length
                      ]
                    "
                  >
                    <img
                      v-if="review.schedule?.client?.profile_photo"
                      style="object-fit: cover; border-radius: 50%"
                      :src="review.schedule?.client?.profile_photo"
                    />

                    <span v-else>
                      {{ getFirstName(review.schedule?.client?.name)?.slice(0, 1) ?? "—" }}
                    </span>
                  </q-avatar>

                  <div class="col-3 text-text font10 fontbold">
                    {{
                      getFirstName(review.schedule?.client?.name) ??
                      $t("scheduling_page.unknown_client")
                    }}
                  </div>

                  <div class="row items-center q-mb-xs q-my-auto">
                    <q-icon
                      v-for="s in 5"
                      :key="s"
                      :name="s <= review.stars ? 'mdi-star' : 'mdi-star-outline'"
                      color="warning"
                      size="14px"
                    />
                  </div>
                </div>

                <div class="font9 fontregular text-text review-comment">
                  {{ review.comment ?? "--------" }}
                </div>
              </q-card-section>
            </q-card>
          </div>
        </div>
      </div>
    </div>
  </q-dialog>
</template>

<script setup>
import { avatarColors } from "src/helpers/avatarColors";
import { computed, onMounted, ref } from "vue";

import {
  createClientFavoriteProvider,
  deleteClientFavoriteProvider,
  getClientFavoriteProviders,
} from "src/api/clientFavoriteProvider";

import { date, useDialogPluginComponent, useQuasar } from "quasar";
import { getClientProviderBlocks } from "src/api/schedule";
import { getFirstName } from "src/helpers/utils";
import { getProfileMediaUrl } from "src/helpers/profileMedia";

import {
  getProviderBlockedDays,
  getProviderWorkingDays,
} from "src/api/providerAvailability";

import { getProviderReceivedReviews } from "src/api/review";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import { userStore } from "src/stores/user";
import { useServicePackageStore } from "src/stores/servicePackage";

import ServicePackageSummaryDialog from "./ServicePackageSummaryDialog.vue";
import ServiceSelectionSheet from "./ServiceSelectionSheet.vue";
import ServiceTimeSelectionDialog from "./ServiceTimeSelectionDialog.vue";
import ProfileInfoDialog from "src/components/profile/ProfileInfoDialog.vue";

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

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

const { t } = useI18n();
const $q = useQuasar();
const router = useRouter();
const { dialogRef } = useDialogPluginComponent();

const servicePackage = useServicePackageStore();
const store = userStore();

const blockedDays = ref([]);
const bookings = ref([]);
const favoriteId = ref(null);
const favoriteLoading = ref(false);
const isFavorite = ref(false);
const loadingAvailability = ref(true);
const loadingReviews = ref(true);
const providerClientBlocks = ref({
  existing_schedules: [],
  fully_blocked_weeks: [],
});
const reviews = ref([]);
const selectedDate = ref(null);
const workingDays = ref([]);

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 blockedWeekStartSet = computed(
  () => new Set(providerClientBlocks.value.fully_blocked_weeks ?? []),
);

const normalizeDate = (dateStr) => (dateStr ?? "").replace(/\//g, "-");

const getWeekStart = (dateStr) => {
  const normalizedDate = normalizeDate(dateStr);

  const d = new Date(`${normalizedDate}T12:00:00`);

  d.setDate(d.getDate() - d.getDay());

  return d.toISOString().split("T")[0];
};

const getServicePackageWeekCount = (selectedDate) => {
  const weekStart = getWeekStart(selectedDate);

  return servicePackage.items.filter(
    (item) =>
      Number(item.provider_id) === Number(props.provider.provider_id) &&
      getWeekStart(item.date) === weekStart,
  ).length;
};

const getLocalWeekCount = (selectedDate) => {
  const weekStart = getWeekStart(selectedDate);

  return bookings.value.filter(
    (booking) => getWeekStart(booking.date) === weekStart,
  ).length;
};

const getServerWeekCount = (selectedDate) => {
  const weekStart = getWeekStart(selectedDate);

  return (providerClientBlocks.value.existing_schedules ?? []).filter(
    (schedule) => getWeekStart(schedule.date) === weekStart,
  ).length;
};

const wouldExceedWeekLimit = (selectedDate) => {
  const servicePackageCount = getServicePackageWeekCount(selectedDate);
  const localCount = getLocalWeekCount(selectedDate);
  const serverCount = getServerWeekCount(selectedDate);

  return serverCount + localCount + servicePackageCount >= 2;
};

const dateOptions = (d) => {
  const today = date.formatDate(new Date(), "YYYY/MM/DD");

  if (d < today) return false;

  const raw = normalizeDate(d);
  const parsed = new Date(`${raw}T12:00:00`);
  const dayOfWeek = parsed.getDay();

  const isWorkingDay = availableWeekDays.value.includes(dayOfWeek);
  const isBlocked = blockedDateSet.value.has(raw);
  const isWeekBlocked = blockedWeekStartSet.value.has(getWeekStart(raw));

  if (!isWorkingDay || isBlocked || isWeekBlocked) return false;

  if (wouldExceedWeekLimit(raw)) return false;

  return true;
};

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

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),
    ]);

    blockedDays.value = bd ?? [];

    providerClientBlocks.value = clientBlocks ?? defaultClientBlocks;

    workingDays.value = wd ?? [];
  } catch {
    blockedDays.value = [];

    providerClientBlocks.value = {
      existing_schedules: [],
      fully_blocked_weeks: [],
    };

    workingDays.value = [];
  } finally {
    loadingAvailability.value = false;
  }
};

const loadFavoriteState = async () => {
  const clientId = store.user?.client?.id;
  if (!clientId) return;

  try {
    const favorites = await getClientFavoriteProviders(clientId);
    const match = (favorites ?? []).find(
      (f) => Number(f.provider_id) === Number(props.provider.provider_id),
    );

    isFavorite.value = !!match;
    favoriteId.value = match?.id ?? null;
  } catch {
    isFavorite.value = false;
    favoriteId.value = null;
  }
};

const loadReviews = async () => {
  loadingReviews.value = true;

  try {
    const all = await getProviderReceivedReviews(props.provider.provider_id);

    reviews.value = (all ?? []).slice(0, 10);
  } catch {
    reviews.value = [];
  } finally {
    loadingReviews.value = false;
  }
};

const onDateSelected = (val) => {
  if (!val) return;

  selectedDate.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: "07:00:00", end_hour: "13:00:00" });
  }

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

  const servicePackageBookingBlocks = servicePackage.items
    .filter(
      (item) =>
        Number(item.provider_id) === Number(props.provider.provider_id) &&
        normalizeDate(item.date) === valFormatted,
    )
    .map((item) => ({
      end_hour: item.end_time,
      init_hour: item.start_time,
    }));

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

  const partialBlocks = [
    ...blocksOfDate,
    ...workingDayBlocks,
    ...localBookingBlocks,
    ...serverBookingBlocks,
    ...servicePackageBookingBlocks,
  ];

  $q.dialog({
    component: ServiceSelectionSheet,
    componentProps: {
      partialBlocks,
      provider: props.provider,
      selectedDate: val,
    },
  }).onOk(({ action, serviceType, date: date_, provider: prov }) => {
    $q.dialog({
      component: ServiceTimeSelectionDialog,
      componentProps: {
        partialBlocks,
        provider: prov,
        selectedDate: date_,
        serviceType,
      },
    }).onOk((booking) => {
      if (action === "servicePackage") {
        servicePackage.addItem({
          date: normalizeDate(booking.date),
          end_time: formatHour(booking.slot.endHour),
          local_id: `${prov.provider_id}-${booking.date}-${booking.slot.value}-${Date.now()}`,
          offers_meal:
            booking.meal === "offer"
              ? true
              : booking.meal === "no_offer"
                ? false
                : null,
          period_type: booking.serviceType.hoursCount,
          provider_id: prov.provider_id,
          provider_name: prov.provider_name,
          provider_photo: getProfileMediaUrl(prov),
          start_time: formatHour(booking.slot.startHour),
          base_amount:
            booking.serviceType.basePrice ?? booking.serviceType.price,
        });

        $q.notify({
          message: t("service_package.add_success"),
          type: "positive",
        });

        dialogRef.value.hide();

        router.push({ name: "ScheduleCartPage" });

        return;
      }

      bookings.value.push(booking);

      $q.dialog({
        component: ServicePackageSummaryDialog,
        componentProps: { initialBooking: booking, provider: props.provider },
      }).onOk(() => {
        dialogRef.value.hide();
      });
    });
  });
};

const openProviderInfo = () => {
  $q.dialog({
    component: ProfileInfoDialog,
    componentProps: {
      provider: props.provider,
    },
  });
};

const toggleFavorite = async () => {
  if (favoriteLoading.value) return;

  const clientId = store.user?.client?.id;
  if (!clientId) {
    $q.notify({
      message: t("scheduling_page.favorite_error"),
      type: "negative",
    });

    return;
  }

  favoriteLoading.value = true;

  try {
    if (isFavorite.value) {
      if (favoriteId.value) {
        await deleteClientFavoriteProvider(favoriteId.value);
      }

      favoriteId.value = null;
      isFavorite.value = false;

      $q.notify({
        message: t("scheduling_page.favorite_removed"),
        type: "positive",
      });
    } else {
      const created = await createClientFavoriteProvider({
        client_id: clientId,
        provider_id: props.provider.provider_id,
      });

      favoriteId.value = created?.id ?? null;
      isFavorite.value = true;

      $q.notify({
        message: t("scheduling_page.favorite_added"),
        type: "positive",
      });
    }
  } catch {
    $q.notify({
      message: t("scheduling_page.favorite_error"),
      type: "negative",
    });
  } finally {
    favoriteLoading.value = false;
  }
};

onMounted(() => {
  loadAvailability();
  loadFavoriteState();
  loadReviews();
});
</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;
}

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

  :deep(.q-date) {
    background: white;
    width: 100%;
  }

  :deep(.q-date__calendar-days .q-btn__content) {
    color: #1e293b !important;
  }

  // dias desabilitados: visíveis mas opacos
  :deep(.q-date__calendar-days .q-btn.disabled .q-btn__content),
  :deep(.q-date__calendar-days .q-btn[disabled] .q-btn__content) {
    color: #000000 !important;
    opacity: 1 !important;
  }

  // o Quasar aplica opacity no elemento .q-btn quando disabled — reseta
  :deep(.q-date__calendar-days .q-btn.disabled),
  :deep(.q-date__calendar-days .q-btn[disabled]) {
    opacity: 1 !important;
  }

  // cabeçalho dos dias (dom, seg, ter, qua...)
  :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),
  :deep(.q-date__calendar-item .q-btn.q-date__selected .q-btn__content) {
    background: #6366f1 !important;
    color: #ffffff !important;
    border-radius: 50%;
    box-shadow: 0 4px 10px rgba(99, 102, 241, 0.4);
  }

  :deep(.q-date__view--months .q-btn),
  :deep(.q-date__view--years .q-btn) {
    color: #6366f1 !important;
  }

  :deep(.q-date__calendar-item--out) {
    color: #b9b9b9 !important;
    opacity: 0.8 !important;
  }
}

// Reviews scroll horizontal
.reviews-scroll {
  display: flex;
  flex-direction: row;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 8px;
  &::-webkit-scrollbar {
    display: none;
  }
}

.review-card {
  flex-shrink: 0;
  min-width: 220px;
  max-width: 240px;
  border-radius: 12px;
  margin-right: 8px;
}

.review-comment {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.min-width-0 {
  min-width: 0;
}
</style>
