'use client';

/**
 * React Query hooks for the admin support dashboard.
 */

import { useQuery, useMutation, useQueryClient, useIsFetching } from '@tanstack/react-query';
import { getCsrfToken } from '@/lib/csrf';
import type { ModelOption } from '@/server/ai/providers/listModels.js';
import type { AdminInboxQuery } from '@/server/schemas/support/admin';
import type { DashboardPrefetchDescriptor } from '@/lib/query/prefetch-registry';

export interface ProviderModelsResponse {
  ok: true;
  models: ModelOption[];
  fetchedAt: string | null;
  stale: boolean;
  error?: string;
}

// ─── Query keys ───────────────────────────────────────────────────────────────

export const adminSupportKeys = {
  inbox: (q: AdminInboxQuery) => ['admin-support', 'inbox', q] as const,
  parent: (type: 'ticket' | 'case', id: string) => ['admin-support', type, id] as const,
  kbList: (q: Record<string, string>) => ['admin-support', 'kb', q] as const,
  kbItem: (id: string) => ['admin-support', 'kb', id] as const,
  settings: () => ['admin-support', 'settings'] as const,
  metrics: (r: { from: string; to: string }) => ['admin-support', 'metrics', r] as const,
  providers: () => ['admin-support', 'providers'] as const,
  providerModels: (id: string) => ['admin-support', 'provider-models', id] as const,
  definitions: () => ['admin-support', 'definitions'] as const,
  definition: (slug: string) => ['admin-support', 'definitions', slug] as const,
};

// ─── Helpers ──────────────────────────────────────────────────────────────────

function qs(params: Record<string, unknown>): string {
  const p = new URLSearchParams();
  for (const [k, v] of Object.entries(params)) {
    if (v !== undefined && v !== null && v !== '') p.set(k, String(v));
  }
  return p.toString();
}

async function jsonOrThrow(res: Response) {
  const data = (await res.json()) as Record<string, unknown>;
  if (!res.ok || !data.ok) {
    throw new Error((data.error as string) ?? `HTTP ${res.status}`);
  }
  return data;
}

export async function fetchAdminSupportInbox(q: AdminInboxQuery) {
  return jsonOrThrow(
    await fetch(`/api/admin/support/inbox?${qs(q as unknown as Record<string, unknown>)}`),
  );
}

export async function fetchAdminSupportSettings() {
  return jsonOrThrow(await fetch('/api/admin/moderation/support-settings'));
}

export async function fetchAdminSupportMetrics(range: { from: string; to: string }) {
  return jsonOrThrow(await fetch(`/api/admin/support/metrics?from=${range.from}&to=${range.to}`));
}

export async function fetchAdminSupportProviders() {
  return jsonOrThrow(await fetch('/api/admin/support/providers'));
}

export async function fetchAdminSupportDefinitions() {
  return jsonOrThrow(await fetch('/api/admin/support/definitions'));
}

export async function fetchAdminSupportDefinition(slug: string) {
  return jsonOrThrow(await fetch(`/api/admin/support/definitions/${slug}`));
}

export interface AdminTicketDetailResponse {
  ok: boolean;
  ticket: {
    id: string;
    status: string;
    assignedAgentId: string | null;
    relatedPurchaseId?: string | null;
    openerId?: string;
    vendorId?: string | null;
  };
  customer: {
    id: string;
    displayName: string | null;
    totalTickets: number;
    openTickets: number;
    purchaseCount: number;
  };
  vendor: {
    id: string;
    businessName: string;
    displayName: string;
    openCaseCount: number;
    activeDealCount: number;
  } | null;
  stats: {
    openedAt: string;
    firstResponseAt: string | null;
    firstResponseMs: number | null;
    avgFirstResponseMs: number | null;
    messageCount: number;
  };
  messages: Array<Record<string, unknown>>;
  attachments: Array<Record<string, unknown>>;
  interventions: Array<Record<string, unknown>>;
  transitions: Array<Record<string, unknown>>;
}

export async function fetchAdminSupportTicketDetail(parentId: string) {
  const res = await fetch(`/api/admin/support/tickets/${parentId}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json() as Promise<AdminTicketDetailResponse>;
}

export interface AdminCaseDetailResponse {
  ok: boolean;
  case: {
    id: string;
    status: string;
    assignedAgentId: string | null;
    purchaseId?: string;
    returnId?: string | null;
    customerId?: string;
    vendorId?: string;
    metadata?: Record<string, unknown>;
  };
  purchase?: {
    totalCents?: number;
  };
  messages: unknown[];
  attachments: unknown[];
  interventions: unknown[];
  transitions: unknown[];
}

export async function fetchAdminSupportCaseDetail(caseId: string) {
  const response = await fetch(`/api/admin/support/cases/${caseId}`);
  return response.json() as Promise<AdminCaseDetailResponse>;
}

export const ADMIN_SUPPORT_PREFETCH_DESCRIPTORS: readonly DashboardPrefetchDescriptor[] = [
  {
    href: '/admin/support',
    queryKey: adminSupportKeys.inbox({
      type: 'all',
      slaBreach: 'any',
      assigned: 'any',
      page: 1,
      pageSize: 25,
      sort: 'sla_soonest',
    }),
    queryFn: () =>
      fetchAdminSupportInbox({
        type: 'all',
        slaBreach: 'any',
        assigned: 'any',
        page: 1,
        pageSize: 25,
        sort: 'sla_soonest',
      }),
  },
  {
    href: '/admin/support/kb',
    queryKey: adminSupportKeys.kbList({}),
    queryFn: () => fetch(`/api/admin/support/kb`).then(jsonOrThrow),
  },
  {
    href: '/admin/support/config',
    queryKey: adminSupportKeys.settings(),
    queryFn: fetchAdminSupportSettings,
  },
  {
    href: '/admin/support/metrics',
    queryKey: adminSupportKeys.metrics({ from: '', to: '' }),
    queryFn: () => fetchAdminSupportMetrics({ from: '', to: '' }),
  },
  {
    href: '/admin/support/definitions',
    queryKey: adminSupportKeys.definitions(),
    queryFn: fetchAdminSupportDefinitions,
  },
] as const;

function csrfHeaders(): HeadersInit {
  return {
    'Content-Type': 'application/json',
    'x-csrf-token': getCsrfToken(),
  };
}

// ─── Inbox ────────────────────────────────────────────────────────────────────

export function useInbox(q: AdminInboxQuery) {
  return useQuery({
    queryKey: adminSupportKeys.inbox(q),
    queryFn: () => fetchAdminSupportInbox(q),
    refetchInterval: 15_000,
    refetchIntervalInBackground: false,
  });
}

export function useInboxIsFetching() {
  return useIsFetching({ queryKey: ['admin-support', 'inbox'] });
}

// ─── Claim ────────────────────────────────────────────────────────────────────

export function useClaim(type: 'ticket' | 'case', id: string, opts?: { onSuccess?: () => void }) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () =>
      fetch(`/api/admin/support/${type}/${id}/claim`, {
        method: 'POST',
        headers: csrfHeaders(),
      }).then(jsonOrThrow),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['admin-support', 'inbox'] });
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.parent(type, id),
      });
      opts?.onSuccess?.();
    },
  });
}

// ─── Assign ───────────────────────────────────────────────────────────────────

export function useAssign(type: 'ticket' | 'case', id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (assignedAgentId: string | null) =>
      fetch(`/api/admin/support/${type}/${id}/assign`, {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify({ assignedAgentId }),
      }).then(jsonOrThrow),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['admin-support', 'inbox'] });
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.parent(type, id),
      });
    },
  });
}

// ─── Post message ─────────────────────────────────────────────────────────────

export function usePostMessage(type: 'ticket' | 'case', id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: {
      text: string;
      visibility: 'public' | 'site_internal';
      attachmentIds?: string[];
    }) =>
      fetch(`/api/admin/support/${type}/${id}/messages`, {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => {
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.parent(type, id),
      });
    },
  });
}

// ─── Close ────────────────────────────────────────────────────────────────────

export function useClose(type: 'ticket' | 'case', id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () =>
      fetch(`/api/admin/support/${type}/${id}/close`, {
        method: 'POST',
        headers: csrfHeaders(),
      }).then(jsonOrThrow),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['admin-support', 'inbox'] });
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.parent(type, id),
      });
    },
  });
}

// ─── Decision ─────────────────────────────────────────────────────────────────

export function useDecide(caseId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch(`/api/admin/cases/${caseId}/decision`, {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['admin-support', 'inbox'] });
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.parent('case', caseId),
      });
    },
  });
}

// ─── KB ───────────────────────────────────────────────────────────────────────

export function useKbList(q: Record<string, string>) {
  return useQuery({
    queryKey: adminSupportKeys.kbList(q),
    queryFn: () => fetch(`/api/admin/support/kb?${qs(q)}`).then(jsonOrThrow),
  });
}

export function useKbCreate() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch('/api/admin/support/kb', {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: ['admin-support', 'kb'] }),
  });
}

export function useKbUpdate(id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch(`/api/admin/support/kb/${id}`, {
        method: 'PATCH',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: ['admin-support', 'kb'] }),
  });
}

export function useKbDelete(id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () =>
      fetch(`/api/admin/support/kb/${id}`, {
        method: 'DELETE',
        headers: csrfHeaders(),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: ['admin-support', 'kb'] }),
  });
}

// ─── Settings ─────────────────────────────────────────────────────────────────

export function useSettings() {
  return useQuery({
    queryKey: adminSupportKeys.settings(),
    queryFn: fetchAdminSupportSettings,
  });
}

export function useSaveSettings() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch('/api/admin/moderation/support-settings', {
        method: 'PATCH',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: adminSupportKeys.settings() }),
  });
}

// ─── Metrics ──────────────────────────────────────────────────────────────────

export function useMetrics(range: { from: string; to: string }) {
  return useQuery({
    queryKey: adminSupportKeys.metrics(range),
    queryFn: () => fetchAdminSupportMetrics(range),
  });
}

// ─── LLM Providers ────────────────────────────────────────────────────────────

export function useProviders() {
  return useQuery({
    queryKey: adminSupportKeys.providers(),
    queryFn: fetchAdminSupportProviders,
  });
}

export function useProviderModels(providerId: string | undefined) {
  return useQuery({
    queryKey: adminSupportKeys.providerModels(providerId ?? ''),
    enabled: !!providerId,
    queryFn: () =>
      fetch(`/api/admin/support/providers/${providerId}/models`).then(
        jsonOrThrow,
      ) as Promise<ProviderModelsResponse>,
    staleTime: 5 * 60 * 1000,
  });
}

export function useRefreshProviderModels(id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () =>
      fetch(`/api/admin/support/providers/${id}/models/refresh`, {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify({}),
      }).then(jsonOrThrow) as Promise<ProviderModelsResponse>,
    onSuccess: () =>
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.providerModels(id),
      }),
  });
}

export function useTestProvider(id: string) {
  return useMutation({
    mutationFn: () =>
      fetch(`/api/admin/support/providers/${id}/test`, {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify({}),
      }).then(jsonOrThrow) as Promise<{
        ok: true;
        data: { ok: boolean; response?: string; error?: string };
      }>,
  });
}

export function useCreateProvider() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch('/api/admin/support/providers', {
        method: 'POST',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: adminSupportKeys.providers() }),
  });
}

export function useUpdateProvider(id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch(`/api/admin/support/providers/${id}`, {
        method: 'PUT',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: adminSupportKeys.providers() }),
  });
}

export function useDeleteProvider(id: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () =>
      fetch(`/api/admin/support/providers/${id}`, {
        method: 'DELETE',
        headers: csrfHeaders(),
      }).then(jsonOrThrow),
    onSuccess: () => void qc.invalidateQueries({ queryKey: adminSupportKeys.providers() }),
  });
}

// ─── Agent Definitions ────────────────────────────────────────────────────────

export function useDefinitions() {
  return useQuery({
    queryKey: adminSupportKeys.definitions(),
    queryFn: fetchAdminSupportDefinitions,
  });
}

export function useDefinition(slug: string) {
  return useQuery({
    queryKey: adminSupportKeys.definition(slug),
    queryFn: () => fetchAdminSupportDefinition(slug),
    enabled: !!slug,
  });
}

export function useUpdateDefinition(slug: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: Record<string, unknown>) =>
      fetch(`/api/admin/support/definitions/${slug}`, {
        method: 'PUT',
        headers: csrfHeaders(),
        body: JSON.stringify(payload),
      }).then(jsonOrThrow),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: adminSupportKeys.definitions() });
      void qc.invalidateQueries({
        queryKey: adminSupportKeys.definition(slug),
      });
    },
  });
}
