<script setup>
import { computed, onMounted, ref, watch } from "vue";
import { Effect, Option } from "effect";
import { Fetch } from "fx-fetch";
import { useIntervalFn, useWindowFocus } from "@vueuse/core";
import { useI18n } from "vue-i18n";
import { getLocalizedText } from "../../../../../share/locale";
import { cel } from "../../../../../utils/cel";
import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
import { fetchJsonOption } from "../../../../../share/request";
import { interpolateMarkdown } from "../../../../table/utils/runtime";
import { Badge } from "../../../../ui/badge";
import { Markdown } from "../../../../ui/markdown";
defineOptions({ name: "ShwfedBlockCardBadge", inheritAttrs: false });
const props = defineProps({
  badge: { type: null, required: true }
});
const { locale } = useI18n();
const inheritedContext = injectCELContext();
const json = ref(void 0);
function baseContext() {
  return celBindings(inheritedContext);
}
const jsonOption = computed(
  () => json.value === void 0 ? Option.none() : Option.some(json.value)
);
const template = computed(() => getLocalizedText(props.badge.content, locale.value) || "");
const rendered = computed(() => {
  if (!template.value) return "";
  return interpolateMarkdown(template.value, cel, { ...baseContext(), json: jsonOption.value });
});
const visible = computed(() => {
  const expr = props.badge.show;
  if (!expr) return true;
  try {
    return Effect.runSync(cel(expr, { ...baseContext(), json: jsonOption.value }));
  } catch (e) {
    console.warn("[shwfed-card-badge] show evaluation failed", e);
    return true;
  }
});
async function refresh() {
  const req = props.badge.request;
  if (!req) return;
  const ctx = baseContext();
  const program = Effect.gen(function* () {
    const json2 = yield* fetchJsonOption(yield* cel(req, ctx));
    return Option.getOrUndefined(json2);
  });
  try {
    json.value = await Effect.runPromise(Effect.provide(program, Fetch.layer));
  } catch (e) {
    console.warn("[shwfed-card-badge] fetch failed", e);
  }
}
const pollingEnabled = computed(() => !!props.badge.request && (props.badge.interval ?? 0) > 0);
const intervalMs = computed(() => Math.max(1, props.badge.interval ?? 1) * 1e3);
const focused = useWindowFocus();
const { pause, resume } = useIntervalFn(() => void refresh(), intervalMs, { immediate: false });
onMounted(() => {
  void refresh();
  if (pollingEnabled.value && focused.value) resume();
});
watch(focused, (isFocused) => {
  if (!pollingEnabled.value) return;
  if (isFocused) {
    void refresh();
    resume();
  } else {
    pause();
  }
});
watch(
  () => [props.badge.request ?? "", props.badge.interval ?? 0].join("|"),
  () => {
    void refresh();
    if (pollingEnabled.value && focused.value) resume();
    else pause();
  }
);
</script>

<template>
  <template v-if="template && visible">
    <Badge
      v-if="badge.dot"
      :variant="badge.variant ?? 'default'"
      class="size-2.5 min-w-0 rounded-full p-0"
      v-bind="$attrs"
    />
    <Badge
      v-else
      :variant="badge.variant ?? 'default'"
      v-bind="$attrs"
    >
      <Markdown
        :source="rendered"
        class="max-w-none text-inherit [&_*]:text-inherit [&_p]:m-0"
      />
    </Badge>
  </template>
</template>
