<template>
  <v-form
    v-model="isInternalFormValid"
    ref="internalFormRef"
    :readonly="viewMode"
  >
    <v-row no-gutters>
      <v-col cols="12">
        <v-row no-gutters class="d-flex align-center ga-2 justify-end">
          <span class="d-flex ga-2 align-center">
            <p>Allow Opening Barrier via Plate Number?</p>
            <v-switch
              v-model="isAllowPlateNumberOpenBarrier"
              hide-details
              color="success"
              size="large"
            />
          </span>
        </v-row>
        <v-row
          no-gutters
          class="d-flex align-center ga-2 justify-space-between"
        >
          <InputLabel
            class="text-capitalize"
            title="Overnight Parking Approval Hours"
          />
          <span class="d-flex ga-2 align-center">
            <p>Auto Approve Parking?</p>
            <v-switch
              v-model="autoApproveOvernightParking"
              hide-details
              color="success"
              size="large"
            />
          </span>
        </v-row>
        <v-card class="mt-2">
          <v-card-text>
            <template
              v-for="(slot, index) in overnightParkingSlotsArray"
              :key="slot.day"
            >
              <v-row no-gutters class="mb-4">
                <v-col
                  cols="12"
                  class="text-capitalize mb-2 text-subtitle-1 d-flex align-center justify-space-between"
                >
                  <span class="font-weight-black">{{ slot.day }}</span>
                  <v-icon
                    :icon="
                      slot?.isEnabled
                        ? 'mdi-check-circle'
                        : 'mdi-check-circle-outline'
                    "
                    size="20"
                    :class="{ 'cursor-pointer': !viewMode }"
                    :color="
                      slot.isEnabled ? 'green-darken-2' : 'black-lighten-1'
                    "
                    @click="!viewMode && toggleEnabled(slot.day)"
                  />
                </v-col>

                <v-col cols="6" class="pr-2">
                  <InputLabel title="Start" :required="slot.isEnabled" />
                  <v-select
                    v-model="slot.startTime"
                    :disabled="!slot.isEnabled"
                    :items="allTimeSlots"
                    item-value="time"
                    item-title="time"
                    density="comfortable"
                    :rules="slot.isEnabled ? [requiredRule] : []"
                    @update:model-value="slot.endTime = null"
                  />
                </v-col>

                <v-col cols="6" class="pl-2">
                  <InputLabel title="End" :required="slot.isEnabled" />
                  <v-select
                    v-model="slot.endTime"
                    :disabled="!slot.isEnabled"
                    :items="generateTimeSlots(0.5, slot.startTime ?? undefined)"
                    item-value="time"
                    item-title="time"
                    density="comfortable"
                    :rules="slot.isEnabled ? [requiredRule] : []"
                  />
                </v-col>

                <v-col v-if="!viewMode" cols="12" class="mt-1">
                  <div
                    class="d-flex align-center ga-1 cursor-pointer text-caption text-medium-emphasis"
                    @click="applyToOtherDays(slot.day)"
                  >
                    <v-icon icon="mdi-content-copy" size="14" />
                    <span>Apply to other days</span>
                  </div>
                </v-col>
              </v-row>

              <v-divider
                v-if="index < overnightParkingSlotsArray.length - 1"
                class="mb-4"
              />
            </template>

            <v-col cols="12" align="end">
              <v-btn
                color="primary"
                class="text-none mt-2"
                size="large"
                :loading="loading.updating"
                variant="flat"
                text="Save"
                :disabled="viewMode || !isValid"
                @click="handleSave('save')"
              />
            </v-col>
          </v-card-text>
        </v-card>
      </v-col>
    </v-row>
  </v-form>

  <Snackbar
    v-model="messageSnackbar"
    :text="message"
    :color="messageColor"
    style="z-index: 3000"
  />

  <v-dialog v-model="applyDialog.open" max-width="360" persistent>
    <v-card>
      <v-card-title class="text-subtitle-1 font-weight-bold pt-4 px-4"
        >Apply to days</v-card-title
      >
      <v-card-text class="px-4 pb-2">
        <p class="text-caption text-medium-emphasis mb-3">
          Select the days to apply
          <span class="font-weight-bold text-capitalize">{{
            applyDialog.sourceDay
          }}</span
          >'s hours to.
        </p>
        <v-checkbox
          v-for="day in applyDialog.targetDays"
          :key="day.day"
          v-model="day.selected"
          :label="day.day"
          density="compact"
          hide-details
          class="text-capitalize"
        />
      </v-card-text>
      <v-card-actions class="px-4 pb-4">
        <v-spacer />
        <v-btn variant="text" @click="applyDialog.open = false">Cancel</v-btn>
        <v-btn
          color="primary"
          variant="flat"
          :disabled="!applyDialog.targetDays.some((d) => d.selected)"
          @click="confirmApply"
          >Apply</v-btn
        >
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script setup lang="ts">
const props = defineProps({
  viewMode: {
    type: Boolean,
    default: false,
    required: false,
  },
  site: {
    type: String,
    default: "",
    required: false,
  },
});

const model = ref<TOvernightParkingAvailability>({
  monday: { isEnabled: false, startTime: null, endTime: null },
  tuesday: { isEnabled: false, startTime: null, endTime: null },
  wednesday: { isEnabled: false, startTime: null, endTime: null },
  thursday: { isEnabled: false, startTime: null, endTime: null },
  friday: { isEnabled: false, startTime: null, endTime: null },
  saturday: { isEnabled: false, startTime: null, endTime: null },
  sunday: { isEnabled: false, startTime: null, endTime: null },
});

const isAllowPlateNumberOpenBarrier = ref(false);
const autoApproveOvernightParking = ref(false);
const isHydrating = ref(true);

const { requiredRule } = useUtils();
const { generateTimeSlots, generateTimeSlotsFromStart } = useFacilityUtils();
const { currentUser } = useLocalAuth();
const {
  getOvernightParkingAvailabilityV2,
  createOrUpdateOvernightParkingAvailabilityV2,
} = useSiteSettings();

type TDay = Exclude<
  keyof TOvernightParkingAvailability,
  "autoApproveOvernightParking"
>;
type TOvernightParkingSlot = TOvernightParkingDay & { day: TDay };

const orderedDays: TDay[] = [
  "monday",
  "tuesday",
  "wednesday",
  "thursday",
  "friday",
  "saturday",
  "sunday",
];

const allTimeSlots = computed(() => generateTimeSlotsFromStart(0.5));

const isInternalFormValid = ref(false);
const internalFormRef =
  ref<InstanceType<typeof import("vuetify/components").VForm>>();

const messageSnackbar = ref(false);
const message = ref("");
const messageColor = ref<"success" | "error">();

const loading = reactive({
  updating: false,
});

const applyDialog = reactive({
  open: false,
  sourceDay: "" as TDay,
  targetDays: [] as { day: TDay; selected: boolean }[],
});

const userType = computed(() => currentUser.value?.type ?? "site");
const updatedByValue = computed(
  () => currentUser.value?._id ?? currentUser.value?.email ?? "system"
);
const { data: availabilityDataReq, refresh: refreshAvailability } =
  await useLazyAsyncData<Record<string, any>>(
    `overnight-parking-availability-${props.site}`,
    () => getOvernightParkingAvailabilityV2(props.site, userType.value)
  );

watch(
  availabilityDataReq,
  (data) => {
    if (!data) return;
    orderedDays.forEach((day) => {
      const slot = overnightParkingSlotsArray.value.find((s) => s.day === day);
      if (!slot) return;
      slot.isEnabled = data?.[day]?.isEnabled ?? false;
      slot.startTime = data?.[day]?.startTime ?? null;
      slot.endTime = data?.[day]?.endTime ?? null;
    });
    isAllowPlateNumberOpenBarrier.value =
      data?.isAllowPlateNumberOpenBarrier === true;
    autoApproveOvernightParking.value =
      data?.autoApproveOvernightParking === true ||
      data?.isAutoApproved === true;
    setTimeout(() => {
      isHydrating.value = false;
    }, 500);
  },
  { immediate: true }
);

const overnightParkingSlotsArray = ref<TOvernightParkingSlot[]>(
  orderedDays.map((day) => ({
    day,
    isEnabled: model.value?.[day]?.isEnabled ?? false,
    startTime: model.value?.[day]?.startTime ?? null,
    endTime: model.value?.[day]?.endTime ?? null,
  }))
);

watch(
  overnightParkingSlotsArray,
  (slots) => {
    const updated = {} as TOvernightParkingAvailability;
    slots.forEach((slot) => {
      updated[slot.day] = {
        isEnabled: slot.isEnabled,
        startTime: slot.startTime,
        endTime: slot.endTime,
      };
    });
    model.value = updated;
  },
  { deep: true }
);

function toggleEnabled(day: TDay) {
  const slot = overnightParkingSlotsArray.value.find((s) => s.day === day);
  if (!slot) return;
  internalFormRef.value?.resetValidation();
  slot.isEnabled = !slot.isEnabled;
}

function applyToOtherDays(sourceDay: TDay) {
  applyDialog.sourceDay = sourceDay;
  applyDialog.targetDays = orderedDays
    .filter((d) => d !== sourceDay)
    .map((d) => ({ day: d, selected: false }));
  applyDialog.open = true;
}

function confirmApply() {
  const source = overnightParkingSlotsArray.value.find(
    (s) => s.day === applyDialog.sourceDay
  );
  if (!source) return;
  const selectedDays = applyDialog.targetDays
    .filter((d) => d.selected)
    .map((d) => d.day);
  overnightParkingSlotsArray.value.forEach((slot) => {
    if (selectedDays.includes(slot.day)) {
      slot.startTime = source.startTime;
      slot.endTime = source.endTime;
      slot.isEnabled = source.isEnabled;
    }
  });
  applyDialog.open = false;
  message.value = `Applied ${
    applyDialog.sourceDay
  }'s hours to ${selectedDays.join(", ")}.`;
  messageColor.value = "success";
  messageSnackbar.value = true;
}

const isValid = computed(() => {
  const slots = overnightParkingSlotsArray.value;
  const enabledSlots = slots.filter((s) => s.isEnabled);
  const isAllSlotsValid = slots.every((s) => {
    if (!s.isEnabled) return true;
    return !!s.startTime?.trim() && !!s.endTime?.trim();
  });
  return isAllSlotsValid && enabledSlots.length > 0;
});

watch(
  isAllowPlateNumberOpenBarrier,
  (newValue, oldValue) => {
    if (oldValue === newValue || isHydrating.value) return;
    handleSave("toggle");
  },
  { immediate: false }
);

watch(
  autoApproveOvernightParking,
  (newValue, oldValue) => {
    if (oldValue === newValue || isHydrating.value) return;
    handleSave("toggle");
  },
  { immediate: false }
);

async function handleSave(action: "toggle" | "save") {
  if (!isValid.value && action === "save") {
    message.value = "Please fill in all required fields.";
    messageColor.value = "error";
    messageSnackbar.value = true;
    return;
  }

  let payload = {};

  payload = {
    ...model.value,
    isAllowPlateNumberOpenBarrier: isAllowPlateNumberOpenBarrier.value,
    autoApproveOvernightParking: autoApproveOvernightParking.value,
    isAutoApproved: autoApproveOvernightParking.value,
    updatedBy: updatedByValue.value,
  };

  try {
    loading.updating = true;
    await createOrUpdateOvernightParkingAvailabilityV2(
      props.site,
      payload,
      userType.value
    );
    refreshAvailability();
    message.value = "Overnight parking settings updated successfully.";
    messageColor.value = "success";
    messageSnackbar.value = true;
  } catch (error) {
    message.value =
      "Failed to update overnight parking settings. Please try again.";
    messageColor.value = "error";
    messageSnackbar.value = true;
  } finally {
    loading.updating = false;
  }
}
</script>

<style scoped></style>
