import type {
  GetObjectResult,
  GetObjectTooLargeResult,
  HeadObjectResult,
  ListObjectsResult,
  PutObjectResult,
  S3Service,
} from "./s3-service";

/**
 * Org-scoped wrapper around S3Service.
 * Bakes in the org ID so callers don't need to pass it on every call.
 */
export interface BoundObjectStorage {
  /**
   * Read an object, or return a `FILE_TOO_LARGE` marker with a presigned URL
   * when it exceeds `presignWhenLargerThan` (the caller's inline budget).
   */
  getBytesOrPresign(
    key: string,
    opts: { presignWhenLargerThan: number; presignExpiresIn?: number },
  ): Promise<GetObjectResult | GetObjectTooLargeResult>;
  /** Read an object's raw bytes, uncapped. */
  getBytes(key: string): Promise<Uint8Array>;
  put(
    key: string,
    body: string | Uint8Array,
    options?: { contentType?: string },
  ): Promise<PutObjectResult>;
  list(options?: {
    prefix?: string;
    maxKeys?: number;
    continuationToken?: string;
    delimiter?: string;
  }): Promise<ListObjectsResult>;
  delete(key: string): Promise<void>;
  head(key: string): Promise<HeadObjectResult>;
  /** Generate a presigned GET URL for the given key. */
  presignedGetUrl(
    key: string,
    expiresIn?: number,
    opts?: { requireFetchable?: boolean },
  ): Promise<string>;
  /** Generate a presigned PUT URL for the given key. */
  presignedPutUrl(
    key: string,
    expiresIn?: number,
    contentType?: string,
  ): Promise<string>;
}

/**
 * Create an org-scoped object storage wrapper.
 */
export function createBoundObjectStorage(
  s3: S3Service,
  orgId: string,
): BoundObjectStorage {
  return {
    getBytesOrPresign: (key, opts) => s3.getBytesOrPresign(orgId, key, opts),
    getBytes: (key) => s3.getBytes(orgId, key),
    put: (key, body, options) => s3.put(orgId, key, body, options),
    list: (options) => s3.list(orgId, options),
    delete: (key) => s3.delete(orgId, key),
    head: (key) => s3.head(orgId, key),
    presignedGetUrl: (key, expiresIn, opts) =>
      s3.presignedGetUrl(orgId, key, expiresIn, opts),
    presignedPutUrl: (key, expiresIn, contentType) =>
      s3.presignedPutUrl(orgId, key, expiresIn, contentType),
  };
}
