/**
 * RTK Query API Definition
 * 
 * This is the recommended way to handle data fetching in Redux Toolkit.
 * Benefits:
 * - Automatic caching and cache invalidation
 * - Automatic loading/error states
 * - Built-in polling support
 * - Optimistic updates
 * - Better TypeScript inference
 */

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import type { 
  UnifiedProgress, 
  HeuristicWeights, 
  WeightedTask,
} from '../types';

const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:3456';

// Version info from backend
export interface VersionInfo {
  version: string;
  versionTag: string;
  name: string;
  fullName: string;
}

export const priorityApi = createApi({
  reducerPath: 'priorityApi',
  baseQuery: fetchBaseQuery({ baseUrl: API_BASE }),
  tagTypes: ['Status', 'Tasks', 'Weights', 'XmemActivity', 'XmemBlockers', 'SharedTasks', 'XmemFocus', 'Linear'],
  endpoints: (builder) => ({
    // GET /version - App version info (single source of truth)
    getVersion: builder.query<VersionInfo, void>({
      query: () => '/version',
    }),

    // GET /status - Main data fetch
    getStatus: builder.query<UnifiedProgress, void>({
      query: () => '/status',
      providesTags: ['Status', 'Tasks', 'Weights'],
    }),

    // GET /top-priority
    getTopPriority: builder.query<{ task: WeightedTask; explanation: string }, void>({
      query: () => '/top-priority',
      providesTags: ['Tasks'],
    }),

    // GET /heuristic-weights
    getHeuristicWeights: builder.query<HeuristicWeights, void>({
      query: () => '/heuristic-weights',
      providesTags: ['Weights'],
    }),

    // PUT /heuristic-weights - Update weights
    updateHeuristicWeights: builder.mutation<
      { message: string; weights: HeuristicWeights },
      Partial<HeuristicWeights>
    >({
      query: (weights) => ({
        url: '/heuristic-weights',
        method: 'PUT',
        body: weights,
      }),
      // Invalidate cache to trigger refetch
      invalidatesTags: ['Status', 'Weights', 'Tasks'],
    }),

    // POST /recalculate - Recalculate all priorities
    recalculatePriorities: builder.mutation<
      { message: string; taskCount: number; topPriority: WeightedTask | null },
      void
    >({
      query: () => ({
        url: '/recalculate',
        method: 'POST',
      }),
      invalidatesTags: ['Status', 'Tasks'],
    }),

    // PATCH /tasks/:id - Update task
    updateTask: builder.mutation<WeightedTask, { id: string; updates: Partial<WeightedTask> }>({
      query: ({ id, updates }) => ({
        url: `/tasks/${id}`,
        method: 'PATCH',
        body: updates,
      }),
      // Optimistic update
      async onQueryStarted({ id, updates }, { dispatch, queryFulfilled }) {
        // Optimistically update the cache
        const patchResult = dispatch(
          priorityApi.util.updateQueryData('getStatus', undefined, (draft) => {
            const task = draft.priorityQueue.find(t => t.id === id);
            if (task) {
              Object.assign(task, updates);
            }
          })
        );
        try {
          await queryFulfilled;
        } catch {
          // Revert on error
          patchResult.undo();
        }
      },
      invalidatesTags: ['Tasks'],
    }),

    // POST /tasks - Create task
    createTask: builder.mutation<WeightedTask, Partial<WeightedTask>>({
      query: (task) => ({
        url: '/tasks',
        method: 'POST',
        body: task,
      }),
      invalidatesTags: ['Status', 'Tasks'],
    }),

    // DELETE /tasks/:id - Delete task
    deleteTask: builder.mutation<void, string>({
      query: (id) => ({
        url: `/tasks/${id}`,
        method: 'DELETE',
      }),
      invalidatesTags: ['Status', 'Tasks'],
    }),

    // V3.2: Online Learning - Log drag reorder
    logDragReorder: builder.mutation<
      {
        event: {
          id: string;
          taskId: string;
          fromRank: number;
          toRank: number;
          direction: 'promoted' | 'demoted';
          implicitPreferences: Array<{
            preferredTaskId: string;
            demotedTaskId: string;
            scoreDiff: number;
          }>;
          appliedWeightDelta?: Partial<HeuristicWeights>;
        };
        pairsGenerated: number;
        weightUpdateApplied: boolean;
      },
      { taskId: string; fromRank: number; toRank: number }
    >({
      query: (params) => ({
        url: '/drag-reorder',
        method: 'POST',
        body: params,
      }),
      // Invalidate to refetch updated weights and scores
      invalidatesTags: ['Status', 'Tasks', 'Weights'],
    }),

    // V3.2: Get online learner state
    getOnlineLearnerState: builder.query<
      {
        totalUpdates: number;
        totalPairs: number;
        correctPredictions: number;
        accuracy: number;
        cumulativeLoss: number;
        currentWeights: HeuristicWeights;
        learningRate: number;
        enabled: boolean;
      },
      void
    >({
      query: () => '/online-learner',
      providesTags: ['Weights'],
    }),

    // V4: Workspace Management
    getWorkspaces: builder.query<
      {
        workspaces: Array<{
          id: string;
          name: string;
          description?: string;
          createdAt: string;
          updatedAt: string;
          freshness?: {
            freshnessScore: number;
            lastTouchedAt: string | null;
            daysSinceTouch: number;
            openTaskCount: number;
            futureDeadlineCount: number;
            active: boolean;
            dormant: boolean;
            activeReason: string | null;
          };
        }>;
        currentWorkspaceId: string | null;
        thresholds?: {
          interactionWindowDays: number;
          futureDeadlineHorizonDays: number;
          decayTauDays: number;
        };
      },
      void
    >({
      query: () => '/workspaces?include_freshness=true',
      providesTags: ['Status'],
    }),

    getCurrentWorkspace: builder.query<
      {
        workspace: {
          id: string;
          name: string;
          description?: string;
          createdAt: string;
          updatedAt: string;
        } | null;
        workspaceId: string | null;
      },
      void
    >({
      query: () => '/workspaces/current',
      providesTags: ['Status'],
    }),

    createWorkspace: builder.mutation<
      {
        id: string;
        name: string;
        description?: string;
        createdAt: string;
        updatedAt: string;
      },
      { name: string; description?: string }
    >({
      query: (data) => ({
        url: '/workspaces',
        method: 'POST',
        body: data,
      }),
      invalidatesTags: ['Status'],
    }),

    switchWorkspace: builder.mutation<
      {
        workspace: {
          id: string;
          name: string;
          description?: string;
          createdAt: string;
          updatedAt: string;
        } | null;
        message: string;
      },
      string
    >({
      query: (workspaceId) => ({
        url: `/workspaces/${workspaceId}/switch`,
        method: 'POST',
      }),
      invalidatesTags: ['Status', 'Tasks', 'Weights'],
    }),

    deleteWorkspace: builder.mutation<
      { success: boolean; message: string },
      string
    >({
      query: (workspaceId) => ({
        url: `/workspaces/${workspaceId}`,
        method: 'DELETE',
      }),
      invalidatesTags: ['Status'],
    }),

    seedWorkspace: builder.mutation<
      { success: boolean; message: string },
      void
    >({
      query: () => ({
        url: '/workspaces/current/seed',
        method: 'POST',
      }),
      invalidatesTags: ['Status', 'Tasks'],
    }),

    // ── Memory-hub (XMem) endpoints ──
    // Talk to /xmem/* REST shims that wrap the dispatchXmemTool helper.

    getXmemStatus: builder.query<{
      configPath: string;
      memory: {
        enabled: boolean;
        backend: 'noop' | 'dryrun' | 'xmem' | 'pgvector';
        teamId: string;
        agentId: string;
      };
      orchestration: { enabled: boolean; supportsOrchestration: boolean };
      health: { ok: boolean; backend: string; detail?: string };
      warnings: string[];
    }, void>({
      query: () => '/xmem/status',
      providesTags: ['XmemActivity'],
    }),

    getXmemTeamActivity: builder.query<{
      teamId: string;
      count: number;
      events: Array<{
        eventId: string;
        teamId: string;
        agentId: string;
        workspaceId: string;
        eventType: string;
        timestamp: string;
        payload: Record<string, unknown>;
        summary: string;
        metadata: Record<string, unknown>;
      }>;
    }, { limit?: number; sinceTs?: string; agentIds?: string } | void>({
      query: (args) => {
        const params = new URLSearchParams();
        if (args && typeof args === 'object') {
          if (args.limit !== undefined) params.set('limit', String(args.limit));
          if (args.sinceTs) params.set('sinceTs', args.sinceTs);
          if (args.agentIds) params.set('agentIds', args.agentIds);
        }
        const qs = params.toString();
        return `/xmem/team-activity${qs ? '?' + qs : ''}`;
      },
      providesTags: ['XmemActivity'],
    }),

    getXmemBlockingMe: builder.query<{
      teamId: string;
      agentId: string;
      count: number;
      blockers: Array<{
        blockedTaskId: string;
        blockedAgentId: string;
        blockingTaskId: string;
        blockingAgentId: string;
        status: 'active' | 'cleared';
        observedAt: string;
      }>;
    }, void>({
      query: () => '/xmem/blocking-me',
      providesTags: ['XmemBlockers'],
    }),

    getXmemIAmBlocking: builder.query<{
      teamId: string;
      agentId: string;
      count: number;
      blockers: Array<{
        blockedTaskId: string;
        blockedAgentId: string;
        blockingTaskId: string;
        blockingAgentId: string;
        status: 'active' | 'cleared';
        observedAt: string;
      }>;
    }, void>({
      query: () => '/xmem/i-am-blocking',
      providesTags: ['XmemBlockers'],
    }),

    // GET /xmem/current-focus — who is working on what right now (per agent)
    getXmemCurrentFocus: builder.query<{
      teamId: string;
      agents: Record<string, {
        currentTaskId: string;
        currentTaskTitle: string;
        project: string;
        startedAt: string;
        sharedTaskId?: string;
      } | null>;
      idleAgents: string[];
      count: number;
    }, void>({
      query: () => '/xmem/current-focus',
      providesTags: ['XmemFocus'],
    }),

    // GET /shared-tasks/list?status=… — the orchestration plane pool
    getSharedTasks: builder.query<{
      count?: number;
      sharedTasks: Array<{
        id: string;
        teamId: string;
        title: string;
        description?: string | null;
        deadline?: string | null;
        priority: 'P0' | 'P1' | 'P2' | 'P3' | null;
        originatorAgentId: string;
        originatorTeamId: string;
        createdAt: string;
        currentClaim: {
          holderAgentId: string;
          holderTeamId: string;
          claimedAt: string;
          leaseUntil: string;
        } | null;
        status: 'claimable' | 'claimed' | 'completed' | 'cancelled';
      }>;
    }, { status: 'claimable' | 'claimed' | 'completed' | 'cancelled' }>({
      query: ({ status }) => `/shared-tasks/list?status=${status}`,
      providesTags: ['SharedTasks'],
    }),

    // GET /linear-crossref — distilled Linear snapshot (regen'd from CDP scrapes)
    getLinearCrossref: builder.query<{
      generatedAt: string | null;
      scrapedAt: string | null;
      source: string | null;
      ticketCount: number;
      tickets: Record<string, {
        id: string;
        title: string | null;
        status: string | null;
        assignee: string | null;
        pr: string | null;
        prState: string | null;
        scrapedAt: string;
        runDir: string;
      }>;
    }, void>({
      query: () => '/linear-crossref',
      providesTags: ['Linear'],
    }),

    searchXmem: builder.mutation<{
      teamId: string;
      query: string;
      count: number;
      results: Array<{
        eventId: string;
        agentId: string;
        eventType: string;
        timestamp: string;
        summary: string;
        payload: Record<string, unknown>;
      }>;
    }, { query: string; limit?: number }>({
      query: (body) => ({
        url: '/xmem/search',
        method: 'POST',
        body,
      }),
    }),
  }),
});

// Export hooks for usage in components
export const {
  useGetVersionQuery,
  useGetStatusQuery,
  useGetTopPriorityQuery,
  useGetHeuristicWeightsQuery,
  useUpdateHeuristicWeightsMutation,
  useRecalculatePrioritiesMutation,
  useUpdateTaskMutation,
  useCreateTaskMutation,
  useDeleteTaskMutation,
  useLogDragReorderMutation,
  useGetOnlineLearnerStateQuery,
  useGetWorkspacesQuery,
  useGetCurrentWorkspaceQuery,
  useCreateWorkspaceMutation,
  useSwitchWorkspaceMutation,
  useDeleteWorkspaceMutation,
  useSeedWorkspaceMutation,
  useGetXmemStatusQuery,
  useGetXmemTeamActivityQuery,
  useGetXmemBlockingMeQuery,
  useGetXmemIAmBlockingQuery,
  useGetXmemCurrentFocusQuery,
  useGetSharedTasksQuery,
  useGetLinearCrossrefQuery,
  useSearchXmemMutation,
} = priorityApi;
