<template>
  <v-card width="100%">
    <v-toolbar>
      <v-row no-gutters class="fill-height px-6" align="center">
        <span class="font-weight-bold text-h5">Assign Access Card to Unit</span>
      </v-row>
    </v-toolbar>
    <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-0">
      <v-form v-model="validForm" :disabled="loading">
        <v-row no-gutters class="px-6 pt-4 pb-2">
          <!-- Building -->
          <v-col cols="12" class="px-1">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Block"
              required
            />
            <v-autocomplete
              v-model="form.building"
              density="compact"
              :items="buildingItems"
              hide-details="auto"
              item-title="name"
              item-value="value"
              placeholder="Select block..."
              persistent-placeholder
              :rules="[requiredRule]"
              :loading="buildingLoading"
            />
          </v-col>

          <!-- Level -->
          <v-col cols="12" class="px-1 mt-2">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Level"
              required
            />
            <v-autocomplete
              v-model="form.level"
              density="compact"
              :items="levelItems"
              hide-details="auto"
              item-title="name"
              item-value="value"
              placeholder="Select level..."
              persistent-placeholder
              :rules="[requiredRule]"
              :disabled="!form.building"
            />
          </v-col>

          <!-- Units (multi-select) -->
          <v-col cols="12" class="px-1 mt-2">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Unit(s)"
              required
            />
            <v-autocomplete
              v-model="form.units"
              density="compact"
              :items="unitItems"
              hide-details="auto"
              item-title="name"
              item-value="value"
              placeholder="Select unit..."
              persistent-placeholder
              :rules="[requiredArrayRule]"
              :disabled="!form.level"
              multiple
              chips
              closable-chips
            />
          </v-col>

          <!-- Type -->
          <v-col cols="12" class="px-1 mt-2">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Type of Access Card"
              required
            />
            <v-select
              v-model="form.type"
              density="compact"
              :items="typeItems"
              hide-details="auto"
              item-title="label"
              item-value="value"
              :rules="[requiredRule]"
            />
          </v-col>

          <!-- Access Level -->
          <v-col cols="12" class="px-1 mt-2">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Access Level"
            />
            <v-select
              v-model="form.accessLevel"
              density="compact"
              :items="accessLevelItems"
              hide-details="auto"
              item-title="name"
              item-value="no"
              :loading="levelsLoading"
              placeholder="Select access level..."
            />
          </v-col>

          <!-- Lift Access Level -->
          <v-col cols="12" class="px-1 mt-2 mb-4">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Lift Access Level"
            />
            <v-select
              v-model="form.liftAccessLevel"
              density="compact"
              :items="liftAccessLevelItems"
              hide-details="auto"
              item-title="name"
              item-value="no"
              :loading="levelsLoading"
              placeholder="Select lift access level..."
            />
          </v-col>

          <!-- Quantity -->
          <v-col cols="12" class="px-1 mt-2">
            <InputLabel
              class="text-capitalize font-weight-bold"
              title="Quantity"
              required
            />
            <v-text-field
              v-model.number="form.quantity"
              density="compact"
              hide-details="auto"
              type="number"
              :min="1"
              hide-spin-buttons
              :rules="[requiredRule, minQuantityRule, maxQuantityRule]"
              @blur="enforceMinQuantity"
            />
            <div class="text-caption mt-1">
              <template v-if="availableLoading">
                <span class="text-grey">Loading available count...</span>
              </template>
              <template v-else-if="availableCount !== null">
                <span :class="availableCount === 0 ? 'text-error' : 'text-grey'">
                  Available: {{ availableCount }}
                </span>
              </template>
            </div>
          </v-col>
        </v-row>
      </v-form>
    </v-card-text>

    <v-toolbar density="compact">
      <v-row no-gutters>
        <v-col cols="6">
          <v-btn
            tile
            block
            variant="text"
            class="text-none"
            size="48"
            @click="cancel"
            :disabled="loading"
          >
            Cancel
          </v-btn>
        </v-col>
        <v-col cols="6">
          <v-btn
            tile
            block
            variant="flat"
            color="black"
            class="text-none"
            size="48"
            :disabled="!validForm || loading || availableCount === 0 || (availableCount !== null && form.quantity > availableCount)"
            :loading="loading"
            @click="submit"
          >
            Assign
          </v-btn>
        </v-col>
      </v-row>
    </v-toolbar>
  </v-card>
</template>
<script setup lang="ts">
const props = defineProps({
  siteId: {
    type: String,
    default: "",
  },
});
const emit = defineEmits(["cancel", "success", "error"]);

const {
  getDoorAccessLevels: _getDoorAccessLevels,
  getLiftAccessLevels: _getLiftAccessLevels,
  assignAccessCard: _assignAccessCard,
  getAvailableAccessCards: _getAvailableAccessCards,
  getBlockLevelUnitList: _getBlockLevelUnitList,
} = useAccessManagement();
const { requiredRule } = useUtils();

const route = useRoute();
const siteId = computed(() => props.siteId || (route.params.site as string));

const validForm = ref(false);
const loading = ref(false);
const levelsLoading = ref(false);
const buildingLoading = ref(false);
const availableLoading = ref(false);
const availableCount = ref<number | null>(null);

const form = ref({
  building: null as string | null,
  level: null as string | null,
  units: [] as string[],
  quantity: 1,
  type: "NFC",
  userType: "Visitor/Resident",
  accessLevel: null as string | null,
  liftAccessLevel: null as string | null,
});

const typeItems = [
  { label: "Physical Access Card", value: "NFC" },
  { label: "Non Physical Access Card", value: "QRCODE" },
];

const NO_SELECTION = { name: "No Selection", no: null };
const accessLevelItems = ref<{ name: string; no: string | null }[]>([]);
const liftAccessLevelItems = ref<{ name: string; no: string | null }[]>([]);
const buildingItems = ref<{ name: string; value: string }[]>([]);
const blockLevelUnitData = ref<any[]>([]);
const levelItems = ref<{ name: string; value: string }[]>([]);
const unitItems = ref<{ name: string; value: string }[]>([]);

function requiredArrayRule(v: string[]) {
  return (v && v.length > 0) || "This field is required";
}

function minQuantityRule(v: number) {
  return v >= 1 || "Quantity must be at least 1";
}

function maxQuantityRule(v: number) {
  if (availableCount.value !== null && v > availableCount.value) {
    return `Quantity cannot exceed available (${availableCount.value})`;
  }
  return true;
}

async function fetchAvailableCount() {
  if (!form.value.accessLevel && !form.value.liftAccessLevel) {
    availableCount.value = null;
    return;
  }
  availableLoading.value = true;
  availableCount.value = null;
  try {
    const res = await _getAvailableAccessCards({
      site: siteId.value,
      userType: form.value.userType,
      type: form.value.type,
      accessLevel: form.value.accessLevel,
      liftAccessLevel: form.value.liftAccessLevel,
    });
    const data: { counts: { count: number }[] }[] = res.data ?? [];
    availableCount.value = data.reduce(
      (total, item) =>
        total + (item.counts ?? []).reduce((s, c) => s + (c.count ?? 0), 0),
      0
    );
  } catch {
    availableCount.value = null;
  } finally {
    availableLoading.value = false;
  }
}

function enforceMinQuantity() {
  if (!form.value.quantity || form.value.quantity < 1) {
    form.value.quantity = 1;
  }
}

onMounted(async () => {
  // Fetch buildings and ACM levels independently so one failure doesn't block the other
  buildingLoading.value = true;
  levelsLoading.value = true;

  const [blockLevelResult, acmResult] = await Promise.allSettled([
    _getBlockLevelUnitList(siteId.value),
    $fetch<{ encrypted: string }>("/api/encrypt-acm-url"),
  ]);

  // Blocks / Levels / Units
  if (blockLevelResult.status === "fulfilled") {
    blockLevelUnitData.value = (blockLevelResult.value as any)?.data || [];
    buildingItems.value = blockLevelUnitData.value.map((b: any) => ({
      name: b.block,
      value: b._id,
    }));
  }
  buildingLoading.value = false;

  // ACM levels (door + lift)
  if (acmResult.status === "fulfilled") {
    const acmUrl = acmResult.value.encrypted;
    try {
      const [doorLevels, liftLevels] = await Promise.all([
        _getDoorAccessLevels(acmUrl),
        _getLiftAccessLevels(acmUrl),
      ]);
      accessLevelItems.value = [NO_SELECTION, ...(doorLevels.data ?? [])];
      liftAccessLevelItems.value = [NO_SELECTION, ...(liftLevels.data ?? [])];
    } catch {
      emit(
        "error",
        "EntryPass server is unavailable. Please contact your administrator."
      );
    }
  } else {
    emit(
      "error",
      "EntryPass server is unavailable. Please contact your administrator."
    );
  }
  levelsLoading.value = false;
});

watch(
  () => form.value.building,
  (newVal) => {
    form.value.level = null;
    form.value.units = [];
    levelItems.value = [];
    unitItems.value = [];

    if (newVal) {
      const selectedBlock = blockLevelUnitData.value.find((b: any) => b._id === newVal);
      if (selectedBlock?.levels) {
        levelItems.value = selectedBlock.levels.map((l: any) => ({
          name: l.level,
          value: l._id,
        }));
      }
    }
  }
);

watch(
  () => form.value.level,
  (newVal) => {
    form.value.units = [];
    unitItems.value = [];

    if (newVal && form.value.building) {
      const selectedBlock = blockLevelUnitData.value.find((b: any) => b._id === form.value.building);
      const selectedLevel = selectedBlock?.levels?.find((l: any) => l._id === newVal);
      if (selectedLevel?.units) {
        unitItems.value = selectedLevel.units.map((u: any) => ({
          name: u.name,
          value: u._id,
        }));
      }
    }
  }
);

watch(
  [
    () => form.value.type,
    () => form.value.accessLevel,
    () => form.value.liftAccessLevel,
  ],
  () => {
    fetchAvailableCount();
  },
  { immediate: true }
);

function cancel() {
  emit("cancel");
}

async function submit() {
  loading.value = true;
  try {
    await _assignAccessCard({
      units: form.value.units,
      quantity: form.value.quantity,
      type: form.value.type,
      site: siteId.value,
      userType: form.value.userType,
      accessLevel: form.value.accessLevel,
      liftAccessLevel: form.value.liftAccessLevel,
    });
    emit("success");
  } catch (error: any) {
    const msg =
      error?.response?._data?.message ||
      error?.data?.message ||
      "Failed to assign access card.";
    emit("error", msg);
  } finally {
    loading.value = false;
  }
}
</script>
