// SPEC: pikasTech/HWLAB#2345 Workbench Pinia Colada migration; PJ2026-010401080313 Workbench实时权威 draft-2026-07-08-p0-workbench-realtime-authority-v2.
// Responsibility: Colada-governed Workbench semantic query execution, cache keys, invalidation and refetch.

import { useQueryCache, type EntryKey, type QueryCache } from "@pinia/colada";
import { api } from "@/api";
import type { AgentChatResultResponse, ApiResult } from "@/types";
import type { SessionListOptions, SessionMessageOptions, WorkbenchMessagePageResponse, WorkbenchSessionDetailResponse, WorkbenchSessionListResponse, WorkbenchTraceRequestOptions } from "@/api/workbench";
import { workbenchColadaKeys } from "./workbench-colada-keys";

interface QueryRunOptions {
  force?: boolean;
  minIntervalMs?: number | null;
}

export interface WorkbenchTraceEventsQueryOptions extends QueryRunOptions, WorkbenchTraceRequestOptions {
  timeoutMs?: number;
  activityRef?: import("@/api/client").ApiRequestOptions["activityRef"];
}

export interface WorkbenchSessionDetailQueryOptions extends QueryRunOptions {
  timeoutMs?: number | null;
  includeMessages?: false | null;
}

export interface WorkbenchColadaQueries {
  queryCache: QueryCache;
  fetchSessions: (options?: SessionListOptions & QueryRunOptions) => Promise<ApiResult<WorkbenchSessionListResponse>>;
  fetchSession: (sessionId: string, options?: WorkbenchSessionDetailQueryOptions) => Promise<ApiResult<WorkbenchSessionDetailResponse>>;
  fetchSessionMessages: (sessionId: string, options?: SessionMessageOptions & QueryRunOptions) => Promise<ApiResult<WorkbenchMessagePageResponse>>;
  fetchTraceEvents: (traceId: string, options?: WorkbenchTraceEventsQueryOptions) => Promise<ApiResult<AgentChatResultResponse>>;
  fetchProviderProfiles: (options?: QueryRunOptions) => Promise<ApiResult<unknown>>;
  invalidateSession: (sessionId: string | null | undefined) => Promise<unknown>;
  invalidateSessionMessages: (sessionId: string | null | undefined) => Promise<unknown>;
  invalidateTraceEvents: (traceId: string | null | undefined) => Promise<unknown>;
  invalidateTraceScope: (input: { sessionId?: string | null; traceId?: string | null }) => Promise<unknown[]>;
}

export function useWorkbenchColadaQueries(): WorkbenchColadaQueries {
  const queryCache = useQueryCache();

  return {
    queryCache,
    fetchSessions: (options = {}) => runWorkbenchQuery(queryCache, workbenchColadaKeys.sessions(options), () => api.workbench.sessions(options), options),
    fetchSession: (sessionId, options = {}) => runWorkbenchQuery(queryCache, workbenchColadaKeys.session(sessionId), () => api.workbench.session(sessionId, { timeoutMs: options.timeoutMs ?? null, includeMessages: false }), options),
    fetchSessionMessages: (sessionId, options = {}) => runWorkbenchQuery(queryCache, workbenchColadaKeys.sessionMessages(sessionId, options), () => api.workbench.sessionMessages(sessionId, options), options),
    fetchTraceEvents: (traceId, options = {}) => runWorkbenchQuery(queryCache, workbenchColadaKeys.traceEvents(traceId, options), () => api.workbench.traceEvents(traceId, options.timeoutMs ?? 8000, options.activityRef, { afterProjectedSeq: options.afterProjectedSeq, limit: options.limit }), options),
    fetchProviderProfiles: (options = {}) => runWorkbenchQuery(queryCache, workbenchColadaKeys.providerProfiles(), () => api.providerProfiles.catalog(), options),
    invalidateSession: (sessionId) => sessionId ? queryCache.invalidateQueries({ key: workbenchColadaKeys.session(sessionId) }) : Promise.resolve(),
    invalidateSessionMessages: (sessionId) => sessionId ? queryCache.invalidateQueries({ key: workbenchColadaKeys.sessionMessagesRoot().concat(sessionId) }) : Promise.resolve(),
    invalidateTraceEvents: (traceId) => traceId ? queryCache.invalidateQueries({ key: workbenchColadaKeys.traceEventsRoot().concat(traceId) }) : Promise.resolve(),
    invalidateTraceScope: async (input) => Promise.all([
      queryCache.invalidateQueries({ key: workbenchColadaKeys.snapshotRoot() }),
      input.sessionId ? queryCache.invalidateQueries({ key: workbenchColadaKeys.historySessionMessagesRoot().concat(input.sessionId) }) : Promise.resolve(),
      input.traceId ? queryCache.invalidateQueries({ key: workbenchColadaKeys.detailRoot() }) : Promise.resolve()
    ])
  };
}

async function runWorkbenchQuery<TResult>(queryCache: QueryCache, key: EntryKey, query: () => Promise<TResult>, options: QueryRunOptions): Promise<TResult> {
  const entry = queryCache.ensure<TResult, Error, undefined>({
    key,
    query,
    enabled: false,
    staleTime: normalizeStaleTime(options.minIntervalMs)
  });
  // refresh() preserves Colada staleTime/min-interval governance; fetch() would bypass it.
  const state = await queryCache.refresh(entry);
  return state.data as TResult;
}

function normalizeStaleTime(value: number | null | undefined): number {
  const number = Number(value);
  return Number.isFinite(number) && number > 0 ? Math.trunc(number) : 0;
}
