import type { DimSdkStore } from "#cli/core/store";
import type { TipIntensity } from "#cli/core/ui-settings";
import type { ComputedRef, Ref } from "vue";
import { t } from "#cli/i18n";
import { watch } from "vue";
import { formatDateKey } from "../../utils/date";

type UseChatTipsOptions = Readonly<{
  store: DimSdkStore;
  anyDialogOpen: ComputedRef<boolean>;
  isLoading: ComputedRef<boolean>;
  tipIntensityValue: ComputedRef<TipIntensity>;
  commandsShortcutLabel: ComputedRef<string>;
  queuePauseTipPending: Ref<boolean>;
  shouldShowQueuePausedTip: () => boolean;
  showQueuePausedTip: () => void;
  showCopyToast: (text: string, durationMs?: number | null) => void;
  currentSessionId: Ref<string>;
  ctxPct: ComputedRef<number | null>;
  timelineEntries: ComputedRef<readonly unknown[]>;
  showTimeline: Ref<boolean>;
}>;

interface TipState {
  contextWarn: boolean;
  contextCritical: boolean;
  timeline: boolean;
  aliasTimeline: boolean;
  errorRecovery: boolean;
  greeting: boolean;
  delight: boolean;
}

const TIP_COOLDOWN_MS = 10_000;
const TIP_DURATION_MS = 3200;
const COMPACT_STREAK_WINDOW_MS = 15 * 60 * 1000;
const COMPACT_DELIGHT_COOLDOWN_MS = 60 * 1000;

export function useChatTips(opts: UseChatTipsOptions): Readonly<{
  handleCompactDelight: () => void;
  showTimelineAliasTip: () => void;
}> {
  const tipState: TipState = {
    contextWarn: false,
    contextCritical: false,
    timeline: false,
    aliasTimeline: false,
    errorRecovery: false,
    greeting: false,
    delight: false,
  };

  let lastTipAtMs = 0;

  const showWarmTip = (text: string, opts2?: { level?: "standard" | "high" }): boolean => {
    if (!text) return false;
    if (opts.queuePauseTipPending.value || opts.shouldShowQueuePausedTip()) {
      if (opts.anyDialogOpen.value || opts.isLoading.value) {
        opts.queuePauseTipPending.value = true;
        return false;
      }
      opts.showQueuePausedTip();
      return false;
    }
    const intensity = opts.tipIntensityValue.value;
    if (intensity === "off") return false;
    const level = opts2?.level ?? "standard";
    if (intensity === "low" && level !== "high") return false;
    if (opts.anyDialogOpen.value || opts.isLoading.value) return false;
    const now = Date.now();
    if (now - lastTipAtMs < TIP_COOLDOWN_MS) return false;
    opts.showCopyToast(text, TIP_DURATION_MS);
    lastTipAtMs = now;
    return true;
  };

  const maybeShowGreeting = () => {
    if (tipState.greeting) return;
    const env = opts.store.state.context?.env ?? {};
    const isTest = String(env.DIMCODE_TEST ?? "").trim() === "1";
    if (isTest) return;
    const uiState = opts.store.state.ui;
    const today = formatDateKey(Date.now());
    const lastSeen = String(uiState.greeting?.lastSeenDate ?? "").trim();
    if (lastSeen === today) return;
    uiState.greeting = { ...uiState.greeting, lastSeenDate: today };
    if (
      showWarmTip(
        t("chatPage.tips.greeting", {
          commandsKey: opts.commandsShortcutLabel.value || "Ctrl+P",
          init: "/init",
        }),
      )
    )
      tipState.greeting = true;
  };

  const handleCompactDelight = () => {
    const intensity = opts.tipIntensityValue.value;
    if (intensity === "off") return;
    const uiState = opts.store.state.ui;
    const delight = uiState.delight ?? {};
    const now = Date.now();
    const lastCompactAt = Number(delight.lastCompactAtMs ?? 0);
    const prevStreak = Number(delight.compactStreak ?? 0);
    const streak =
      lastCompactAt && now - lastCompactAt <= COMPACT_STREAK_WINDOW_MS ? prevStreak + 1 : 1;
    const lastDelightAt = Number(delight.lastDelightAtMs ?? 0);
    uiState.delight = {
      ...delight,
      compactStreak: streak,
      lastCompactAtMs: now,
      lastDelightAtMs: lastDelightAt,
    };

    if (streak >= 2 && now - lastDelightAt >= COMPACT_DELIGHT_COOLDOWN_MS) {
      if (showWarmTip(t("chatPage.tips.compactDelight"))) {
        uiState.delight = { ...uiState.delight, lastDelightAtMs: now };
        tipState.delight = true;
      }
    }
  };

  const resetTips = () => {
    tipState.contextWarn = false;
    tipState.contextCritical = false;
    tipState.timeline = false;
    tipState.aliasTimeline = false;
    tipState.errorRecovery = false;
    tipState.greeting = false;
    tipState.delight = false;
    lastTipAtMs = 0;
  };

  queueMicrotask(() => {
    maybeShowGreeting();
  });

  watch(opts.currentSessionId, () => resetTips(), { immediate: true });

  watch(
    () => [opts.ctxPct.value, opts.anyDialogOpen.value, opts.isLoading.value] as const,
    ([pct, dialogOpen, loading]) => {
      if (pct == null) return;
      if (dialogOpen || loading) return;
      if (pct >= 95 && !tipState.contextCritical) {
        if (showWarmTip(t("chatPage.tips.contextCritical"), { level: "high" })) {
          tipState.contextCritical = true;
          tipState.contextWarn = true;
        }
        return;
      }
      if (pct >= 80 && !tipState.contextWarn) {
        if (showWarmTip(t("chatPage.tips.contextWarn"))) tipState.contextWarn = true;
      }
    },
    { immediate: true },
  );

  watch(
    () =>
      [opts.timelineEntries.value.length, opts.anyDialogOpen.value, opts.isLoading.value] as const,
    ([len, dialogOpen, loading]) => {
      if (dialogOpen || loading) return;
      if (len >= 8 && !tipState.timeline) {
        if (showWarmTip(t("chatPage.tips.timeline"))) tipState.timeline = true;
      }
    },
    { immediate: true },
  );

  watch(opts.showTimeline, (open) => {
    if (open) tipState.timeline = true;
  });

  const showTimelineAliasTip = () => {
    if (!tipState.aliasTimeline) {
      if (showWarmTip(t("chatPage.tips.timelineAlias"))) tipState.aliasTimeline = true;
    }
  };

  return { handleCompactDelight, showTimelineAliasTip };
}
