/**
 * TanStack Query hooks for the /v1/tenants/{id}/sources/* endpoints.
 *
 * The hooks are feature-scoped: callers (list, create-dialog,
 * detail-page) pull these and don't talk to fetchWithAuth
 * directly. That way the cache is shared across views and the
 * query keys are predictable.
 *
 * Cache key strategy: ['sources', 'list', tenantId, params] for
 * the list, ['sources', 'detail', tenantId, sourceId] for the
 * detail. tenantId is part of the key (not just the URL) so the
 * list cache for tenant A doesn't leak when the user navigates
 * to tenant B.
 */

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { ApiError, apiGet, apiSend } from '@/lib/api';
import type {
  CreateOrRotateResponse,
  CreateSourceInput,
  ListSourcesResponse,
  Source,
  UpdateSourceInput,
} from './types';

export interface ListSourcesParams {
  q?: string;
  type?: string;
  status?: string;
  limit?: number;
  offset?: number;
}

const KEYS = {
  list: (tenantId: string | undefined, params: ListSourcesParams) =>
    ['sources', 'list', tenantId, params] as const,
  detail: (tenantId: string | undefined, sourceId: string | undefined) =>
    ['sources', 'detail', tenantId, sourceId] as const,
};

function buildListQuery(tenantId: string, params: ListSourcesParams): string {
  const u = new URLSearchParams();
  if (params.q) u.set('q', params.q);
  if (params.type) u.set('type', params.type);
  if (params.status) u.set('status', params.status);
  if (params.limit) u.set('limit', String(params.limit));
  if (params.offset) u.set('offset', String(params.offset));
  const s = u.toString();
  return s
    ? `/v1/tenants/${tenantId}/sources?${s}`
    : `/v1/tenants/${tenantId}/sources`;
}

export function useSourcesList(tenantId: string | undefined, params: ListSourcesParams) {
  return useQuery({
    queryKey: KEYS.list(tenantId, params),
    queryFn: () => apiGet<ListSourcesResponse>(buildListQuery(tenantId as string, params)),
    enabled: Boolean(tenantId),
    staleTime: 15_000,
  });
}

export function useSource(tenantId: string | undefined, sourceId: string | undefined) {
  return useQuery({
    queryKey: KEYS.detail(tenantId, sourceId),
    queryFn: () => apiGet<Source>(`/v1/tenants/${tenantId}/sources/${sourceId}`),
    enabled: Boolean(tenantId) && Boolean(sourceId),
  });
}

export function useCreateSource(tenantId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (input: CreateSourceInput) =>
      apiSend<CreateOrRotateResponse>('POST', `/v1/tenants/${tenantId}/sources`, input),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['sources', 'list', tenantId] });
    },
  });
}

export function useUpdateSource(tenantId: string, sourceId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (input: UpdateSourceInput) =>
      apiSend<Source>('PATCH', `/v1/tenants/${tenantId}/sources/${sourceId}`, input),
    onSuccess: (source) => {
      qc.setQueryData(KEYS.detail(tenantId, sourceId), source);
      void qc.invalidateQueries({ queryKey: ['sources', 'list', tenantId] });
    },
  });
}

export function useSetSourceStatus(tenantId: string, sourceId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (status: 'active' | 'suspended') =>
      apiSend<Source>('POST', `/v1/tenants/${tenantId}/sources/${sourceId}/status`, {
        status,
      }),
    onSuccess: (source) => {
      qc.setQueryData(KEYS.detail(tenantId, sourceId), source);
      void qc.invalidateQueries({ queryKey: ['sources', 'list', tenantId] });
    },
  });
}

export function useRotateSourceSecrets(tenantId: string, sourceId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () =>
      apiSend<CreateOrRotateResponse>(
        'POST',
        `/v1/tenants/${tenantId}/sources/${sourceId}/rotate-secrets`,
        {},
      ),
    onSuccess: (resp) => {
      qc.setQueryData(KEYS.detail(tenantId, sourceId), resp.source);
      void qc.invalidateQueries({ queryKey: ['sources', 'list', tenantId] });
    },
  });
}

export function getErrorMessage(err: unknown): string {
  if (err instanceof ApiError) {
    const body = err.body as { error?: string; message?: string } | null;
    return body?.message ?? body?.error ?? err.message;
  }
  if (err instanceof Error) return err.message;
  return 'Unknown error';
}
