/**
 * File picker hooks: list objects (via FILE_OBJECTS_LIST MCP tool) and
 * upload through the org-scoped proxy endpoint. Uploads do not use the
 * browser→S3 presigned PUT path because that would require CORS on every
 * customer bucket; instead the browser POSTs the raw File as the request
 * body (NOT multipart — multipart parsing on the server would buffer
 * the whole payload) and the server streams it through to S3 via
 * `@aws-sdk/lib-storage`.
 */

import { useProjectContext } from "@/sdk";
import { useInfiniteQuery, useMutation } from "@tanstack/react-query";
import { useStudioTools } from "@/lib/studio-tools";
import { KEYS } from "../lib/query-keys";

export interface PickerObject {
  key: string;
  size: number;
  lastModified: string | null;
  publicUrl: string;
}

export interface ListObjectsResponse {
  items: PickerObject[];
  nextCursor: string | null;
}

/**
 * Infinite query over a configured bucket's objects. Page 1 returns the
 * server's "newest first" view (year-prefix probe + lastModified sort);
 * subsequent pages walk the broad prefix via the S3 continuation token.
 * Recent uploads always sit on page 1, so we can keep showing them at
 * the top no matter how deep the user pages.
 */
export function useFilePickerObjects(params: {
  configId: string | null;
  search?: string;
  imageOnly?: boolean;
  enabled?: boolean;
}) {
  const { org } = useProjectContext();
  const studio = useStudioTools();
  const search = params.search?.trim() || undefined;
  const imageOnly = params.imageOnly ?? false;

  return useInfiniteQuery({
    queryKey: KEYS.filePickerObjects(
      org.id,
      params.configId,
      search,
      imageOnly,
    ),
    enabled: params.enabled !== false && !!params.configId,
    staleTime: 30_000,
    initialPageParam: null as string | null,
    queryFn: async ({ pageParam }) => {
      // configId is non-null here: the query is gated by `enabled: !!configId`.
      return await studio.call("FILE_OBJECTS_LIST", {
        configId: params.configId as string,
        cursor: pageParam ?? undefined,
        search,
        // imageOnly only narrows the server-side search scan; it's a no-op on
        // the normal (non-search) listing, which the client filters instead.
        imageOnly: imageOnly || undefined,
      });
    },
    getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
  });
}

export interface UploadResult {
  key: string;
  publicUrl: string;
  contentType: string;
  size: number;
}

/**
 * Upload a file to a configured bucket via the studio proxy endpoint. We
 * don't presign + PUT directly from the browser because that requires
 * per-bucket CORS configuration on every customer bucket (S3, GCS, R2),
 * which is too much friction for a CMS. The proxy streams through studio
 * once and avoids the cross-origin problem entirely.
 *
 * The file is sent as the raw POST body (NOT multipart) so the server
 * can stream it straight to S3 via `@aws-sdk/lib-storage` without ever
 * buffering the full payload — necessary for the 100 MB cap.
 */
export function useFilePickerUpload() {
  const { org } = useProjectContext();

  return useMutation({
    mutationFn: async (input: {
      configId: string;
      file: File;
    }): Promise<UploadResult> => {
      const contentType = input.file.type || "application/octet-stream";

      const response = await fetch(
        `/api/${encodeURIComponent(org.slug)}/file-configs/${encodeURIComponent(input.configId)}/upload?filename=${encodeURIComponent(input.file.name)}`,
        {
          method: "POST",
          headers: { "Content-Type": contentType },
          body: input.file,
        },
      );

      if (!response.ok) {
        const text = await response.text().catch(() => "");
        let message = `${response.status} ${response.statusText}`;
        try {
          const parsed = JSON.parse(text) as { message?: string };
          if (parsed.message) message = parsed.message;
        } catch {
          if (text) message = text.slice(0, 200);
        }
        throw new Error(`Upload failed: ${message}`);
      }

      return (await response.json()) as UploadResult;
    },
  });
}
