import { Effect } from "effect";
import {
  makeSupabaseApiClient,
  type SupabaseApiClientOptions,
  type SupabaseApiClientShape,
  type SupabaseApiConfig,
} from "./internal/client.ts";
import { makeEffectApiClient, type EffectClient } from "./internal/effect-client.ts";
import {
  type GeneratedEffectOperations,
  versionedEffectOperations,
} from "./generated/effect-client.ts";

export type {
  SupabaseApiError,
  SupabaseApiInputErrorSource,
  SupabaseApiRawRequestOptions,
  SupabaseApiRequestOptions,
  SupabaseApiRetryOptions,
} from "./internal/client.ts";
export {
  markSupabaseApiInputErrorAsUserInput,
  SupabaseApiConfigError,
  SupabaseApiInputError,
} from "./internal/client.ts";
export type { SupabaseApiClientOptions, SupabaseApiConfig } from "./internal/client.ts";
export { apiConfigLayer, DEFAULT_SUPABASE_API_URL } from "./config/api-config.layer.ts";
export { ApiConfig } from "./config/api-config.service.ts";

export {
  type OperationDefinition,
  type OperationId,
  type OperationInput,
  type OperationOutput,
  operationDefinitions,
} from "./generated/contracts.ts";
export * from "./generated/contracts.ts";

export const makeApiClient = (config: SupabaseApiConfig = {}, options?: SupabaseApiClientOptions) =>
  Effect.map(makeSupabaseApiClient(config, options), (client) => ({
    ...makeEffectApiClient(client, versionedEffectOperations),
    // Expose the raw-execute escape hatch alongside the typed operations so
    // callers can opt out of strict output decoding without hand-building
    // requests (reuses the client's URL/auth/header/body handling).
    executeRaw: client.executeRaw,
  }));

export type ApiClient = EffectClient<GeneratedEffectOperations> & {
  readonly executeRaw: SupabaseApiClientShape["executeRaw"];
};